當前位置:
首頁 > 知識 > OpenCV 之 神經網路(一)

OpenCV 之 神經網路(一)

人工神經網路(ANN) 簡稱神經網路(NN),能模擬生物神經系統對物體所作出的交互反應,是由具有適應性簡單單元(稱為神經元)組成的廣泛並行互連網路

1 神經元

1.1 M-P 神經元

如下圖所示,來自其它神經元的信號,$x_1, x_2, ... , x_n $,傳遞過來作為輸入信號,並通過帶權重 ($w_1, w_2, ... , w_n$) 的連接 (connection) 繼續傳遞,

然後神經元的總輸入值 $sum w_i x_i$ 與閾值 $ heta$ 作比較,最後經過激活函數$,f,$產生神經元的輸出: $y = fleft(,sum limits_{i=1}^n {w_i x_i} - heta
ight)$

OpenCV 之 神經網路(一)

1.2 激活函數 (activation function)

理想中,階躍函數可作為激活函數,將輸入值映射為輸出值 「0」 和 「1

實際中,常用 Sigmoid 函數作激活函數, $f(x)=eta ,dfrac{1-e^{-alpha x}}{1+e^{-alpha x}}$

當$,alpha = 1, , eta = 1,$時,該函數把可能在較大範圍內變化的輸入值,「擠壓」 到 (0, 1) 的輸出範圍內。

OpenCV 之 神經網路(一)

2 神經網路

2.1 感知機 (perceptron)

感知機由兩層神經元組成,輸入層接收外界輸入信號,而輸出層則是一個 M-P 神經元。

實際上,感知機可視為一個最簡單的「神經網路」,用它可很容易的實現邏輯與、或、非等簡單運算。

OpenCV 之 神經網路(一)

2.2 層級結構

常見的神經網路,可分為三層:輸入層、隱含層、輸出層。輸入層接收外界輸入,隱層和輸出層負責對信號進行加工,輸出層輸出最終的結果。

以下圖為例:每層神經元與下一層神經元全互連,而同層神經元之間不連接,也不存在跨層連接,這樣的結構稱為「多層前饋神經網路」(multi-layer feedforward neural networks)

OpenCV 之 神經網路(一)

2.3 層數設置

OpenCV 中,設置神經網路層數和神經元個數的函數為 setLayerSizes(InputArray _layer_sizes),則上圖對應的 InputArray 可由如下代碼來構成

// (a) 3層,輸入層神經元個數為 4,隱層的為 6,輸出層的為 4
Mat layerSizes = (Mat_(1,3) << 4,6,4); // (b) 4層,輸入層神經元個數為 4,第一個隱層的為 6,第二個隱層的為 5,輸出層的為 4 Mat layerSizes = (Mat_(1,4) << 4,6,5,4);

如何設置隱層神經元的個數仍是個未決的問題,實際中多採用「試錯法」來調整

3 OpenCV 函數

1) 創建

static Ptr cv::ml::ANN_MLP::create; // 創建空模型

2) 設置參數

// 設置神經網路的層數和神經元數量
virtual void cv::ml::ANN_MLP::setLayerSizes(InputArray _layer_sizes);

// 設置激活函數,目前只支持 ANN_MLP::SIGMOID_SYM
virtual void cv::ml::ANN_MLP::setActivationFunction(int type, double param1 = 0, double param2 = 0);

// 設置訓練方法,默認為 ANN_MLP::RPROP,較常用的是 ANN_MLP::BACKPROP
// 若設為 ANN_MLP::BACKPROP,則 param1 對應 setBackpropWeightScale中的參數,param2 對應 setBackpropMomentumScale 中的參數
virtual void cv::ml::ANN_MLP::setTrainMethod(int method, double param1 = 0, double param2 = 0);
virtual void cv::ml::ANN_MLP::setBackpropWeightScale(double val); // 默認值為 0.1
virtual void cv::ml::ANN_MLP::setBackpropMomentumScale(double val); // 默認值為 0.1

// 設置迭代終止準則,默認為 TermCriteria(TermCriteria::MAX_ITER + TermCriteria::EPS, 1000, 0.01)
virtual void cv::ml::ANN_MLP::setTermCriteria(TermCriteria val);

3) 訓練

// samples - 訓練樣本; layout - 訓練樣本為 「行樣本」 ROW_SAMPLE 或 「列樣本」 COL_SAMPLE; response - 對應樣本數據的分類結果
virtual bool cv::ml::StatModel::train(InputArray samples,int layout,InputArray responses);

4) 預測

// samples,輸入的樣本書數據;results,輸出矩陣,默認不輸出;flags,標識,默認為 0
virtual float cv::ml::StatModel::predict(InputArray samples, OutputArray results=noArray,int flags=0) const;

4 代碼示例

下面是 OpenCV 3.2 中,在「支持向量機」的常式上做的修改,使用 BP 神經網路,實現了和 SVM 相同的分類功能。

OpenCV 中的 支持向量機 (Support Vector Machine),可參見另一篇博文 OpenCV 之 支持向量機 (一)

