OpenCV中神经网络的搭建

由于项目需要,最近一段在学习神经网络的相关知识。项目用到了OpenCV,所以打算用里面的函数实现神经网络。
关于OpenCV中神经网络的实现,资料很少,《学习OpenCV》中更是仅有一小段描述。今天找到了一个小例子,通过查文档基本上弄懂了如何搭起来神经网络的结构。

#include "stdafx.h"
#include "cv.h"
#include "ml.h"
 
// The neural network
CvANN_MLP machineBrain;
 
// Read the training data and train the network.
void trainMachine()
{
	int i;
	//The number of training samples. 
	int train_sample_count;
 
	//The training data matrix. 
	//Note that we are limiting the number of training data samples to 1000 here.
	//The data sample consists of two inputs and an output. That's why 3.
	float td[1000][3];
 
	//Read the training file
	/*
	A sample file contents(say we are training the network for generating 
	the mean given two numbers) would be:
 
	5
	12 16 14
	10 5  7.5
	8  10 9
	5  4  4.5
	12 6  9
 
	*/
	FILE *fin;
	fin = fopen("train.txt", "r");
 
	//Get the number of samples.
	fscanf(fin, "%d", &train_sample_count);
	printf("Found training file with %d samples...\n", train_sample_count);
 
	//Create the matrices
 
	//Input data samples. Matrix of order (train_sample_count x 2)
	CvMat* trainData = cvCreateMat(train_sample_count, 2, CV_32FC1);
 
	//Output data samples. Matrix of order (train_sample_count x 1)
	CvMat* trainClasses = cvCreateMat(train_sample_count, 1, CV_32FC1);
 
	//The weight of each training data sample. We'll later set all to equal weights.
	CvMat* sampleWts = cvCreateMat(train_sample_count, 1, CV_32FC1);
 
	//The matrix representation of our ANN. We'll have four layers.
	CvMat* neuralLayers = cvCreateMat(4, 1, CV_32SC1);
 
	CvMat trainData1, trainClasses1, neuralLayers1, sampleWts1;
 
	cvGetRows(trainData, &trainData1, 0, train_sample_count);
	cvGetRows(trainClasses, &trainClasses1, 0, train_sample_count);
	cvGetRows(trainClasses, &trainClasses1, 0, train_sample_count);
	cvGetRows(sampleWts, &sampleWts1, 0, train_sample_count);
	cvGetRows(neuralLayers, &neuralLayers1, 0, 4);
 
	//Setting the number of neurons on each layer of the ANN
	/* 
	We have in Layer 1: 2 neurons (2 inputs)
	Layer 2: 3 neurons (hidden layer)
	Layer 3: 3 neurons (hidden layer)
	Layer 4: 1 neurons (1 output)
	*/
	cvSet1D(&neuralLayers1, 0, cvScalar(2));
	cvSet1D(&neuralLayers1, 1, cvScalar(3));
	cvSet1D(&neuralLayers1, 2, cvScalar(3));
	cvSet1D(&neuralLayers1, 3, cvScalar(1));
 
	//Read and populate the samples.
	for (i=0;i<train_sample_count;i++)
		fscanf(fin,"%f %f %f",&td[i][0],&td[i][1],&td[i][2]);
 
	fclose(fin);
 
	//Assemble the ML training data.
	for (i=0; i<train_sample_count; i++)
	{
		//Input 1
		cvSetReal2D(&trainData1, i, 0, td[i][0]);
		//Input 2
		cvSetReal2D(&trainData1, i, 1, td[i][1]);
		//Output
		cvSet1D(&trainClasses1, i, cvScalar(td[i][2]));
		//Weight (setting everything to 1)
		cvSet1D(&sampleWts1, i, cvScalar(1));
	}
 
	//Create our ANN.
	machineBrain.create(neuralLayers);//sigmoid 0 0(激活函数的两个参数)
 
	//Train it with our data.	
	machineBrain.train(
		trainData,//输入
		trainClasses,//输出
		sampleWts,//输入项的权值
		0,
		CvANN_MLP_TrainParams(
		cvTermCriteria(
		CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,///类型 CV_TERMCRIT_ITER 和CV_TERMCRIT_EPS二值之一,或者二者的组合
		10000000,//最大迭代次数
		0.00000001//结果的精确性 两次迭代间权值变化量
		),
		CvANN_MLP_TrainParams::BACKPROP,//BP算法
		0.01,//几个可显式调整的参数
		0.05
		)
		);
}
 
// Predict the output with the trained ANN given the two inputs.
void Predict(float data1, float data2)
{
	float _sample[2];
	CvMat sample = cvMat(1, 2, CV_32FC1, _sample);
	float _predout[1];
	CvMat predout = cvMat(1, 1, CV_32FC1, _predout);
	sample.data.fl[0] = data1;
	sample.data.fl[1] = data2;
 
	machineBrain.predict(&sample, &predout);
 
	printf("%f \n",predout.data.fl[0]);
 
}
 
int _tmain(int argc, _TCHAR* argv[])
{
	int wait;
 
	// Train the neural network  with the samples
	trainMachine();
 
	// Now try predicting some values with the trained network
 
 
	Predict(12.0,16.0);// 14
	Predict(10.0,5.0);//  7.5
	Predict(8.0,10.0);// 9
	Predict(5.0,4.0);//  4.5
	Predict(12.0,6.0);//  9
 
	//I'll wait for an integer. :)
	scanf("%d",&wait);
	return 0;
}

一点愚见:
其实搭起来结构不是难事,难的是输入输出的确定。如果神经网络的学习效果不好,首先调整参数,实在不行再调整输入输出。如果还不行,那就换结构。而OpenCV里只实现了BACKPROP和RPROP……闹不好还得找别的类库。
It’s really a tough thing.

