Back-propagation Neural Net(BP神经网络)算法实现介绍浅析

(AI还没开始学,神经网络方面的知识缺乏。故暂时不能深入了理解。)

神经网络,可以理解为一个自动机,一个需要学习的自动机。先给其一些学习数据,帮助其建立一个合适的网络。然后就和自动机类似。CodeProject里(http://www.codeproject.com/Articles/13582/Back-propagation-Neural-Net)有这个BP的,不过代码下载有问题。不过网页上的讲解有利于理解这个方面的知识。

BP神经网络,学术点的研究,这里有篇博文(http://blog.csdn.net/sealyao/article/details/6538361)可以看下。

然后继续Wiki之(http://en.wikipedia.org/wiki/Backpropagation):分三个层,然后进行信号传递,之后多个误差反馈。(代码中的forward_pass和backward_pass函数)

Actual algorithm for a 3-layer network (only one hidden layer):

  Initialize the weights in the network (often randomly)
  Do
         For each example e in the training set
              O = neural-net-output(network, e) ; forward pass
              T = teacher output for e
              Calculate error (T - O) at the output units
              Compute delta_wh for all weights from hidden layer to output layer ; backward pass
              Compute delta_wi for all weights from input layer to hidden layer ; backward pass continued
              Update the weights in the network
  Until all examples classified correctly or stopping criterion satisfied
  Return the network

关于BP的问题也有如下:大概意思就是学习收敛较慢和收敛的正确性无法保证。然后需要第三条不能理解。第四条貌似说学习过程需要按比例和正规化的输入。

Limitations

  • The convergence obtained from backpropagation learning is very slow.
  • The convergence in backpropagation learning is not guaranteed.
  • The result may generally converge to any local minimum on the error surface, since stochastic gradient descent exists on a surface which is not flat.
  • Backpropagation learning requires input scaling or normalization.

网上找到一个意大利学生的代码,看懂后添加了注释,并且小修改了下。不过感觉精度总是不够,也不知道是训练问题,还是什么的。

//make函数中的gaset取值时,貌似强制转换会出现运行错误,无法读写。觉得可以用Random生成放进去吧,或者添加&运算符。

代码如下:(懒人专线,0分资源页传送门,http://download.csdn.net/detail/betabin/4245516

/*
Run the program, then load the data file you can download from this page, or choose the option "make data file ".
The program asks you to specify values, a nice learning rate to start with is 0.5 .
Use binary values for the patterns. Weights and biases are given random values automatically.(随机赋值边权重和节点偏差)
Then load the file you just created with the option "load data file".
Then select option "learn from data file", in this way the network will be trained with the data you specified.
When the network is trained successfully, test it with the "compute output" option. Don't forget to save your results before exiting!
If the training seems to don't give any results, specify a lower learning rate (the training process got stuck in a local maximum).
*/

//Backpropagation, 25x25x8 units, binary sigmoid function network
//Written by Thomas Riga, University of Genoa, Italy
//thomas@magister.magi.unige.it

/*
由BetaBin整理、添加注释
时间:2012/04/21
个人主页:http://blog.csdn.net/BetaBin
*/

//#include <iostream.h>
#include <iostream>
//#include <fstream.h>
#include <fstream>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <stdio.h>
#include <float.h>

using namespace std;

double **input,
*hidden,
**output,
**target,
*bias,
**weight_i_h,
**weight_h_o,
*errorsignal_hidden,
*errorsignal_output;

int input_array_size,
hidden_array_size,
output_array_size,
max_patterns,
bias_array_size,
gaset = -2500,
number_of_input_patterns,
pattern,
file_loaded = 0,
ytemp = 0,
ztemp = 0;
double learning_rate,
max_error_tollerance = 0.1;
char filename[128];
//学习效率,用于调整的时候所取的权重
//学习效率低的话,难收敛,学习次数多
//学习效率高的话,容易大范围波动

//下面的宏定义用于初始化BP网络的边权值及偏差(随机赋值)
#define IA   16807
#define IM   2147483647
#define AM   (1.0 / IM)
#define IQ   127773
#define IR   2836
#define NTAB 32
#define NDIV (1+(IM-1) / NTAB)
#define EPS  1.2e-7
#define RNMX (1.0 - EPS)

int compare_output_to_target();		//计算学习程度是否合格(通过误差阈值判断)
void load_data(char *arg);			//从arg文件中加载学习数据,文件格式见make函数
void save_data(char *argres);		//保存现在的BP神经网络数据
void forward_pass(int pattern);		//信号的正向传播,也就是计算输出节点值
void backward_pass(int pattern);	//误差的反向传播,也就是误差反馈,调整各边权值及各节点偏差
void custom();						//由用户输出测试数据
void compute_output_pattern();		//计算输出引导函数,引导输入数据方式
void get_file_name();				//从stdin读入文件名字
float bedlam(long *idum);			//……生成随机浮点值………………范围…………
void learn();						//对上次加载学习数据开始学习
void make();						//学习文件生成引导函数,引导文件格式
void test();						//从学习数据中抽取输入计算输出
void print_data();					//打印向导函数,引导打印方式
void print_data_to_screen();		//打印BP神经网络数据到stdout
void print_data_to_file();			//打印BP神经网络数据到文件
void output_to_screen();			//打印输出结构到stdout
int getnumber();					//从stdin中读取数据一定范围整数
void change_learning_rate();		//重置学习效率
void initialize_net();				//初始化BP网络,空间申请
void clear_memory();				//释放空间

//主函数
//打印菜单提示信息,读取操作,分别调用函数
int main()
{
	cout << "backpropagation network by Thomas Riga, University of Genoa, Italy" << endl;
	for(;;) {
		char choice;
		cout << endl << "1. load data" << endl;
		cout << "2. learn from data" << endl;
		cout << "3. compute output pattern" << endl;
		cout << "4. make new data file" << endl;
		cout << "5. save data" << endl;
		cout << "6. print data" << endl;
		cout << "7. change learning rate" << endl;
		cout << "8. exit" << endl << endl;
		cout << "Enter your choice (1-8)";
		do { choice = getch(); } while (choice != '1' && choice != '2' && choice != '3' && choice != '4' && choice != '5' && choice != '6' && choice != '7' && choice != '8');
		switch(choice) {
			case '1':
				{
					//file_loaded用于判断是否已经加载过学习文件
					//主要用于内存释放,还有学习函数判断是否能学习等
					if (file_loaded == 1) clear_memory();
					get_file_name();
					file_loaded = 1;
					load_data(filename);
				}
				break;
			case '2': learn();
				break;
			case '3': compute_output_pattern();
				break;
			case '4': make();
				break;
			case '5':
				{
					if (file_loaded == 0)
					{
						cout << endl
							<< "there is no data loaded into memory"
							<< endl;
						break;
					}
					cout << endl << "enter a filename to save data to: ";
					cin >> filename;
					save_data(filename);
				}
				break;
			case '6': print_data();
				break;
			case '7': change_learning_rate();
				break;
			case '8': return 0;
		};
	}

	return 0;
}

void initialize_net()
{
	int x;

	//创建输入节点
	input = new double * [number_of_input_patterns];
	if(!input) { cout << endl << "memory problem!"; exit(1); }
	for(x=0; x<number_of_input_patterns; x++)
	{
		input[x] = new double [input_array_size];
		if(!input[x]) { cout << endl << "memory problem!"; exit(1); }
	}

	//创建隐层节点
	hidden = new double [hidden_array_size];
	if(!hidden) { cout << endl << "memory problem!"; exit(1); }

	//创建输出节点
	output = new double * [number_of_input_patterns];
	if(!output) { cout << endl << "memory problem!"; exit(1); }
	for(x=0; x<number_of_input_patterns; x++)
	{
		output[x] = new double [output_array_size];
		if(!output[x]) { cout << endl << "memory problem!"; exit(1); }
	}

	//教师性输出节点
	target = new double * [number_of_input_patterns];
	if(!target) { cout << endl << "memory problem!"; exit(1); }
	for(x=0; x<number_of_input_patterns; x++)
	{
		target[x] = new double [output_array_size];
		if(!target[x]) { cout << endl << "memory problem!"; exit(1); }
	}

	//节点偏差空间
	bias = new double [bias_array_size];
	if(!bias) { cout << endl << "memory problem!"; exit(1); }

	//输入到隐层边权值空间
	weight_i_h = new double * [input_array_size];
	if(!weight_i_h) { cout << endl << "memory problem!"; exit(1); }
	for(x=0; x<input_array_size; x++)
	{
		weight_i_h[x] = new double [hidden_array_size];
		if(!weight_i_h[x]) { cout << endl << "memory problem!"; exit(1); }
	}
	
	//隐层到输出边权值空间
	weight_h_o = new double * [hidden_array_size];
	if(!weight_h_o) { cout << endl << "memory problem!"; exit(1); }
	for(x=0; x<hidden_array_size; x++)
	{
		weight_h_o[x] = new double [output_array_size];
		if(!weight_h_o[x]) { cout << endl << "memory problem!"; exit(1); }
	}

	//隐层节点误差信号空间
	errorsignal_hidden = new double [hidden_array_size];
	if(!errorsignal_hidden) { cout << endl << "memory problem!"; exit(1); }

	//输出节点误差信号空间
	errorsignal_output = new double [output_array_size];
	if(!errorsignal_output) { cout << endl << "memory problem!"; exit(1); }
	
	return;
}

//传说中的学习部分
void learn()
{
	//判断是否加载过学习数据文件
	if (file_loaded == 0)
	{
		cout << endl
			<< "there is no data loaded into memory"
			<< endl;
		return;
	}
	
	cout << endl << "learning..." << endl << "press a key to return to menu" << endl;

	//循环学习
	//至学习完成或者有键盘输入
	register int y;
	while(!kbhit()) {
		for(y=0; y<number_of_input_patterns; y++) {
			forward_pass(y);
			backward_pass(y);
		}
		//每次学习完之后进行学习合格判断
		if(compare_output_to_target()) {
			cout << endl << "learning successful" << endl;
			return;
		}

	}
	
	cout << endl << "learning not successful yet" << endl;
	
	return;
}

void load_data(char *arg) {
	int x, y;
	
	ifstream in(arg);
	if(!in) { cout << endl << "failed to load data file" << endl; file_loaded = 0; return; }
	
	in >> input_array_size;
	in >> hidden_array_size;
	in >> output_array_size;
	in >> learning_rate;
	in >> number_of_input_patterns;
	
	bias_array_size = hidden_array_size + output_array_size;
	
	initialize_net();

	//顺序读入隐层和输出层节点偏差
	for(x=0; x<bias_array_size; x++) in >> bias[x];

	//顺序读入每个输入节点到各隐层节点权值
	for(x=0; x<input_array_size; x++) { 
		for(y=0; y<hidden_array_size; y++) in >> weight_i_h[x][y];
	}

	//顺序读入每个隐层节点到各输出节点权值
	for(x=0; x<hidden_array_size; x++) { 
		for(y=0; y<output_array_size; y++) in >> weight_h_o[x][y];
	}

	//顺序读入每个输入模式
	for(x=0; x<number_of_input_patterns; x++) {
		for(y=0; y<input_array_size; y++) in >> input[x][y];
	}

	//顺序读入每个输入模式对应的教师输出
	for(x=0; x<number_of_input_patterns; x++) {
		for(y=0; y<output_array_size; y++) in >> target[x][y];
	}
	
	in.close();
	cout << endl << "data loaded" << endl;
	
	return;
}


void forward_pass(int pattern)
{
	//中断异常屏蔽?
	_control87 (MCW_EM, MCW_EM);
	
	register double temp=0;
	register int x,y;

	//通过输入层节点计算隐层节点值
	// INPUT -> HIDDEN
	for(y=0; y<hidden_array_size; y++) {
		for(x=0; x<input_array_size; x++) {
			temp += (input[pattern][x] * weight_i_h[x][y]);
		}
		hidden[y] = (1.0 / (1.0 + exp(-1.0 * (temp + bias[y]))));
		temp = 0;
	}

	//通过隐层节点值计算输出节点值
	// HIDDEN -> OUTPUT
	for(y=0; y<output_array_size; y++) {
		for(x=0; x<hidden_array_size; x++) {
			temp += (hidden[x] * weight_h_o[x][y]);
		}
		output[pattern][y] = (1.0 / (1.0 + exp(-1.0 * (temp + bias[y + hidden_array_size]))));
		temp = 0;
	}
	
	return;
}


void backward_pass(int pattern)
{
	register int x, y;
	register double temp = 0;

	//计算输出误差
	// COMPUTE ERRORSIGNAL FOR OUTPUT UNITS
	for(x=0; x<output_array_size; x++) {
		errorsignal_output[x] = (target[pattern][x] - output[pattern][x]);
	}

	//通过输出误差计算隐层误差
	// COMPUTE ERRORSIGNAL FOR HIDDEN UNITS
	for(x=0; x<hidden_array_size; x++) {
		for(y=0; y<output_array_size; y++) { 
			temp += (errorsignal_output[y] * weight_h_o[x][y]);
		}
		errorsignal_hidden[x] = hidden[x] * (1-hidden[x]) * temp;
		temp = 0.0;
	}

	//接下来进行四个反馈调整

	//调整隐层到输出权值
	// ADJUST WEIGHTS OF CONNECTIONS FROM HIDDEN TO OUTPUT UNITS
	double length = 0.0;
	for (x=0; x<hidden_array_size; x++) {
		length += hidden[x]*hidden[x];
	}
	if (length<=0.1) length = 0.1;
	for(x=0; x<hidden_array_size; x++) {
		for(y=0; y<output_array_size; y++) {
			weight_h_o[x][y] += (learning_rate * errorsignal_output[y] * 
				hidden[x]/length);
		}
	}

	//调整输出节点偏差
	// ADJUST BIASES OF HIDDEN UNITS
	for(x=hidden_array_size; x<bias_array_size; x++) {
		bias[x] += (learning_rate * errorsignal_output[x] / length);
	}

	//调整输入到隐层权值
	// ADJUST WEIGHTS OF CONNECTIONS FROM INPUT TO HIDDEN UNITS
	length = 0.0;
	for (x=0; x<input_array_size; x++) {
		length += input[pattern][x]*input[pattern][x];
	}
	if (length<=0.1) length = 0.1;
	for(x=0; x<input_array_size; x++) {
		for(y=0; y<hidden_array_size; y++) {
			weight_i_h[x][y] += (learning_rate * errorsignal_hidden[y] * 
				input[pattern][x]/length);
		}
	}

	//调整隐层节点偏差
	// ADJUST BIASES FOR OUTPUT UNITS
	for(x=0; x<hidden_array_size; x++) {
		bias[x] += (learning_rate * errorsignal_hidden[x] / length);
	}
	return;
}

int compare_output_to_target()
{
	register int y,z;
	register double temp, error = 0.0;
	
	temp = target[ytemp][ztemp] - output[ytemp][ztemp];
	if (temp < 0) error -= temp;
	else error += temp;

	//误差超过阈值,再次学习
	if(error > max_error_tollerance) return 0;

	//遍历所有对应输出,如有超过阈值的则记录坐标,然后退出
	error = 0.0;
	for(y=0; y < number_of_input_patterns; y++) {
		for(z=0; z < output_array_size; z++) {
			temp = target[y][z] - output[y][z];
			
			if (temp < 0) error -= temp;
			else error += temp;
			
			if(error > max_error_tollerance) {
				ytemp = y;
				ztemp = z;
				return 0;
			}
			error = 0.0;
		}
	}
	
	return 1;
}

void save_data(char *argres) {
	int x, y;
	ofstream out;    
	out.open(argres);
	if(!out) { cout << endl << "failed to save file" << endl; return; }
	out << input_array_size << endl;
	out << hidden_array_size << endl;
	out << output_array_size << endl;
	out << learning_rate << endl;
	out << number_of_input_patterns << endl << endl;
	for(x=0; x<bias_array_size; x++) out << bias[x] << ' ';
	out << endl << endl;
	for(x=0; x<input_array_size; x++) {
		for(y=0; y<hidden_array_size; y++) out << weight_i_h[x][y] << ' ';
	}
	out << endl << endl;
	for(x=0; x<hidden_array_size; x++) {
		for(y=0; y<output_array_size; y++) out << weight_h_o[x][y] << ' ';
	}
	out << endl << endl;
	for(x=0; x<number_of_input_patterns; x++) {
		for(y=0; y<input_array_size; y++) out << input[x][y] << ' ';
		out << endl;
	}
	out << endl;
	for(x=0; x<number_of_input_patterns; x++) {
		for(y=0; y<output_array_size; y++) out << target[x][y] << ' ';
		out << endl;
	}
	out.close();
	cout << endl << "data saved" << endl;
	return;
}    

//创建新的学习数据文件
void make()
{
	int x, y, z;
	double inpx, bias_array_size, input_array_size, hidden_array_size, output_array_size;
	char makefilename[128];
	cout << endl << "enter name of new data file: ";
	cin >> makefilename;
	ofstream out;
	out.open(makefilename);
	if(!out) { cout << endl << "failed to open file" << endl; return;}
	cout << "how many input units? ";
	cin >> input_array_size;
	out << input_array_size << endl;
	cout << "how many hidden units? ";
	cin >> hidden_array_size;
	out << hidden_array_size << endl;
	cout << "how many output units? ";
	cin >> output_array_size;
	out << output_array_size << endl;
	bias_array_size = hidden_array_size + output_array_size;
	cout << endl << "Learning rate: ";
	cin >> inpx;
	out << inpx << endl;
	cout << endl << "Number of input patterns: ";
	cin >> z;
	out << z << endl << endl;
	for(x=0; x<bias_array_size; x++) out << (1.0 - (2.0 * bedlam((long*)(gaset)))) << ' ';//貌似强制转换会出现运行错误,无法读写。觉得可以用Random生成放进去吧,或者添加&运算符
	out << endl << endl;
	for(x=0; x<input_array_size; x++) {
		for(y=0; y<hidden_array_size; y++) out << (1.0 - (2.0 * bedlam((long*)(gaset)))) << ' ';
	}
	out << endl << endl;
	for(x=0; x<hidden_array_size; x++) {
		for(y=0; y<output_array_size; y++) out << (1.0 - (2.0 * bedlam((long*)(gaset)))) << ' ';
	}
	out << endl << endl;
	for(x=0; x < z; x++) {
		cout << endl << "input pattern " << (x + 1) << endl;
		for(y=0; y<input_array_size; y++) {
			cout << (y+1) << ": ";
			cin >> inpx;
			out << inpx << ' ';
		}
		out << endl;
	}
	out << endl;
	for(x=0; x < z; x++) {
		cout << endl << "target output pattern " << (x+1) << endl;
		for(y=0; y<output_array_size; y++) {
			cout << (y+1) << ": ";
			cin >> inpx;
			out << inpx << ' ';
		}
		out << endl;
	}
	out.close();
	cout << endl << "data saved, to work with this new data file you first have to load it" << endl;
	return;
}

float bedlam(long *idum)
{
	int xj;
	long xk;
	static long iy=0;
	static long iv[NTAB];
	float temp;

	if(*idum <= 0 || !iy)
	{
		if(-(*idum) < 1)
		{
			*idum = 1 + *idum;
		}
		else
		{
			*idum = -(*idum);
		}
		for(xj = NTAB+7; xj >= 0; xj--)
		{
			xk = (*idum) / IQ;
			*idum = IA * (*idum - xk * IQ) - IR * xk;
			if(*idum < 0)
			{
				*idum += IM;
			}
			if(xj < NTAB)
			{
				iv[xj] = *idum;
			}
		}
		iy = iv[0];
	}

	xk = (*idum) / IQ;
	*idum = IA * (*idum - xk * IQ) - IR * xk;
	if(*idum < 0)
	{
		*idum += IM;
	}
	xj = iy / NDIV;
	iy = iv[xj];
	iv[xj] = *idum;

	if((temp=AM*iy) > RNMX)
	{
		return(RNMX);
	}
	else
	{
		return(temp);
	}
}

//再次计算一组原先的学习数据
//并打印其此次输出模式
void test()
{
	pattern = 0;
	while(pattern == 0) {
		cout << endl << endl << "There are " << number_of_input_patterns << " input patterns in the file," << endl << "enter a number within this range: ";
		pattern = getnumber();
	}
	pattern--;
	forward_pass(pattern);
	output_to_screen();
	return;
}

//打印输出模式到stdout上
void output_to_screen()
{
	int x;
	cout << endl << "Output pattern:" << endl;
	for(x=0; x<output_array_size; x++) {
		cout << endl << (x+1) << ": " << output[pattern][x] << "    binary: ";
		if(output[pattern][x] >= 0.9) cout << "1";
		else if(output[pattern][x]<=0.1) cout << "0";
		else cout << "intermediate value";
	}
	cout << endl;
	return;
}

//从stdin读入一个1到number_of_input_patterns的整数
//读入错误则返回0
int getnumber()
{
	int a, b = 0;
	char c, d[5];
	while(b<4) {
		do { c = getch(); } while (c != '1' && c != '2' && c != '3' && c != '4' && c != '5' && c != '6' && c != '7' && c != '8' && c != '9' && c != '0' && toascii(c) != 13);
		if(toascii(c)==13) break;
		if(toascii(c)==27) return 0;
		d[b] = c;
		cout << c;
		b++;
	}
	d[b] = '\0';
	a = atoi(d);
	if(a < 0 || a > number_of_input_patterns) a = 0;
	return a;
}

void get_file_name()
{
	cout << endl << "enter name of file to load: ";
	cin >> filename;
	return;
}

void print_data()
{
	char choice;
	if (file_loaded == 0)
	{
		cout << endl
			<< "there is no data loaded into memory"
			<< endl;
		return;
	}
	cout << endl << "1. print data to screen" << endl;
	cout << "2. print data to file" << endl;
	cout << "3. return to main menu" << endl << endl;
	cout << "Enter your choice (1-3)" << endl;
	do { choice = getch(); } while (choice != '1' && choice != '2' && choice != '3');
	switch(choice) {
		case '1': print_data_to_screen();
			break;
		case '2': print_data_to_file();
			break;
		case '3': return;
	};
	return;
}


void print_data_to_screen() {
	register int x, y;
	cout << endl << endl << "DATA FILE: " << filename << endl;
	cout << "learning rate: " << learning_rate << endl;
	cout << "input units: " << input_array_size << endl;
	cout << "hidden units: " << hidden_array_size << endl;
	cout << "output units: " << output_array_size << endl;
	cout << "number of input and target output patterns: " << number_of_input_patterns  << endl << endl;
	cout << "INPUT AND TARGET OUTPUT PATTERNS:";
	for(x=0; x<number_of_input_patterns; x++) {
		cout << endl << "input pattern: " << (x+1) << endl;
		for(y=0; y<input_array_size; y++) cout << input[x][y] << "  ";
		cout << endl << "target output pattern: " << (x+1) << endl;
		for(y=0; y<output_array_size; y++) cout << target[x][y] << "  ";
	}
	cout << endl << endl << "BIASES:" << endl;
	for(x=0; x<hidden_array_size; x++) {
		cout << "bias of hidden unit " << (x+1) << ": " << bias[x];
		if(x<output_array_size) cout << "      bias of output unit " << (x+1) << ": " << bias[x+hidden_array_size];
		cout << endl;
	}
	cout << endl << "WEIGHTS:" << endl;
	for(x=0; x<input_array_size; x++) {
		for(y=0; y<hidden_array_size; y++) cout << "i_h[" << x << "][" << y << "]: " << weight_i_h[x][y] << endl;
	}
	for(x=0; x<hidden_array_size; x++) {
		for(y=0; y<output_array_size; y++) cout << "h_o[" << x << "][" << y << "]: " << weight_h_o[x][y] << endl;
	}
	return;
}

void print_data_to_file()
{
	char printfile[128];
	cout << endl << "enter name of file to print data to: ";
	cin >> printfile;
	ofstream out;
	out.open(printfile);
	if(!out) { cout << endl << "failed to open file"; return; }
	register int x, y;
	out << endl << endl << "DATA FILE: " << filename << endl;
	out << "input units: " << input_array_size << endl;
	out << "hidden units: " << hidden_array_size << endl;
	out << "output units: " << output_array_size << endl;
	out << "learning rate: " << learning_rate << endl;
	out << "number of input and target output patterns: " << number_of_input_patterns << endl << endl;
	out << "INPUT AND TARGET OUTPUT PATTERNS:";
	for(x=0; x<number_of_input_patterns; x++) {
		out << endl << "input pattern: " << (x+1) << endl;
		for(y=0; y<input_array_size; y++) out << input[x][y] << "  ";
		out << endl << "target output pattern: " << (x+1) << endl;
		for(y=0; y<output_array_size; y++) out << target[x][y] << "  ";
	}
	out << endl << endl << "BIASES:" << endl;
	for(x=0; x<hidden_array_size; x++) {
		out << "bias of hidden unit " << (x+1) << ": " << bias[x];
		if(x<output_array_size) out << "      bias of output unit " << (x+1) << ": " << bias[x+hidden_array_size];
		out << endl;
	}
	out << endl << "WEIGHTS:" << endl;
	for(x=0; x<input_array_size; x++) {
		for(y=0; y<hidden_array_size; y++) out << "i_h[" << x << "][" << y << "]: " << weight_i_h[x][y] << endl;
	}
	for(x=0; x<hidden_array_size; x++) {
		for(y=0; y<output_array_size; y++) out << "h_o[" << x << "][" << y << "]: " << weight_h_o[x][y] << endl;
	}
	out.close();
	cout << endl << "data has been printed to " << printfile << endl;
	return;
}

void change_learning_rate()
{
	if (file_loaded == 0)
	{
		cout << endl
			<< "there is no data loaded into memory"
			<< endl;
		return;
	}
	cout << endl << "actual learning rate: " << learning_rate << " new value: ";
	cin >> learning_rate;
	return;
}

void compute_output_pattern()
{
	if (file_loaded == 0)
	{
		cout << endl
			<< "there is no data loaded into memory"
			<< endl;
		return;
	}
	char choice;
	cout << endl << endl << "1. load trained input pattern into network" << endl;
	cout << "2. load custom input pattern into network" << endl;
	cout << "3. go back to main menu" << endl << endl;
	cout << "Enter your choice (1-3)" << endl;
	do { choice = getch(); } while (choice != '1' && choice != '2' && choice != '3');
	switch(choice) {
		case '1': test();
			break;
		case '2': custom();
			break;
		case '3': return;
	};
}

void custom()
{
	_control87 (MCW_EM, MCW_EM);
	
	char filename[128];
	register double temp=0;
	register int x,y;

	//测试输入空间
	double *custom_input = new double [input_array_size];
	if(!custom_input)
	{
		cout << endl << "memory problem!";
		return;
	}

	//测试输入结果空间
	double *custom_output = new double [output_array_size];
	if(!custom_output)
	{
		delete [] custom_input;
		cout << endl << "memory problem!";
		return;
	}
	
	cout << endl << endl << "enter file that contains test input pattern: ";
	cin >> filename;
	ifstream in(filename);
	if(!in) { cout << endl << "failed to load data file" << endl; return; }

	//读入测试输入数据,一个模式
	for(x = 0; x < input_array_size; x++) {
		in >> custom_input[x];
	}

	//先计算隐层数据
	for(y=0; y<hidden_array_size; y++) {
		for(x=0; x<input_array_size; x++) {
			temp += (custom_input[x] * weight_i_h[x][y]);
		}
		hidden[y] = (1.0 / (1.0 + exp(-1.0 * (temp + bias[y]))));
		temp = 0;
	}

	//再计算输出结果
	for(y=0; y<output_array_size; y++) {
		for(x=0; x<hidden_array_size; x++) {
			temp += (hidden[x] * weight_h_o[x][y]);
		}
		custom_output[y] = (1.0 / (1.0 + exp(-1.0 * (temp + bias[y + hidden_array_size]))));
		temp = 0;
	}

	//打印输入测试模式
	cout << endl << "Input pattern:" << endl;
	for(x = 0; x < input_array_size; x++) {
		cout << "[" << (x + 1) << ": " << custom_input[x] << "]  ";
	}

	//打印测试结果
	cout << endl << endl << "Output pattern:";
	for(x=0; x<output_array_size; x++) {
		cout << endl << (x+1) << ": " << custom_output[x] << "    binary: ";
		if(custom_output[x] >= 0.9) cout << "1";
		else if(custom_output[x]<=0.1) cout << "0";
		else cout << "intermediate value";
	}
	
	cout << endl;
	delete [] custom_input;
	delete [] custom_output;
	return;
}

void clear_memory()
{
	int x;
	for(x=0; x<number_of_input_patterns; x++)
	{
		delete [] input[x];
	}
	delete [] input;
	delete [] hidden;
	for(x=0; x<number_of_input_patterns; x++)
	{
		delete [] output[x];
	}
	delete [] output;
	for(x=0; x<number_of_input_patterns; x++)
	{
		delete [] target[x];
	}
	delete [] target;
	delete [] bias;
	for(x=0; x<input_array_size; x++)
	{
		delete [] weight_i_h[x];
	}
	delete [] weight_i_h;
	for(x=0; x<hidden_array_size; x++)
	{
		delete [] weight_h_o[x];
	}
	delete [] weight_h_o;
	delete [] errorsignal_hidden;
	delete [] errorsignal_output;
	file_loaded = 0;
	return;
}

    原文作者:神经网络算法
    原文地址: https://blog.csdn.net/betabin/article/details/7485050
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