OpenCV中神经网络的应用
OpenCV中也提供神经网络的算法,下面对其中的一些参数进行介绍。
激活函数
OpenCV中提供三种激活函数,分别是线性激活函数、sigmoid激活函数和高斯激活函数。
我们最常用的也是OpenCV默认的激活函数是sigmoid激活函数,在α=1,β=1的情况下,其输出f(x)的区间是-1到1。
尺寸选择
神经网络的尺寸越大,也即隐藏层越多、神经元越多,训练得到的神经网络就越灵活,能够更好的拟合样本集。但这样神经网络也学习到了样本集的噪音,因此当神经网络的尺寸增加到一定数值后,其精度不再上升,而是开始下降。另外,大尺寸的神经网络训练时间会明显增长,如果需要可以考虑使用PCA:operator()(主成分分析)或者其他类似的降维方法,仅对必要的特征进行训练。
训练算法
OpenCV中有两种神经网络训练算法,一种是经典的随机序列反向传播算法(BACKPROP),另外一种是自适应快速反向传播算法,这也是OpenCV的默认算法。
训练参数CvANN_MLP_TrainParams
CvANN_MLP_TrainParams这个结构体包含神经网络的一些训练参数,针对BACKPROP和RPROP算法的参数是不同的。CvANN_MLP_TrainParams有一个默认构造函数,一般情况下我们使用默认构造函数的参数就好了。
CvANN_MLP_TrainParams::CvANN_MLP_TrainParams()
{
term_crit = cvTermCriteria( CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 1000, 0.01 );
train_method = RPROP;
bp_dw_scale = bp_moment_scale = 0.1;
rp_dw0 = 0.1; rp_dw_plus = 1.2; rp_dw_minus = 0.5;
rp_dw_min = FLT_EPSILON; rp_dw_max = 50.;
}
cvTermCriteria这个结构体主要定义了训练的终止条件,CV_TERMCRIT_ITER 表示迭代到指定次数停止,CV_TERMCRIT_EPS表示误差小于指定值时迭代终止,默认迭代次数1000次,误差0.01,两个参数中有一个达到训练即终止。权值更新率bp_dw_scale和权值更新冲量bp_moment_scale这两个量一般情况设置为默认值0.1就行了。后面的5个参数是针对RPROP算法设置的,具体意义请参考RPROP算法的参考文献。
训练
int CvANN_MLP::train(const Mat& inputs, const Mat& outputs, const Mat& sampleWeights, const Mat& sampleIdx=Mat(), CvANN_MLP_TrainParams params=CvANN_MLP_TrainParams(), int flags=0 );
- inputs:输入矩阵。它存储了所有训练样本的特征。假设所有样本总数为nSamples,而我们提取的特征维数为ndims,则inputs是一个nSamples*ndims的矩阵。
- outputs:输出矩阵。我们实际在训练中,我们知道每个样本所属的种类,假设一共有nClass类。那么我们将outputs设置为一个nSample行nClass列的矩阵,每一行表示一个样本的预期输出结果,该样本所属的那类对应的列设置为1,其他都为0。比如我们需要识别0-9这10个数字,则总的类数为10类,那么样本数字“3”的预期输出为[0,0,1,0,0,0,0,0,0,0];
- sampleWeights:一个在使用RPROP方法训练时才需要的数据,使用RPROP直接设置为Mat()即可。
- sampleIdx:相当于一个遮罩,它指定哪些行的数据参与训练。如果设置为Mat(),则所有行都参与。
- params:训练参数。
- flag:它提供了3个可选项参数,用来指定数据处理的方式,我们可以用逻辑符号去组合它们。UPDATE_WEIGHTS指定用一定的算法去初始化权值矩阵而不是用随机的方法。NO_INPUT_SCALE和NO_OUTPUT_SCALE分别用于禁止输入与输出矩阵的归一化。
识别
float CvANN_MLP::predict(const Mat& inputs, Mat& outputs) const
在进行识别的时候,我们对图像进行特征提取,把它保存在inputs里,通过调用predict函数,我们得到一个输出向量,它是一个1*nClass的行向量,其中每一列说明它与该类的相似程度(0-1之间),也可以说是置信度。我们只用对output求一个最大值,就可得到结果。这个函数的返回值是一个无用的float值,应该忽略。
示例
int main()
{
//Setup the BPNetwork
CvANN_MLP bp;
// Set up BPNetwork's parameters
CvANN_MLP_TrainParams params;
params.train_method=CvANN_MLP_TrainParams::BACKPROP;
params.bp_dw_scale=0.1;
params.bp_moment_scale=0.1;
// Set up training data
float labels[4][2] = {{1.0,-1.0},{-1.0,1.0},{-1.0,1.0},{-1.0,1.0}};
Mat labelsMat(4, 2, CV_32FC1, labels);
float trainingData[4][2] = { {501,10},{255,10}, {501,255},{10,501} };
Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
//Fist param:input feature number Second param:Hidden layer neuron number Third param:output feature number
Mat layerSizes=(Mat_<<span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); background-color: inherit; font-weight: bold;">int>(1,3) << 2,6,2);
//create BPNetwork
bp.create(layerSizes,CvANN_MLP::SIGMOID_SYM);
cout<<"Start train BP network"<<endl;
bp.train(trainingDataMat, labelsMat, Mat(),Mat(), params);
cout<<"End of train BP network"<<endl;
// Data for visual representation
int width = 512, height = 512;
Mat image = Mat::zeros(height, width, CV_8UC3);
Vec3b green(0,255,0), blue (255,0,0);
// Show the decision regions given by the SVM
Mat sampleMat(Mat_<<span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); background-color: inherit; font-weight: bold;">float>(1,2));
Mat responseMat;
cout<<"Starting predict result"<<endl;
for (int i = 0; i < image.rows; ++i)
{
for (int j = 0; j < image.cols; ++j)
{
sampleMat = (Mat_<<span class="datatypes" style="margin: 0px; padding: 0px; border: none; color: rgb(46, 139, 87); background-color: inherit; font-weight: bold;">float>(1,2) << j,i);
bp.predict(sampleMat,responseMat);
Point maxLoc;
double maxVal;
minMaxLoc(responseMat,NULL,&maxVal,NULL,&maxLoc);
int result=maxLoc.x;
if (result == 0)
image.ptr(i)[j] = green;
else
image.ptr(i)[j] = blue;
}
}
cout<<"End of predict result"<<endl;
// Visualize the training data
int thickness = -1;
int lineType = 8;
circle( image, Point(501, 10), 5, Scalar( 0, 0, 0), thickness, lineType);
circle( image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);
circle( image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);
circle( image, Point( 10, 501), 5, Scalar(255, 255, 255), thickness, lineType);
imwrite("result.png", image); // save the image
imshow("BP Simple Example", image); // show it to the user
waitKey(0);
}
结果如下图:
【转载】http://blog.sina.com.cn/s/blog_802a94a20102vj8q.html