神经网络|【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"
#endifusing namespace Microsoft::MSR::CNTK;
template
using GetEvalProc = void(*)(IEvaluateModel**);
typedef std::pair*> MapEntry;
typedef std::map*> Layer;
int main(int argc, char* argv[])
{
IEvaluateModel *model;
GetEvalF(&model);
return 0;
}
文章图片
GetEvalF在Eavl.h里的声明:
template
void EVAL_API GetEval(IEvaluateModel** peval);
extern "C" EVAL_API void GetEvalF(IEvaluateModel** peval);
extern "C" EVAL_API void GetEvalD(IEvaluateModel** 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)等知识。
正文
(接上边环境配置)
【神经网络|【CNTK】CNTK学习笔记之应用卷积神经网络模型进行数据预测】一定要将调试模式改为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
#include
#include
#include
using namespace Microsoft::MSR::CNTK;
using namespace std;
template
using GetEvalProc = void(*)(IEvaluateModel**);
typedef std::pair*> MapEntry;
typedef std::map*> Layer;
int main(int argc, char* argv[])
{argc = 0;
std::string app = "D:/cntk/Examples/Image/";
std::string path;
IEvaluateModel *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/";
#endifGetEvalF(&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 inDims;
std::map 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 inputs;
int count=0;
for (int i = 0;
i < inDims[inputLayerName];
i++)
{
inputs.push_back(static_cast(i % 255));
count++;
}
cout << count<< endl;
std::vector 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里,这源码里就用了一个循环随机初始化。自己做数据时,直接改代码传进来就可以了。
推荐阅读
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘
- 学无止境,人生还很长