1 #include
2 #include
3 #include "opencv2/imgcodecs.hpp"
4 #include
5 #include
6
7 using namespace cv;
8 using namespace cv::ml;
9
10 int main
11 {
12 // 512 x 512 零矩陣
13 int width = 512, height = 512;
14 Mat image = Mat::zeros(height, width, CV_8UC3);
15
16 // 訓練樣本
17 float trainingData[6][2] = { { 500, 60 },{ 245, 40 },{ 480, 250 },{ 160, 380 },{400, 25},{55, 400} };
18 float labels[6] = {0,0,0,1,0,1}; // 每個樣本數據對應的輸出
19 Mat trainingDataMat(6, 2, CV_32FC1, trainingData);
20 Mat labelsMat(6, 1, CV_32FC1, labels);
21
22 // BP 模型創建和參數設置
23 Ptr bp = ANN_MLP::create;
24
25 Mat layerSizes = (Mat_(1,3) << 2,6,1); 26 bp->setLayerSizes(layerSizes);
27
28 bp->setTrainMethod(ANN_MLP::BACKPROP,0.1,0.1);
29 bp->setActivationFunction(ANN_MLP::SIGMOID_SYM);
30 bp->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 10000, /*FLT_EPSILON*/1e-6));
31
32 // 保存訓練好的神經網路參數
33 bool trained = bp->train(trainingDataMat,ROW_SAMPLE,labelsMat);
34 if (trained) {
35 bp->save("bp_param");
36 }
37
38 // 創建訓練好的神經網路
39 // Ptr bp = ANN_MLP::load("bp_param");
40
41 // 顯示分類的結果
42 Vec3b green(0, 255, 0), blue(255, 0, 0);
43 for (int i = 0; i < image.rows; ++i) 44 for (int j = 0; j < image.cols; ++j) 45 { 46 Mat sampleMat = (Mat_(1, 2) << j, i); 47 Mat responseMat; 48 bp->predict(sampleMat,responseMat);
49 float response = responseMat.ptr(0)[0];
50 if (response > 0.5)
51 image.at(i, j) = green;
52 else if (response < 0.5) 53 image.at(i, j) = blue;
54 }
55
56 // 畫出訓練樣本數據
57 int thickness = -1;
58 int lineType = 8;
59 circle(image, Point(500, 60), 5, Scalar(255, 255, 255), thickness, lineType);
60 circle(image, Point(245, 40), 5, Scalar(255, 255, 255), thickness, lineType);
61 circle(image, Point(480, 250), 5, Scalar(255, 255, 255), thickness, lineType);
62 circle(image, Point(160, 380), 5, Scalar(0, 0, 255), thickness, lineType);
63 circle(image, Point(400, 25), 5, Scalar(255, 255, 255), thickness, lineType);
64 circle(image, Point(55, 400), 5, Scalar(0, 0, 255), thickness, lineType);
65
66 imwrite("result.png", image); // 保存訓練的結果
67 imshow("BP Simple Example", image);
68 waitKey(0);
69 }

運行結果如下所示:

OpenCV 之 神經網路(一)

注意:OpenCV 3.0 以上版本,相較之前的版本,其中有關機器學習的部分做了較大改動,本人也是踩了很多坑才得到預期的效果。

1) 代碼 #26,必須在 setActivationFunction 之前,否則訓練後的結果多為 nan

2) 代碼 #48,responseMat 為預測的結果。若輸出向量為 1 列,則如 #49 所示,可直接取出預測結果;若輸出向量為 n 列,則可取平均值或者最大值。

同時,根據平均值或最大值,代碼 #50 處的閾值也要相應的改變。

float response = 0;
for (int i=0;i(0)[i];
}

3) 代碼 #39,若已經訓練好神經網路的參數,並將其保存到文件 bp_param 中。

則可將 #23 ~ #36 全部注釋掉,再反注釋掉 #39,這樣,直接載入訓練好的神經網路,便可以使用了。

參考資料:

<機器學習> 周志華 第5章

<統計學習方法> 李航 第1章

OpenCV 3.0 Tutorials -- Neural Networks

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

JavaScript HTML DOM 元素
把angular項目整合到.net mvc中
來吧學學.Net Core之項目文件簡介及配置文件與IOC的使用

TAG:科技優家 |

您可能感興趣

BP神經網路模型:Matlab
當Node.js遇上OpenCV深度神經網路
AKASHA:基於Ethereum+IPFS的去中心化社交網路
快思聰:新的Crestron DM XiODirector網路設備簡化DMNVX網路視音頻系統的部署
兩種網路通信架構:socket與RPC
比WANNA ONE還狂!席捲韓國網路的爆紅限定女團「Celeb Five」!
WiFi網路與RFID物聯網的融合(上)
NYU Courant 二年級博士生薑仲石:網格曲面的神經網路
Python之網路編程
FB秘密衛星網路計劃曝光 想挑戰SpaceX/OneWeb
FB秘密衛星網路計劃曝光 欲挑戰SpaceX/OneWeb
OFF-WHITE × Vapor Street Flyknit 驚現網路!
兒子轉眼就長大:Hinton、LeCun、Bengio 口述神經網路簡史
在 KVM 中測試 IPv6 網路
Netty-網路IO模型
TensorFlow的使用之實現神經網路
Spotlight論文:解耦神經網路DCNet,性能優於標準CNN
哈希日報:OmiseGo與泰國ETDA達成合作關係;ATM網路商Athena Bitcoin即將支持BCH
分散式ExpressNet SDN在盛大雲平台的網路部署實踐
OpenStack-Neutron的網路實現方式-flat網路