做题笔记(续)

还是三道题。粗略地测试了一下,貌似没有大问题。
贴上来。
2008年的复试上机题目
1.素数
输入一个整数,要求输出所有从1到这个整数之间个位为1的素数,如果没有则输出-1(30分)(水题吗)

#include <stdio.h>
#include <math.h>
 
bool judge(int n)
{
	bool flag=true;
	for(int i=2;i<=sqrt(n);i++)
	{
		if(n%i==0)
		{
			flag=false;
			break;
		}
	}
	return flag;
}
 
void main()
{
	int n;
	scanf("%d",&n);
	if(n<=11)
	{
		printf("%d",-1);
	}
	else
	{
		for(int i=11;i<n;i=i+10)
		{
			if(judge(i))
			{
				printf("%d ",i);
			}
		}
	}
}

2.旋转矩阵
任意输入两个9阶以下矩阵,要求判断第二个是否是第一个的旋转矩阵,如果是,输出旋转角度(0、90、180、270),如果不是,输出-1。
要求先输入矩阵阶数,然后输入两个矩阵,每行两个数之间可以用任意个空格分隔。行之间用回车分隔,两个矩阵间用任意的回车分隔。(60分)

#include <stdio.h>
 
void printMatrix(int** a,int n)
{
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			printf("%d ",a[i][j]);
		}
		printf("%s","\n");
	}
}
 
void initMatrix(int** a,int n)
{
	for(int i=0;i<n;i++)
	{
		a[i]=new int [n];
		for(int j=0;j<n;j++)
		{
			scanf("%d",&a[i][j]);
		}
	}
}
 
bool zero(int** a,int** b,int n)
{	
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(a[i][j]==b[i][j])
				continue;
			else			
				return false;			
		}
	}
	return true;
}
 
bool ninety(int** a,int** b,int n)
{	
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(a[i][j]==b[j][n-1-i])
				continue;
			else			
				return false;			
		}
	}
	return true;
}
 
bool reverse(int** a,int** b,int n)
{	
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(a[i][j]==b[n-1-i][n-1-j])
				continue;
			else			
				return false;			
		}
	}
	return true;
}
 
bool counterninety(int** a,int** b,int n)
{	
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			if(a[i][j]==b[n-1-j][i])
				continue;
			else			
				return false;			
		}
	}
	return true;
}
 
void main()
{
	int m=0,n=0;
	scanf("%d",&n);
	scanf("%d",&m);	
	int** m1=new int* [n];
	int** m2=new int* [m];
	initMatrix(m1,n);
	initMatrix(m2,m);
 
	if(m!=n)
	{
		printf("%d",-1);		
	}
	else if(zero(m1,m2,n))
	{
		printf("%d",0);
	}
	else if(ninety(m1,m2,n))
	{
		printf("%d",90);
	}
	else if(reverse(m1,m2,n))
	{
		printf("%d",180);
	}
	else if(counterninety(m1,m2,n))
	{
		printf("%d",270);
	}
	else
	{
		printf("%d",-1);
	}
}

3.字符串匹配
从string.in中读入数据,然后用户输入一个短字符串。要求查找string.in中和短字符串的所有匹配,输出行号、匹配字符串到string.out文件中。匹配时不区分大小写,并且可以有一个用中括号表示的模式匹配。如“aa[123]bb”,就是说aa1bb、aa2bb、aa3bb都算匹配。(60分)

#include <stdio.h>
#include <string.h>
#include <ctype.h> 
//认为[]只能匹配一个字符
char getNewStarter(char *t,int j)
{
	while(t[j]!=']')
		j++;
	return t[j+1];
}
 
bool find(char *s,char *t,int start,int& end)
{	
	int i=start,j=0;
	end=start;
	while(t[j]&&s[i])
	{
		if(tolower(s[i])==tolower(t[j]))
		{
			i++;
			j++;				
		}		
		else if(t[j]=='[')
		{
			if(tolower(s[i])==tolower(getNewStarter(t,j)))//fanjunishere fan[89]jun和[89]fanjun
			{
				while(t[j]!=']')
					j++;
				i++;
				j=j+2;
			}
			else if(getNewStarter(t,j)=='\0')//fanjunishere fanjun[89]
			{
				end=i;
				return true;
			}
			else{//普通情况
				bool flag=false;
				do
				{
					j++;
					if(tolower(t[j])==tolower(s[i]))
					{
						flag=true;					
					}
				}while(t[j]!=']');
				if(!flag)
				{
					return false;				
				}
				else
				{
					i++;
					j++;
				}
			}
		}
		else
		{
			return false;
		}
	}
	if(t[j]=='\0'||t[j]=='[')//doyouknowfanjun fanjun[89]
	{
		end=i;
		return true;
	}
	else
	{
		return false;
	}
}
 
void main()
{
	char input[50];
	scanf("%s",input);
	FILE *fp1,*fp2;	
	if ((fp1=fopen("string.in","r"))==NULL)
        { 
                printf("cannot open file\n");
		return;			
        }
	fp2=fopen("string.out","w");
	char buff[50];
	int line=1;
	while(fgets(buff,50,fp1)>0)
	{
		for(unsigned int i=0;i<strlen(buff);i++)
		{
			int end;
			if(find(buff,input,i,end))
			{
				fprintf(fp2,"%d ",line);
				for(int j=i;j<end;j++)
					fprintf(fp2,"%c",buff[j]);
				fprintf(fp2,"%s","\n");
			}
		}
		line++;
	}
}

总结一下,字符串是重点。