📄 bp.cpp
字号:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
const int N = 20; //学习样本个数
const int IN = 1; //输入层神经元数目
const int HN = 50; //隐层神经元数目
const int OUT = 1; //输出层神经元数目
const double MAX = 0x7fff;
const double EPS = 0.00001;
double P[IN]; //单个样本输入数据
double T[OUT]; //单个样本教师数据
double W[HN][IN];//输入层至隐层权值
double V[OUT][HN];//隐层至输出层权值
double HIN[HN]; //隐层的输入
double OIN[OUT];//输出层的输入
double HOUT[HN];//隐层的输出
double OOUT[OUT];//输出层的输出
double HLIMIT[HN];//隐层的阈值
double OLIMIT[OUT];//输出层的阈值
double ERROR[N];//第m个样本的总误差
double ALPHA;//输出层至隐层的学习效率
double BETA;//隐层至输入层学习效率
double YITA;
double ERROROH[OUT];
double ERRORHI[HN];
double OLDW[HN];
double OLDV[OUT];
int NOW;
double BEFORE;
//定义一个放学习样本的结构
struct DATA
{
double input[IN];
double teach[OUT];
};
struct DATA TrainingData[N];
///////////////////////////
//初始化权、阈值子程序/////
///////////////////////////
void Initial()
{
NOW = 0;
ALPHA = 0.6;
BETA = 0.6;
YITA = 0.6;
srand((unsigned int)time(NULL));
double sign;
int i, j;
//初始化输入-隐层权值矩阵
for(i = 0; i < HN; ++i)
{
for(j = 0; j < IN; ++j)
{
sign = pow(-1, rand()%2);
W[i][j] = sign * rand() / MAX;
}
}
//初始化隐层-输出权值矩阵
for(i = 0; i < OUT; ++i)
{
for(j = 0; j < HN; ++j)
{
sign = pow(-1, rand()%2);
V[i][j] = sign * rand() / MAX;
}
}
//初始化隐层阈值
for(i = 0; i < HN; ++i)
{
sign = pow(-1, rand()%2);
HLIMIT[i] = sign * rand() / MAX;
}
//初始化输出层阈值
for(j = 0; j < OUT; ++j)
{
sign = pow(-1, rand()%2);
OLIMIT[i] = sign * rand() / MAX;
}
}
//得到第m个样本数据
void GetOneData(const int m)
{
int i;
for(i = 0; i < IN; ++i)
{
P[i] = TrainingData[m].input[i];
T[i] = TrainingData[m].teach[i];
}
}
//得到净输入、输出,采用sigmoid函数
void Calculate()
{
int i, j;
double total;
//计算隐层输出
for(i = 0; i < HN; ++i)
{
total = 0;
for(j = 0; j < IN; ++j)
{
total += W[i][j] * P[j];
}
HIN[i] = total - HLIMIT[i];
HOUT[i] = 1.0 / (1.0 + exp(-HIN[i]));
}
//计算输出层输出
for(i = 0; i < OUT; ++i)
{
total = 0;
for(j = 0; j < HN; ++j)
{
total += V[i][j] * HOUT[j];
}
OIN[i] = total - OLIMIT[i];
OOUT[i] = 1.0 / (1.0 + exp(-OIN[i]));
}
}
//计算输出-隐层误差
void ErrorOutToHide(const int m)
{
int i;
double *Abs_Error = new double [OUT];
double Sqr_Error = 0;
for(i = 0; i < OUT; ++i)
{
Abs_Error[i] = (T[i] - OOUT[i]);
Sqr_Error += Abs_Error[i] * Abs_Error[i];
ERROROH[i] = Abs_Error[i] * OOUT[i] * (1 - OOUT[i]);
}
ERROR[m] = Sqr_Error / 2.0;
delete [OUT]Abs_Error;
}
//计算隐层-输入误差
void ErrorHideToIn()
{
int i, j;
double total;
for(i = 0; i < HN; ++i)
{
total = 0;
for(j = 0; j < OUT; ++j)
{
total += ERROROH[j] * V[j][i];
}
ERRORHI[i] = total * HOUT[i] * (1 - HOUT[i]);
}
}
void GetOldError()
{
int i;
for(i = 0; i < HN; ++i)
OLDW[i] = ALPHA * ERRORHI[i];
for(i = 0; i < OUT; ++i)
OLDV[i] = BETA * ERROROH[i];
}
//输出层至隐层权值、阈值调整
void UpdateV()
{
int i, j;
if(NOW == 1)
{
for(i = 0; i < OUT; ++i)
{
for(j = 0; j < HN; ++j)
{
V[i][j] += BETA * ERROROH[i] * HOUT[j];
}
OLIMIT[i] += BETA * ERROROH[i];
}
}
else
{
for(i = 0; i < OUT; ++i)
{
for(j = 0; j < HN; ++j)
{
V[i][j] += (1 - YITA) * BETA * ERROROH[i] * HOUT[j] + YITA * OLDV[i];
}
OLIMIT[i] += BETA * ERROROH[i];
}
}
}
void UpdateW()
{
int i, j;
if(NOW == 1)
{
for(i = 0; i < HN; ++i)
{
for(j = 0; j < IN; ++j)
{
W[i][j] += ALPHA * ERRORHI[i] * P[j];
}
HLIMIT[i] += ALPHA * ERRORHI[i];
}
}
else
{
for(i = 0; i < HN; ++i)
{
for(j = 0; j < IN; ++j)
{
W[i][j] += (1 - YITA) * ALPHA * ERRORHI[i] * P[j] + YITA * OLDW[i];
}
HLIMIT[i] += ALPHA * ERRORHI[i] ;
}
}
}
//计算N个样本全局误差,用于判断收敛
bool GetGlobalError()
{
int i;
double GlobalError = 0;
for(i = 0; i < N; ++i)
GlobalError += ERROR[i];
if(GlobalError < EPS)return true;
return false;
}
//读取训练数据
void GetData()
{
int i, j, k;
for(i = 0; i < N; ++i)
{
for(j = 0; j < IN; ++j)
{
scanf("%lf", &TrainingData[i].input[j]);
}
for(k = 0; k < OUT; ++k)
{
scanf("%lf", &TrainingData[i].teach[k]);
}
}
}
///////////////////////////////////////////////////////
//测试所用函数为y = sin(x)
void GenerateData()
{
// freopen("TrainingData.txt","w",stdout);
srand((unsigned int)time(NULL));
int i;
double x;
for(i = 0; i < N; i++)
{
x = (double)rand() / MAX;
// printf("%lf %lf\n", x, sin(x));
}
}
void GetTest()
{
freopen("in.txt","r", stdin);
double x;
while(scanf("%lf\n", &x)!=EOF)
{
P[0] = x;
Calculate();
printf("\n%lf %lf\n", sin(x), OOUT[0]);
}
}
//////////////////////////////////////////////////////////////////////////
int main()
{
FILE *stream;
int i, j, k;
const int MAXGENERATION = 10000;
// GenerateData();
stream = freopen("TrainingData.txt", "r", stdin);
// freopen("out.txt","w",stdout);
GetData();
Initial();
do
{
++NOW;
// printf("第%d次迭代\n", NOW);
for(i = 0; i < N; ++i)
{
GetOneData(i);
Calculate();
GetOldError();
ErrorOutToHide(i);
ErrorHideToIn();
UpdateW();
UpdateV();
}
} while((!GetGlobalError()) && (NOW != MAXGENERATION));
GetTest();
return 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -