?? long-bp.cpp
字號:
/*********** universal BP algorithm ***********
*********** dglag@163.com ***********/
#include "iostream.h"
#include "iomanip.h"
#include "stdlib.h"
#include "math.h"
#include "stdio.h"
#include "time.h"
#include "fstream.h"
/* definition of user data */
int N;//學習樣本個數
int M;//神經網絡層數
int note[10];//各層的節點數,層數一般小于10
/*定義一個輸入輸出結構*/
struct individual{
double input[50]; //輸入小于50個
double teach[50]; //輸出小于50個
};
/* definition of global variables */
double W[50][10][50];//權值
double YU[50][10];//閾值
double X[200][10][50];//每個樣本各層的輸出,設樣本數小于200
double a=0.6; //學習效率
struct individual Study_Data[200];//N個學習樣本
double pre_error;//預定誤差
/* function prototype */
void talk();//與用戶交談
void initial();//初始化權、閾值
void GetTrainingData();//從txt中讀取樣本數據
void IO_process();//計算各層輸出
void adjust();//調整權、閾值
double Err_Sum();//計算總的誤差
void savevalue();//儲存權、閾值
/* main program */
int main()
{
double sum_err;
int study=0;//訓練次數
srand(static_cast<unsigned>(time(static_cast<time_t *>(NULL))));//隨機數種子
talk();
GetTrainingData();
initial();
do
{
IO_process();
adjust();
study++;
sum_err=Err_Sum(); //全部樣本全局誤差計算
cout<<"第"<<study<<"次學習的均方誤差為"<<sum_err<<endl;
}while (sum_err>pre_error);
cout<<"網絡已經學習了"<<study<<"次,學習的均方誤差為"<<sum_err<<endl;
savevalue();
return 0;
}
/* 與用戶交談 */
void talk()
{
cout<<"請輸入您需要的神經網絡層數: ";
cin>>M;
cout<<"請輸入您需要的各層的節點數(依次從輸入到輸出層,空格隔開): ";
for(int i=0;i<M;i++)
cin>>note[i];
cout<<"請確保學習樣本已存入“學習樣本.txt”,并輸入學習樣本的個數: ";
cin>>N;
cout<<"請輸入您需要的預定精度: ";
cin>>pre_error;
cout<<"學習中....... "<<endl;
}
/* 初始化權、閾值 */
void initial()
{
double random_0_1;
int q,i,j;
for(q=0;q<M-1;q++)
{
for(i=0;i<note[q+1];i++)
{
for(j=0;j<note[q];j++)
{
random_0_1=rand()/static_cast<double>(RAND_MAX);//[0.0,1]間
W[i][q][j]=2.0*random_0_1-1.0; //初始化所有的權值,[-1.0,1.0]
}
}
}
for(q=0;q<M-1;q++)
{
for(i=0;i<note[q+1];i++)
{
random_0_1=rand()/static_cast<double>(RAND_MAX);//[0.0,1]間
YU[i][q]=2.0*random_0_1-1.0; //閾值初始化 ,[-1.0,1.0]
}
}
}
/* 從txt中讀取樣本數據 */
void GetTrainingData()
{
ifstream GetTrainingData ( "訓練樣本.txt", ios::in );
for(int m=0;m<N;m++)
{
for(int i=0;i<note[0];i++)
{
GetTrainingData>>Study_Data[m].input[i]; //取得輸入數據
}
for(int j=0;j<note[M-1];j++)
{
GetTrainingData>>Study_Data[m].teach[j]; //取得輸出數據
}
}
GetTrainingData.close();
}
/* 計算各層輸出 */
void IO_process()
{
double sigma1;
double sigma2;
int i,m,q,h;
//X[200][10][50]
for(m=0;m<N;m++)
{
for(i=0;i<note[0];i++)
X[m][0][i]=Study_Data[m].input[i];//第0層輸入即輸出
for(q=1;q<M;q++)
{
for(i=0;i<note[q];i++)
{
sigma1=0;
for(h=0;h<note[q-1];h++)
{
sigma1+=X[m][q-1][h]*W[i][q-1][h];
}
sigma2=sigma1-YU[i][q-1];
X[m][q][i]=1.0/(1.0+exp(-sigma2));
}
}
}
}
/* 調整權、閾值 */
void adjust()
{
double delta[200][10][50];
int i,j,k,h,m,q;
for(m=0;m<N;m++)
{
for(h=0;h<note[M-1];h++)
delta[m][M-1][h]=(Study_Data[m].teach[h]-X[m][M-1][h])*X[m][M-1][h]*(1-X[m][M-1][h]);
for(j=M-2;j>0;j--)
{
for(i=0;i<note[j];i++)
{
delta[m][j][i]=0;
for(k=0;k<note[j+1];k++)
delta[m][j][i]+=delta[m][j+1][k]*W[k][j][i]*X[m][j][i]*(1-X[m][j][i]);
}
}
}
for(q=0;q<M-1;q++)
{
for(i=0;i<note[q+1];i++)
{
for(j=0;j<note[q];j++)
{
for(m=0;m<N;m++)
{
W[i][q][j]+=a*delta[m][q+1][i]*X[m][q][j];//權值調整
}
}
}
}
for(q=0;q<M-1;q++)
{
for(i=0;i<note[q+1];i++)
{
for(m=0;m<N;m++)
{
YU[i][q]-=a*delta[m][q+1][i];//閾值調整
}
}
}
}
/* 計算總的誤差 */
double Err_Sum()
{
double s_err=0;
int m,h;
for(m=0;m<N;m++)
{
for(h=0;h<note[M-1];h++)
{
s_err+=(Study_Data[m].teach[h]-X[m][M-1][h])*(Study_Data[m].teach[h]-X[m][M-1][h])/2;
}
}
return s_err;
}
/* 儲存權、閾值 */
void savevalue()
{
ofstream outQuanFile( "權值.txt", ios::out );
ofstream outYuFile( "閾值.txt", ios::out );
outQuanFile<<"W[i][q][j]:第q層j指向i的權,\n";
for(int q=0;q<M-1;q++)
{
for(int j=0;j<note[q];j++)
{
outQuanFile<<"\n"<<"q="<<q<<","<<"j="<<j<<":"<<endl;
for(int i=0;i<note[q+1];i++)
{
outQuanFile<<W[i][q][j]<<" ";
}
}
outQuanFile<<"\n";
}
outYuFile<<"各層的閾值為YU[i][q](第q+1層第i個閾值):\n";
for(int qq=0;qq<M-1;qq++)
{
outYuFile<<"\n"<<"第"<<qq+1<<"層:"<<endl;
for(int ii=0;ii<note[qq+1];ii++)
{
outYuFile<<YU[ii][qq]<<" "; //輸出層閾值寫入文本
}
}
outQuanFile.close();
outYuFile.close();
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -