////////////////////////////////////////////////////////////////////////////////////////
//
// BP网络解决异或问题实例
//
// 本网络结构为三层BP网络,各层神经元个数可变,更改如下#define即可
//
// 所用函数和矩阵类都定义在functions.h中
//
////////////////////////////////////////////////////////////////////////////////////////
#include "functions.h"
#include <stdlib.h>
#define IN_NUM 2 //输入层神经元个数
#define OUT_NUM 1 //输出层神经元个数
#define HID_NUM 2 //隐藏层神经元个数
#define SAM_NUM 4 //训练样本数
#define LEARN 0.6 //学习系数
#define ERROR 0.008 //网络总误差上限
#define ALPHA 0 //动量系数,用于改进的BP算法,为0则不增加动量项
#define MAXCOUNT 1e5 //迭代训练次数上限
void main()
{
cout<<'\n'<<" (异或问题)BP神经网络结构如下:"<<'\n'<<'\n';
cout<<'\t'<<"输出层神经元个数——"<<OUT_NUM<<endl;
cout<<'\t'<<"隐含层神经元个数——"<<HID_NUM<<endl;
cout<<'\t'<<"输入层神经元个数——"<<IN_NUM<<endl<<endl;
CMatrix teacher (SAM_NUM, IN_NUM+OUT_NUM );//导师信号矩阵
teacher.Set(0,0) = 0;//输入样本00
teacher.Set(0,1) = 0;
teacher.Set(0,2) = 0;//期望输出0
teacher.Set(1,0) = 0;//输入样本01
teacher.Set(1,1) = 1;
teacher.Set(1,2) = 1;//期望输出1
teacher.Set(2,0) = 1;//输入样本10
teacher.Set(2,1) = 0;
teacher.Set(2,2) = 1;//期望输出1
teacher.Set(3,0) = 1;//输入样本11
teacher.Set(3,1) = 1;
teacher.Set(3,2) = 0;//期望输出0
cout<<"导师信号:"<<endl<<'\t'<<"输入 "<<'\t'<<" 输出"<<endl;
teacher.Print(6);
CMatrix w1 (IN_NUM+1 , HID_NUM);//权值矩阵
CMatrix w2 (HID_NUM+1 , OUT_NUM);
w1.Set(0,0) = 0.0513;//输入层到隐藏层权值矩阵初值,也可随机赋值
w1.Set(1,0) = 0.0579;
w1.Set(2,0) = 0.0703;//阈值
w1.Set(0,1) = -0.0291;
w1.Set(1,1) = 0.0999;
w1.Set(2,1) = 0.0939;//阈值
w2.Set(0,0) = 0.0801;//隐藏层到输出层权值矩阵初值,也可随机赋值
w2.Set(1,0) = -0.0605;
w2.Set(2,0) = 0.0109;//阈值
cout<<"输入层到隐藏层权值矩阵初始值:"<<endl;
w1.Print();
cout<<"隐藏层到输出层权值矩阵初始值:"<<endl;
w2.Print();
cout<<endl;
CMatrix input (IN_NUM,1);//样本输入
CMatrix expect (OUT_NUM,1);//期望输出
CMatrix input_ex (IN_NUM+1, 1);//样本输入扩展(在最后列补上-1,用于减去阈值)
CMatrix hidden (HID_NUM , 1);//隐藏层输出
CMatrix hidden_ex (HID_NUM+1, 1);//隐藏层输出扩展(在最后列补上-1,用于减去阈值)
CMatrix output (OUT_NUM , 1);//实际输出
CMatrix error_hidden (HID_NUM , 1);//隐藏层误差
CMatrix error_output (OUT_NUM , 1);//输出层误差
CMatrix delta_w1 (IN_NUM+1 , HID_NUM);//输入层到隐藏层权值矩阵调整值
CMatrix delta_w2 (HID_NUM+1 , OUT_NUM);//隐藏层到输出层权值矩阵调整值
CMatrix last_dw1 (IN_NUM+1 , HID_NUM);//用于保存上次输入层到隐藏层权值矩阵调整值
CMatrix last_dw2 (HID_NUM+1 , OUT_NUM);//用于保存上次隐藏层到输出层权值矩阵调整值
last_dw1.zeros();//置零
last_dw2.zeros();//置零
long turns_count;//迭代训练次数计数
int sample_count;//样本数计数
double error_ave=0;//网络总误差,采用“各样本误差的和”,可自定义
double error_sum=0;
for(turns_count=1;turns_count<MAXCOUNT; turns_count++)//开始迭代训练
{
for(sample_count=1;sample_count<=SAM_NUM;sample_count++)//一轮(每个样本逐次训练)
{
input=teacher.SelectRow(sample_count,1,IN_NUM).transp();
expect=teacher.SelectRow(sample_count,IN_NUM+1,OUT_NUM).transp();
input_ex = input.ColumnExpand();
hidden = w1.transp() * input_ex;
hidden.SigmoidColumn();
hidden_ex=hidden.ColumnExpand();
output = w2.transp() * hidden_ex;
output.SigmoidColumn();//计算实际输出
for(int i=0;i<OUT_NUM;i++)
error_output.Set(0,i) = (*(expect.Getp()+i) - *(output.Getp()+i)) * Derivative(*(output.Getp()+i));
CMatrix wRow (1,OUT_NUM);
for(i=0;i<HID_NUM;i++)
{
wRow=w2.SelectRow(i+1,1,OUT_NUM);
CMatrix deltaw = wRow * error_output;
*(error_hidden.Getp()+i) = *(deltaw.Getp()) * Derivative(*(hidden.Getp()+i));
}
delta_w2=hidden_ex * error_output.transp();
delta_w2.MultipleK(LEARN);
w2=w2+delta_w2+last_dw2;//调整阈值
delta_w1=input_ex * error_hidden.transp();
delta_w1.MultipleK(LEARN);
w1=w1+delta_w1+last_dw1;//调整阈值
last_dw2=delta_w2;
last_dw1=delta_w1;
last_dw2.MultipleK(ALPHA);
last_dw1.MultipleK(ALPHA);//保留上次调整值
}
error_ave=0;
for(sample_count=1;sample_count<=SAM_NUM;sample_count++)// 计算网络总误差
{
input=teacher.SelectRow(sample_count,1,IN_NUM).transp();
expect=teacher.SelectRow(sample_count,IN_NUM+1,OUT_NUM).transp();
input_ex = input.ColumnExpand();
hidden = w1.transp() * input_ex;
hidden.SigmoidColumn();
hidden_ex=hidden.ColumnExpand();
output = w2.transp() * hidden_ex;
output.SigmoidColumn();//实际输出
error_sum=0;
for(int i=0;i<OUT_NUM;i++)
error_sum+=pow(*(output.Getp()+i) - *(expect.Getp()+i),2);
error_sum=error_sum/2;//一个样本的输出误差,采用“各个输出误差平方和/2”
error_ave += error_sum;//网络总误差,采用“各样本误差的和”,可自定义
}
if(error_ave<=ERROR)//若成功
break;
}
cout<<"迭代"<<turns_count<<"次后"<<'\n'<<endl;
cout<<"总误差 E = "<<error_ave<<'\t'<<"成功!"<<'\n'<<endl;
cout<<"输入层到隐藏层权值矩阵:"<<endl;
w1.Print();
cout<<"隐藏层到输出层权值矩阵:"<<endl;
w2.Print();
cout<<"实际输出依次为:"<<endl<<endl;
for(sample_count=1;sample_count<=SAM_NUM;sample_count++)
{
input=teacher.SelectRow(sample_count,1,IN_NUM).transp();
expect=teacher.SelectRow(sample_count,IN_NUM+1,OUT_NUM).transp();
input_ex = input.ColumnExpand();
hidden = w1.transp() * input_ex;
hidden.SigmoidColumn();
hidden_ex=hidden.ColumnExpand();
output = w2.transp() * hidden_ex;
output.SigmoidColumn();
output.Print();
}
}
评论3
最新资源