[TOC]
# 第一課 開講了
# 視頻下載
鏈接: https://pan.baidu.com/s/1snuohzR 密碼: 22g9
## 在線觀看(強烈建議)
https://www.youtube.com/watch?v=Ad0aaUQyasc&feature=youtu.be
WTF?打不開?自己想辦法。1080非常清晰的并且帶字幕!!!

# 講解內容
第一課,主要講研究環境的配置,他需要你有以下基本環境
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

# 安裝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



慢慢等待即可.

# 安裝 cuda8.0-win10
下載地址1
http://www.zifuture.com/fs/jan/cuda_8.0.61_win10.exe
# 1、opencv的配置、imagewatch
## 配置opencv
新建項目


用的是 opencv2.4.10,我們用的是靜態庫,不要用動態庫。依賴已經帶好了。
打開配置管理器

看到已經增加了。

雙擊

我們需要配置,包含目錄及庫目錄

### 在包含目錄中配置
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
```

### 在庫目錄中配置
`D:\cc\lean\lib\opencv2.4.10`

為了讓他能自動識別是win32 還是 x64 這里需要用到變量.
```
D:\cc\lean\lib\opencv2.4.10\$(Platform)\vc$(PlatformToolsetVersion)\staticlib
```

同樣的在做相同的操作.

```
包含目錄
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

這下子證明 opencv已經配置成功。


### 保存 保存 保存 屬性管理器
保存以后下次就不需要再配置了

## 安裝ImageWatch
用于調試時,圖片數據的可視化的查看。十分方便。

直接安裝即可。
```
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變量中的數據。

如果沒有看到可以自己打開,視圖->其他窗口->Image Watch

這樣子就可以查看到矩陣的具體數值.作用非常大
# 2、cc4.0的配置
## 添加系統環境變量
```
D:\cc\cc4.0.3\bin
```

這樣子配置后方便一點.
## 引入cc庫文件

include 是頭文件
lib是庫文件
因為只支持x64 所以win32可以不用配
### 在包含文件中添加
如前面opencv所示的位置.
```
D:\cc\cc4.0.3\include
```

### 在庫目錄中添加
如前面opencv所示的位置.
```
D:\cc\cc4.0.3\lib
```

### 編寫測試代碼
```
#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();
}
```
#### 運行測試

### 保存 保存 保存 屬性管理器
保存以后下次就不需要再配置了

# lstm-ocr 項目源碼分析
建議到這里換成帶有注釋版本的源碼更好地理解
[yzm-lstm.cpp 帶注釋](ymz-lstm.md)
經過前面的配置這個項目打開以后就能直接跑了

## 從何開始閱讀
首先看到 main函數
注釋test()即可訓練
test()為調用模型前向運算
### 訓練
我們找到 LstmDataLayer
```
class LstmDataLayer : public DataLayer{
```
這是輸入層 DataLayer 用于完成 邊訓練邊讀取數據 的過程,類似于lmdb的實現。
非常方便地了解到機器學習過程,數據的變化,如何傳入,等等,深入了解機器學習對數據的預處理。
十分建議在該處下斷點調試,了解圖片如何變為機器能夠理解的數據。
## 查看訓練數據的變化情況
在以前這是不敢相信的,現在我們可以直觀的看到數據變化的過程。對于做研究是非常有幫助的。

這里我們可以看到 圖片變成 負1和正1的過程(歸一化)

### 前向運算
test()函數中,了解網絡如何初始化,加載權重,對圖片預處理后,傳入網絡進行前向運算,最終取出結果。

## 了解一下caffe圖片的格式
平面的形式

## 了解一下opencv的圖片格式
通道式的

# 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);
}
```

# 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) {
}
};
```
訓練時就能夠看到圖片了


彩色圖片

藍色是響應很低的 紅色的響應很高的 跟天氣預報一樣
# 工具類軟件
## everything
非常適合搜索全盤的文件

## depends22_x64
依賴庫查看 依賴在哪里都可以看到
```
D:\cc\tools\depends22_x64
```
可以非常清楚的看到

## GPU-Z
可以非常方便的看到內存占用 顯存占用 頻率 等等信息

- cc框架
- 視頻課程
- 第一課:CC框架簡介
- 第二課:相關基本概念
- 第三課:訓練驗證碼識別
- 第四課:圖像識別、分類、人臉識別
- 第五課:CNN+LSTM少樣本高精度驗證碼識別
- 第六課:總結和展望
- 快速入門
- 常用碼表-label-map
- 目標檢測入門
- 人臉檢測入門
- 重要說明必看
- 雜項
- CC框架使用須知
- 機器學習速成課程 谷歌
- cc4.0視頻教程
- 前言
- cc4.0介紹
- 第一課筆記
- yzm-lstm.cpp 帶注釋
- 第二課筆記
- 眾籌結果公示
- 第三課筆記
- 目標檢測算法之SSD
- 第四課筆記
- 其他資訊
- YOLO3
- 資料
- 性能計算
- 筆記
- cc4.0訓練流程圖
- cc4.0 alexnet 訓練 mnist
- cc4.0 googlenet 訓練 mnist
- cc4.0 加層
- tensorflow -> caffemodel課題筆記
- getnetShape
- RPN
- 記錄
- 數據集
- mnist
- Cifar10
- mtcnn樣本轉ssd樣本易語言代碼