【CNTK】CNTK学习笔记之应用卷积神经网络模型进行数据预测

跳坑里爬了三天,爬不出来了。

VS2013新建CPP工程,把

\cntk\Examples\Evaluation\CPPEvalClient\CPPEvalClient.cpp

拷贝到工程里,在项目上右键->属性,分别设置
VC++目录:
包含目录->\cntk\Include
库目录->\cntk\cntk
链接器
输入->附加依赖项->EvalDll.lib

这里写图片描述

这里写图片描述

代码:

#include "stdafx.h"
#include "Eval.h"
#ifdef _WIN32
#include "Windows.h"
#endif

using namespace Microsoft::MSR::CNTK;
template<typename ElemType>
using GetEvalProc = void(*)(IEvaluateModel<ElemType>**);

typedef std::pair<std::wstring, std::vector<float>*> MapEntry;
typedef std::map<std::wstring, std::vector<float>*> Layer;
int main(int argc, char* argv[])
{
    IEvaluateModel<float> *model;
    GetEvalF(&model);
    return 0;
}

这里写图片描述

GetEvalF在Eavl.h里的声明:

template <typename ElemType>
void EVAL_API GetEval(IEvaluateModel<ElemType>** peval);
extern "C" EVAL_API void GetEvalF(IEvaluateModel<float>** peval);
extern "C" EVAL_API void GetEvalD(IEvaluateModel<double>** peval);

刚爬出坑来,终于找到问题解释,EvalDll.dll必须在vs2013 update5的64位平台下编译,默认32位是不行的。
From Github/Microsoft/CNTK/CNTK Evaluation Overview

The Windows C++ project must be compiled with an x64 target configuration platform, otherwise some issues arise when calling the EvalDLL library. Refer to the Common Pitfalls page for more information.

这里写图片描述

PS.在解决这个问题的三天里,积累了很多解决问题的思路和方法,遇到了很多热心的网友,虽相隔千里,语种不同,但代码和关键字成了共同的语言,这是件很奇妙的事。查看dll依赖的Dependents.exe,lib和dll的原理,github上提问,读英文文档,预编译的 __declspec(dllimport)和 __declspec(dllexport)等知识。

正文
(接上边环境配置)

一定要将调试模式改为Release模式,否则会出现读取字符串错误。原因在此

贴代码:能编译通过就能跑通。还有一个路径问题:

std::string app = “D:/cntk/Examples/Image/”;

我试了试1.5版本的CPU-ONLY的CNTK release版,里面的cntk/cntk里就有一个CPPEvalClient.exe,那个路径放到就不对,把CPPEvalClient.exe拷贝到D:\cntk\Examples\Image里才能正确运行。到了这一版(1.6版),才发现这个源码里是这么写的,在指定了app路径后,modelWorkingDirectory的路径居然是

modelWorkingDirectory = path + "/../../Examples/Image/MNIST/Data/";

app+/../../,也就是app的上两级目录再加后面的Example/Image/MNIST/Data,所以如果放到/cntk/cntk目录下,就找不到路径了。自己在命令行里指定路径时,也必须找Image的同级目录了。


#include "Eval.h"
#ifdef _WIN32
#include "Windows.h"
#endif
#include<io.h>
#include <string.h> 
#include <iostream>
#include <fstream>
using namespace Microsoft::MSR::CNTK;
using namespace std;

template<typename ElemType>
using GetEvalProc = void(*)(IEvaluateModel<ElemType>**);

typedef std::pair<std::wstring, std::vector<float>*> MapEntry;
typedef std::map<std::wstring, std::vector<float>*> Layer;


int main(int argc, char* argv[])
{

    argc = 0;
    std::string app = "D:/cntk/Examples/Image/";
    std::string path;
    IEvaluateModel<float> *model;

#ifdef _WIN32
    path = app.substr(0, app.rfind("\\"));
    const std::string modelWorkingDirectory = path + "/../../Examples/Image/MNIST/Data/";
#else // on Linux
    path = app.substr(0, app.rfind("/"));

    // This relative path assumes launching from CNTK's binary folder, e.g. build/release/bin/
    const std::string modelWorkingDirectory = path + "/../../../Examples/Image/MNIST/Data/";
#endif

    GetEvalF(&model);
    const std::string modelFilePath = modelWorkingDirectory + "../Output/Models/01_OneHidden";

    // Load model with desired outputs
    std::string networkConfiguration;
    // Uncomment the following line to re-define the outputs (include h1.z AND the output ol.z)
    // When specifying outputNodeNames in the configuration, it will REPLACE the list of output nodes 
    // with the ones specified.
    //networkConfiguration += "outputNodeNames=\"h1.z:ol.z\"\n";
    networkConfiguration += "modelPath=\"" + modelFilePath + "\"";
    model->CreateNetwork(networkConfiguration);


    std::map<std::wstring, size_t> inDims;
    std::map<std::wstring, size_t> outDims;
    model->GetNodeDimensions(inDims, NodeGroup::nodeInput);
    model->GetNodeDimensions(outDims, NodeGroup::nodeOutput);

    // Generate dummy input values in the appropriate structure and size
    auto inputLayerName = inDims.begin()->first;
    std::vector<float> inputs;
    int count=0;
    for (int i = 0; i < inDims[inputLayerName]; i++)
    {
        inputs.push_back(static_cast<float>(i % 255));
        count++;
    }
    cout << count<< endl;

    std::vector<float> outputs;

    Layer inputLayer;
    inputLayer.insert(MapEntry(inputLayerName, &inputs));
    Layer outputLayer;
    auto outputLayerName = outDims.begin()->first;
    outputLayer.insert(MapEntry(outputLayerName, &outputs));

    // We can call the evaluate method and get back the results (single layer)...
    model->Evaluate(inputLayer, outputLayer);

    // Output the results
    fprintf(stderr, "Layer '%ls' output:\n", outputLayerName.c_str());
    for (auto& value : outputs)
    {
        fprintf(stderr, "%f\n", value);
    }

    system("pause");
    return 0;
}

运行结果:
这里写图片描述

数据输入时在input里,这源码里就用了一个循环随机初始化。自己做数据时,直接改代码传进来就可以了。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页