[TOC] # 第一课 开讲了 # 视频下载 链接: https://pan.baidu.com/s/1snuohzR 密码: 22g9 ## 在线观看(强烈建议) https://www.youtube.com/watch?v=Ad0aaUQyasc&feature=youtu.be WTF?打不开?自己想办法。1080非常清晰的并且带字幕!!! ![](https://box.kancloud.cn/371fb9c707bdfff6315a6336479f71d1_1140x796.png) # 讲解内容 第一课,主要讲研究环境的配置,他需要你有以下基本环境 1、一台win10 x64系统的电脑 2、一块NVIDIA的显卡,最低980系列,有条件可以买10系列 请按照要求下载并安装工具配置环境,相信安装软件大家都会 1、cuda8.0-win10,如果他安装失败了,一方面可能显卡驱动有问题,另一方面也可能说明你的电脑或者显卡不适合 2、visual studio 2013,我们的开发工具一致的时候最方便 我们是基于visual studio的c++环境来讲解如何基于CC4.0(Caffe)来做深度学习的研究工作 实现更方便,更有用的研究 谢谢大家,Hope 时间定在2018年3月4日 15:40:00开始 # 运行环境 笔者的硬件条件 操作系统 Windows 10 Enterprise 64位 处理器 英特尔 Core i7-8700K @ 3.70GHz 六核 显卡 Nvidia GeForce GTX 1080 Ti ( 11 GB / 技嘉 ) # 下载 lesson1研究环境配置.rar ![](https://box.kancloud.cn/8677f053fdc1696c44fe4e77e17ad375_181x187.png) # 安装vs2013 下载地址1 http://download.microsoft.com/download/0/7/5/0755898A-ED1B-4E11-BC04-6B9B7D82B1E4/VS2013_RTM_ULT_CHS.iso 下载地址2 https://pan.baidu.com/s/1kW9JhKr ![](https://box.kancloud.cn/935dc0bee43971d090b313fca3981b42_460x644.png) ![](https://box.kancloud.cn/1a52ebb09332e0fe76dda3b367ab11e8_460x644.png) ![](https://box.kancloud.cn/dbb2bd6614db8ac13a827f25464b06c6_460x644.png) 慢慢等待即可. ![](https://box.kancloud.cn/e734eae7124a1af4cf543a8ec7298b2b_460x644.png) # 安装 cuda8.0-win10 下载地址1 http://www.zifuture.com/fs/jan/cuda_8.0.61_win10.exe # 1、opencv的配置、imagewatch ## 配置opencv 新建项目 ![](https://box.kancloud.cn/54a2d88d5fb1624a1618df908a3e3fe3_955x660.png) ![](https://box.kancloud.cn/11bc4d971249ea5acc160a277e5ba0ff_685x493.png) 用的是 opencv2.4.10,我们用的是静态库,不要用动态库。依赖已经带好了。 打开配置管理器 ![](https://box.kancloud.cn/8f6f08ae61ea524f590af5e3f1f70e98_716x504.png) 看到已经增加了。 ![](https://box.kancloud.cn/7817ddfd7df287b23b10e8e790210456_225x163.png) 双击 ![](https://box.kancloud.cn/f37a9d16449d308df1ac068b2b6d2a14_252x247.png) 我们需要配置,包含目录及库目录 ![](https://box.kancloud.cn/960f401ad3f7bf8fdc6ffc9935a85f1c_1148x755.png) ### 在包含目录中配置 opencv中有3个目录 ``` D:\cc\lean\include\opencv2.4.10 D:\cc\lean\include\opencv2.4.10\opencv D:\cc\lean\include\opencv2.4.10\opencv2 ``` ![](https://box.kancloud.cn/4a4a88e73d6251cb311b533f73d64495_436x405.png) ### 在库目录中配置 `D:\cc\lean\lib\opencv2.4.10` ![](https://box.kancloud.cn/d3005d923e3781472caf0f116fa15faf_274x116.png) 为了让他能自动识别是win32 还是 x64 这里需要用到变量. ``` D:\cc\lean\lib\opencv2.4.10\$(Platform)\vc$(PlatformToolsetVersion)\staticlib ``` ![](https://box.kancloud.cn/a16ad7b08e8f7b976b56f7fc3f77a166_1033x554.png) 同样的在做相同的操作. ![](https://box.kancloud.cn/a9ba0ca9016f5e23cda2d7460e16b599_300x288.png) ``` 包含目录 D:\cc\lean\include\opencv2.4.10;D:\cc\lean\include\opencv2.4.10\opencv;D:\cc\lean\include\opencv2.4.10\opencv2;$(IncludePath) 库目录 D:\cc\lean\lib\opencv2.4.10\$(Platform)\vc$(PlatformToolsetVersion)\staticlib;$(LibraryPath) ``` ### 编写测试代码 ``` #include <cv.h> #include <highgui.h> using namespace cv; void main(){ Mat im(500, 500, CV_8UC3, Scalar(0, 255)); imshow("test opencv", im); waitKey(); } ``` #### 运行测试 运行起来,发现报错了。需要修改 在静态库中使用MFC ![](https://box.kancloud.cn/056031feb54c490e4dbdf3a1a1d4633d_1269x755.png) 这下子证明 opencv已经配置成功。 ![](https://box.kancloud.cn/95c91afe353362f61db2ad4e5676d61c_430x321.png) ![](https://box.kancloud.cn/ddf0171b0b67a84fe2cc454b6bb1afe2_886x593.png) ### 保存 保存 保存 属性管理器 保存以后下次就不需要再配置了 ![](https://box.kancloud.cn/8c23367b28c24f17b29115bbe6edcd6c_246x161.png) ## 安装ImageWatch 用于调试时,图片数据的可视化的查看。十分方便。 ![](https://box.kancloud.cn/dde3abf5bac414c4047747196ee2e1e1_320x85.png) 直接安装即可。 ``` D:\cc\tools\ImageWatch\ImageWatch.vsix ``` ### 编写测试代码 ``` #include <cv.h> #include <highgui.h> using namespace cv; void main(){ Mat im = imread("test.png"); imshow("test opencv", im); waitKey(); } ``` #### 运行测试 如图所示 下断点,然后执行过程。即可查看到im变量中的数据。 ![](https://box.kancloud.cn/2a750991ba5327f38446c2bbc8f93bd0_1106x604.png) 如果没有看到可以自己打开,视图->其他窗口->Image Watch ![](https://box.kancloud.cn/bf2ba4143ba7099eb0e2dfc15210702c_1182x763.png) 这样子就可以查看到矩阵的具体数值.作用非常大 # 2、cc4.0的配置 ## 添加系统环境变量 ``` D:\cc\cc4.0.3\bin ``` ![](https://box.kancloud.cn/419e41a86e244ecb63dd4285b63cafe9_1144x650.png) 这样子配置后方便一点. ## 引入cc库文件 ![](https://box.kancloud.cn/b50916776e3516451c3cdeb1720456f3_218x144.png) include 是头文件 lib是库文件 因为只支持x64 所以win32可以不用配 ### 在包含文件中添加 如前面opencv所示的位置. ``` D:\cc\cc4.0.3\include ``` ![](https://box.kancloud.cn/664300e0f41f4d8910e766c78b3dff3b_419x183.png) ### 在库目录中添加 如前面opencv所示的位置. ``` D:\cc\cc4.0.3\lib ``` ![](https://box.kancloud.cn/02b823164a0aeddce8cb45200782ac9e_425x148.png) ### 编写测试代码 ``` #include <cv.h> #include <highgui.h> #include <cc_utils.h> #pragma comment(lib, "libcaffe.lib") using namespace cv; using namespace cc; void main(){ printf("%s, %X\n", getCCVersionString(), getCCVersionInt()); Mat im(500, 500, CV_8UC3, Scalar(0, 255)); imshow("test opencv", im); waitKey(); } ``` #### 运行测试 ![](https://box.kancloud.cn/ef8aa681436324a609402522c3f88bbc_500x276.png) ### 保存 保存 保存 属性管理器 保存以后下次就不需要再配置了 ![](https://box.kancloud.cn/8c23367b28c24f17b29115bbe6edcd6c_246x161.png) # lstm-ocr 项目源码分析 建议到这里换成带有注释版本的源码更好地理解 [yzm-lstm.cpp 带注释](ymz-lstm.md) 经过前面的配置这个项目打开以后就能直接跑了 ![](https://box.kancloud.cn/decbfe4c0b43308284fd06d118c8a1ef_1679x697.png) ## 从何开始阅读 首先看到 main函数 注释test()即可训练 test()为调用模型前向运算 ### 训练 我们找到 LstmDataLayer ``` class LstmDataLayer : public DataLayer{ ``` 这是输入层 DataLayer 用于完成 边训练边读取数据 的过程,类似于lmdb的实现。 非常方便地了解到机器学习过程,数据的变化,如何传入,等等,深入了解机器学习对数据的预处理。 十分建议在该处下断点调试,了解图片如何变为机器能够理解的数据。 ## 查看训练数据的变化情况 在以前这是不敢相信的,现在我们可以直观的看到数据变化的过程。对于做研究是非常有帮助的。 ![](https://box.kancloud.cn/a7c75ea8a74f5e080a3a953f90102d6c_1059x672.png) 这里我们可以看到 图片变成 负1和正1的过程(归一化) ![](https://box.kancloud.cn/94be4007df157918e3b67dc138138715_1419x666.png) ### 前向运算 test()函数中,了解网络如何初始化,加载权重,对图片预处理后,传入网络进行前向运算,最终取出结果。 ![](https://box.kancloud.cn/4c6b746c4af630571849647fe9a17bb8_1491x552.png) ## 了解一下caffe图片的格式 平面的形式 ![](https://box.kancloud.cn/5c69722277c78b0c945c9be8b7a6bf85_699x693.png) ## 了解一下opencv的图片格式 通道式的 ![](https://box.kancloud.cn/57af96ae695e29ca64af20ee5d32811d_521x452.png) # 3、4.0使用,一个训练任务 这就是一个训练的任务过程 ``` void main(){ printf("version: %s, %X\n", getCCVersionString(), getCCVersionInt()); //设置当前目录 SetCurrentDirectoryA("train"); //安装注册器 installRegister(); /* 注册一个layer cpp_param { type: "LstmDataLayer" param_str: "batch_size: 16; width: 150; height: 60; num: 6" } 指的 LstmDataLayer 的名字 大小写不能错 */ INSTALL_LAYER(LstmDataLayer); //INSTALL_LAYER(WatcherLayer); // Forward 前向运算 或者叫推理 //test(); //加载求解器 WPtr<Solver> solver = loadSolverFromPrototxt("solver-gpu.prototxt"); //solver->Restore("models/blstmctc_iter_12111.solverstate"); solver->Solve(); } ``` # 4、4.0使用,一个前向运算 test() 函数即为 前向运算的过程。请阅读源码 ``` void test(){ //读取图片的 PaVfiles vfs; paFindFiles("data-test", vfs, "*.png"); //打乱图片 std::random_shuffle(vfs.begin(), vfs.end()); //只取5个图片来测试 if (vfs.size() > 5) vfs.erase(vfs.begin() + 5, vfs.end()); //构建一个大图 把多个图片合成一起处理 Mat big(60, vfs.size()*150, CV_8UC3); for (int i = 0; i < vfs.size(); ++i){ resize(imread(vfs[i]), big(Rect(i * 150, 0, 150, 60)), Size(150, 60)); } //WPtr智能指针 自动释放net WPtr<Net> net = loadNetFromPrototxt("deploy.prototxt"); //把训练的权重复制进去 net->copyTrainedParamFromFile("models/blstmctc_iter_6044.caffemodel"); //复制图片 Mat show = big.clone(); //转换为正1负1 训练的时候就处理了.所以这里也需要处理.这是归一化的过程. big.convertTo(big, CV_32F, 1 / 127.5, -1); /* 输入的数据 net->input_blob(0) 指的是下面的内容 input: "data" input_shape { dim: 1 dim: 3 dim: 60 dim: 150 } */ Blob* input = net->input_blob(0); // 这里重置了输入图片的大小.因为我们输入的是5张图片的宽度. // n 批次 c 通道 h 高度 w 宽度 顺序不要搞错了 input->Reshape(1, 3, big.rows, big.cols); //自动算一遍网络的参数 net->Reshape(); //把通道式的图片数据变成caffe用的平面形式的数据 Mat ms[3]; float* ptr = input->mutable_cpu_data(); for (int i = 0; i < 3; ++i){ ms[i] = Mat(input->height(), input->width(), CV_32F, ptr); ptr += input->width()*input->height(); } split(big, ms); //前向运算 net->Forward(); //输出的结果 Blob* out = net->output_blob(0); int c = 37; int prev = 0; string r; float* result = out->mutable_cpu_data(); for (int i = 0; i < out->num(); ++i){ int label = std::max_element(result, result + c) - result; if (label != prev && label != 0){ printf("%c", toChar(label)); r += toChar(label); } result += c; prev = label; } printf("\n"); putText(show, r, Point(10, 60), 1, 1, Scalar(0, 255), 1); imshow("big", show); waitKey(); imwrite("show.png", show); exit(0); } ``` ![](https://box.kancloud.cn/058cce1a3e54544a80b058ba518f9af9_759x189.png) # 5、4.0使用,写一个运行状态的layer train.prototxt 增加一个layer ``` layer { name: "watcher" type: "CPP" bottom: "conv1" include { phase: TRAIN } cpp_param { type: "WatcherLayer" } } ``` 源码中添加一个类 ``` class WatcherLayer : public AbstractCustomLayer{ public: SETUP_LAYERFUNC(WatcherLayer); virtual void setup(const char* name, const char* type, const char* param_str, int phase, Blob** bottom, int numBottom, Blob** top, int numTop) { } virtual void forward(Blob** bottom, int numBottom, Blob** top, int numTop) { Blob* conv1 = bottom[0]; const float* ptr = conv1->cpu_data(); int height = conv1->height(); int width = conv1->width(); Mat im(height, width, CV_32F, (void*)ptr); imshow("im", im); waitKey(1); } virtual void reshape(Blob** bottom, int numBottom, Blob** top, int numTop) { } }; ``` 训练时就能够看到图片了 ![](https://box.kancloud.cn/e02bb279e5e786cacb7826ee501b4f4e_993x519.png) ![](https://box.kancloud.cn/1f915adc4c249c3a6f7a5ee2a37e21e7_579x329.png) 彩色图片 ![](https://box.kancloud.cn/d9f19f93700a6202031dfe6c43fdea2a_1516x677.png) 蓝色是响应很低的 红色的响应很高的 跟天气预报一样 # 工具类软件 ## everything 非常适合搜索全盘的文件 ![](https://box.kancloud.cn/26934958d7094460bdc077bfc58827b6_721x393.png) ## depends22_x64 依赖库查看 依赖在哪里都可以看到 ``` D:\cc\tools\depends22_x64 ``` 可以非常清楚的看到 ![](https://box.kancloud.cn/4fc1ec1bfe6cc581b07217d452464656_938x896.png) ## GPU-Z 可以非常方便的看到内存占用 显存占用 频率 等等信息 ![](https://box.kancloud.cn/5b1bd16ed8959a32b8b76d9a79a1cd5e_400x494.png)