?? main.cpp
字號:
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <iostream>
#define PI 3.14159
#define EPSILON 1E-6
//3層的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
typedef struct tag_bpnnt
{
int in_n; //輸入層神經(jīng)元數(shù)
int hidd_n; //隱層神經(jīng)元數(shù)
int out_n; //輸出層神經(jīng)元
double *in_unit; //輸入層神經(jīng)元
double *hidd_unit; //隱層神經(jīng)元
double *out_unit; //輸出層神經(jīng)元
double *hidd_delta;//隱層誤差
double *out_delta; //輸出層誤差
double *hidd_dfda;
double *out_dfda;
double *target; //目標(biāo)向量
double **in_w; //輸入層權(quán)值
double **hidd_w; //隱層權(quán)值
//前一次結(jié)果(用于迭代)
double **prev_in_w;
double **prev_hidd_w;
}BPNN_t;
//分配1d內(nèi)存
double *bpnn_malloc1d(int n);
//分配2d內(nèi)存
double **bpnn_malloc2d(int m,int n);
//銷毀2d內(nèi)存
void bpnn_mfree2d(double **pmem,int m);
//計(jì)算sigmoid函數(shù)
double sigmoid(double x);
//建立神經(jīng)網(wǎng)絡(luò)
BPNN_t *bpnn_create(int nIn,int nHidden,int nOut);
//銷毀網(wǎng)絡(luò)
void bpnn_destroy(BPNN_t *pNet);
//初始化權(quán)值
void bpnn_init_weight(double **w,int m,int n,int flag);
//前向計(jì)算本層輸出
void bpnn_layerforward(double *layer1,double *layer2,double **conn,int n1,int n2);
//計(jì)算輸出層反傳誤差
void bpnn_out_error(double *delta,double *dfda,double *target,double *output,int nj,double *err);
//計(jì)算隱層反傳誤差
void bpnn_hidd_error(double *delta_h,double *delta_o,double *dfda_h,double *dfda_o,int nh,int nout,double **w_ho,double *h_unit,double*err);
//計(jì)算整個(gè)網(wǎng)絡(luò)輸出
void bpnn_nnforward(BPNN_t *pNet);
//最速下降法訓(xùn)練一次
double bpnn_train_steepest(BPNN_t *pNet,double eta,double **indata,double **targetdata,int np);
//Levenberg-Marquardt訓(xùn)練
double bpnn_train_lm(BPNN_t *pNet,double **indata,double **targetdata,int np,double *lamda);
//gauss-jordan消元法解線性方程組
void gauss_jordan(double *a,double *b,int n);
//交換
void SWAP(double x,double y)
{
if((x)!=(y))
{
x=x+y;
y=x-y;
x=x-y;
}
}
//設(shè)置單位矩陣
static void SetEye(double*mat,int n);
//分配1d內(nèi)存
double *bpnn_malloc1d(int n)
{
double *pout;
pout=(double*)malloc(n*sizeof(double));
return pout;
}
//分配2d內(nèi)存
//m為行數(shù)(組數(shù)),n為列數(shù)(每組個(gè)數(shù))
double **bpnn_malloc2d(int m,int n)
{
double **pout;
int i;
pout=(double**)malloc(m*sizeof(double*));
for(i=0;i<m;i++)
{
pout[i]=(double*)malloc(n*sizeof(double));
}
return pout;
}
//銷毀2d內(nèi)存
void bpnn_mfree2d(double **pmem,int m)
{
int i;
for(i=0;i<m;i++)
{
free(pmem[i]);
}
free(pmem);
pmem=NULL;
}
/**//////////////////////////////////////////////////////////////////////
//初始化權(quán)值
// 參數(shù)
// flag-- 1隨機(jī)初始化 0 全部清0[Page]
// m--上一層神經(jīng)元數(shù)目
// n--下一層神經(jīng)元數(shù)目
/**/////////////////////////////////////////////////////////////////////
void bpnn_init_weight(double **w,int m,int n,int flag)
{
int i,j;
srand((unsigned int)time(NULL));
if(flag) //隨機(jī)生成
{
for(i=0;i<m+1;i++)
for(j=0;j<n+1;j++)
{
//-1.0~1.0的隨機(jī)值
w[i][j]=(double)(rand()%2000)/1000.0-1;
}
}
else //全部清0
{
for(i=0;i<m+1;i++)
for(j=0;j<n+1;j++)
{
w[i][j]=0.0;
}
}
}
//計(jì)算sigmoid函數(shù)
double sigmoid(double x)
{
return 1.0/(1.0+exp(-x));
}
/**//////////////////////////////////////////////////////////////////////
//建立神經(jīng)網(wǎng)絡(luò)
// 參數(shù)
// nIn --輸入層神經(jīng)元數(shù)
// nHidden --隱層神經(jīng)元數(shù)
// nOut --輸出層神經(jīng)元數(shù)
/**//////////////////////////////////////////////////////////////////////
BPNN_t *bpnn_create(int nIn,int nHidden,int nOut)
{
BPNN_t *pNet;
pNet=(BPNN_t*)malloc(sizeof(BPNN_t));
pNet->in_n=nIn;
pNet->hidd_n=nHidden;
pNet->out_n=nOut;
pNet->in_unit=bpnn_malloc1d(nIn+1); //增加1保存閥值分量b
pNet->hidd_unit=bpnn_malloc1d(nHidden+1);
pNet->out_unit=bpnn_malloc1d(nOut+1);
pNet->hidd_delta=bpnn_malloc1d(nHidden+1);
pNet->out_delta=bpnn_malloc1d(nOut+1);
pNet->hidd_dfda=bpnn_malloc1d(nHidden+1);
pNet->out_dfda=bpnn_malloc1d(nOut+1);
pNet->target=bpnn_malloc1d(nOut+1);
pNet->in_unit[0]=1.0; //閥值分量
pNet->hidd_unit[0]=1.0;
//網(wǎng)絡(luò)權(quán)重
pNet->in_w=bpnn_malloc2d(nIn+1,nHidden+1);
pNet->hidd_w=bpnn_malloc2d(nHidden+1,nOut+1);
pNet->prev_in_w=bpnn_malloc2d(nIn+1,nHidden+1);
pNet->prev_hidd_w=bpnn_malloc2d(nHidden+1,nOut+1);
//初始化權(quán)值
bpnn_init_weight(pNet->in_w,nIn,nHidden,1);
bpnn_init_weight(pNet->hidd_w,nHidden,nOut,1);
bpnn_init_weight(pNet->prev_in_w,nIn,nHidden,0);
bpnn_init_weight(pNet->prev_hidd_w,nHidden,nOut,0);
return pNet;
}
//銷毀網(wǎng)絡(luò)
void bpnn_destroy(BPNN_t *pNet)
{
int i;
int n1;
int n2;
n1=pNet->in_n;
n2=pNet->hidd_n;
free(pNet->in_unit);
free(pNet->hidd_unit);
free(pNet->out_unit);
free(pNet->hidd_delta);
free(pNet->out_delta);
free(pNet->hidd_dfda);
free(pNet->out_dfda);
free(pNet->target);
for(i=0;i<n1+1;i++)
{
free(pNet->prev_in_w[i]);
free(pNet->in_w[i]);
}
free(pNet->prev_in_w);
free(pNet->in_w);
for(i=0;i<n2+1;i++)
{
free(pNet->prev_hidd_w[i]);
free(pNet->hidd_w[i]);
}
free(pNet->prev_hidd_w);
free(pNet->hidd_w);
free(pNet);
}
/**//////////////////////////////////////////////////////////////////////
//前向計(jì)算本層的輸出
// 參數(shù)
// layer1 --上一層神經(jīng)元數(shù)組
// layer2 --該層神經(jīng)元數(shù)組
// conn --上層連接權(quán)值
// n1 --上層神經(jīng)元個(gè)數(shù)
// n2 --本層神經(jīng)元個(gè)數(shù)
// 返回
// 更新layer1,layer2
/**//////////////////////////////////////////////////////////////////////
void bpnn_layerforward(double *layer1,double *layer2,double **conn,int n1,int n2)
{
double sum;
int j,k;
layer1[0]=1.0; //以第0個(gè)代表閥值分量
for(j=1;j<n2+1;j++)
{
sum=0.0;
for(k=0;k<n1+1;k++)
{
sum+=conn[k][j]*layer1[k];
}
layer2[j]=sigmoid(sum);
}
}
/**//////////////////////////////////////////////////////////////////////[Page]
//計(jì)算輸出層反傳誤差(單個(gè)樣本)
// 參數(shù)
// delta --反傳誤差向量
// target --目標(biāo)值
// output --網(wǎng)絡(luò)輸出值
// nj --輸出層神經(jīng)元數(shù)
// err --總誤差
// 返回
// 更新err,delta
/**//////////////////////////////////////////////////////////////////////
void bpnn_out_error(double *delta,double *dfda,double *target,double *output,int nj,double*err)
{
int j;
double errsum=0.0;
for(j=0;j<nj+1;j++)
{
//求反傳誤差
delta[j]=output[j]*(1-output[j])*(target[j]-output[j]);
dfda[j]=output[j]*(1-output[j]);
errsum+=fabs(delta[j]);
}
*err=errsum;
}
/**//////////////////////////////////////////////////////////////////////
//計(jì)算隱層反傳誤差(單個(gè)樣本)
// 參數(shù)
// delta_h --隱層反傳誤差向量
// delta_o --輸出層反傳誤差
//------------------ Page 8-----------------------
// dfda_h
// dfda_h
// nh --隱層神經(jīng)元數(shù)目
// nout --輸出層神經(jīng)元數(shù)
// w_ho --隱層到輸出層連接權(quán)值
// h_unit --隱層神經(jīng)元數(shù)組
// err --總誤差[Page]
// 返回
// 更新err,delta_h
/**//////////////////////////////////////////////////////////////////////
void bpnn_hidd_error(double *delta_h,double *delta_o,double *dfda_h,double *dfda_o,int nh,int nout,double **w_ho,double *h_unit,double *err)
{
int j,k;
double hidd,sum,sum2,errsum;
errsum=0.0;
for(j=0;j<nh+1;j++)
{
hidd=h_unit[j];
sum=0.0;
sum2=0.0;
for(k=1;k<nout+1;k++)
{
sum+=delta_o[k]*w_ho[j][k];
sum2+=dfda_o[k]*w_ho[j][k];
}
delta_h[j]=hidd*(1-hidd)*sum;
dfda_h[j]=hidd*(1-hidd)*sum2;
errsum+=fabs(delta_h[j]);
}
*err=errsum;
}
//計(jì)算整個(gè)網(wǎng)絡(luò)輸出
void bpnn_nnforward(BPNN_t *pNet)
{
int nIn,nHidd,nOut;
nIn=pNet->in_n;
nHidd=pNet->hidd_n;
nOut=pNet->out_n;
//計(jì)算輸入層--隱層
//----------------------- Page 9-----------------------
bpnn_layerforward(pNet->in_unit,pNet->hidd_unit,pNet->in_w,nIn,nHidd);
//計(jì)算隱層--輸出層
bpnn_layerforward(pNet->hidd_unit,pNet->out_unit,pNet->hidd_w,nHidd,nOut);
}
/**//////////////////////////////////////////////////////////////////////
//最速下降法的BP網(wǎng)絡(luò)單次訓(xùn)練(全部樣本)
// 參數(shù)
// pNet --已初始化的神經(jīng)網(wǎng)絡(luò)
// eta --最速下降步長
// indata --輸入的樣本數(shù)組
// targetdata--輸出期望
// np --樣本個(gè)數(shù)
// 返回
// 返回更新后的平方誤差
// 更新pNet
/**//////////////////////////////////////////////////////////////////////
double bpnn_train_steepest(BPNN_t *pNet,double eta,double **indata,double **targetdata,int np)
{
int p,i,j,k;
int nIn,nHidd,nOut;
double errout,errh;
double esqrsum,esqr;
double **pGradIn,**pGradH;
nIn=pNet->in_n;
nHidd=pNet->hidd_n;
nOut=pNet->out_n;
pGradIn=bpnn_malloc2d(nIn+1,nHidd+1);
pGradH=bpnn_malloc2d(nHidd+1,nOut+1);
//累加梯度清0
for(j=0;j<=nIn;j++)
for(k=0;k<=nHidd;k++)
{
pGradIn[j][k]=0.0;
}
for(j=0;j<=nHidd;j++)
for(k=0;k<=nOut;k++)
{
pGradH[j][k]=0.0;
}
//----------------------- Page 10-----------------------
for(p=0;p<np;p++)
{
//輸入數(shù)據(jù)
pNet->in_unit[0]=0.0; //無偏移[Page]
for(i=1;i<=nIn;i++)
pNet->in_unit[i]=indata[p][i-1];
for(i=1;i<=nOut;i++)
pNet->target[i]=targetdata[p][i-1];
bpnn_nnforward(pNet);
bpnn_out_error(pNet->out_delta,pNet->out_dfda,pNet->target,pNet->out_unit,nOut,&errout);
bpnn_hidd_error(pNet->hidd_delta,pNet->out_delta,pNet->hidd_dfda,pNet->out_dfda,nHidd,nOut,pNet->hidd_w,pNet->hidd_unit,&errh);
//累加梯度
for(j=0;j<=nIn;j++)
for(k=1;k<=nHidd;k++)
{
pGradIn[j][k]+=pNet->hidd_delta[k]*pNet->in_unit[j];
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -