📄 bp.txt
字号:
#include "stdafx.h"
#include <string>
#include <cmath>
#include<ctime>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
const int N = 8; //样本数量
const int d = 4; //样本特征维数
const int nH = 3; //隐含层元素个数,包括阙值
const int c = 1; //每个样本的目标值都是1维的
const double error_limit = 0.01; //迭代结束的误差
const double rate = 0.05; //学习率
const double momentum = 0.9; //冲量大小
//
class weight{
public:
double samples[N][d]; //N个样本的d维特征空间
double weight_HI[nH][d]; //输入层到隐含层权值
double weight_OH[c][nH]; //隐含层到输出层权值
double old_weight_HI[nH][d]; //前一时刻输入层和隐含层权重的变化率
double old_weight_OH[c][nH]; //前一时刻输出层和隐含层权重的变化率
double dweight_HI[nH][d]; //输入层和隐含层权重的变化率
double dweight_OH[c][nH]; //隐含层和输出层权重的变化率
double old_dweight_HI[nH][d]; //输入层和隐含层上一次权重的变化率
double old_dweight_OH[c][nH]; //隐含层和输出层上一次权重的变化率
double sensitity_k[c]; //隐含层敏感度
double sensitity_j[nH]; //输出层敏感度
double x[d]; //随机选择的样本
double y[nH]; //类的定义中,只能声明不能实例化,也就是不能有分配内存空间的变量
double z[c]; //在新的权值(weight_HI和weight_OH)下输出层的输出值
double net_j[nH]; //隐含层净值
double net_k[c]; //输出层层净值
double t[N][c]; //N个样本的标准输出值
double t_now[c]; //当前样本的标准输出值
double error; //准则函数误差变化率
//构造函数
weight(double s[N][d],double st[N][c]) {
for(int k = 0;k < c;k++) {
sensitity_k[k] = 0;
}
for(int j = 0;j < nH;j++) {
sensitity_j[j] = 0;
}
for(int n = 0;n < N;n++)
for(int i = 0;i < d;i++) {
samples[n] = s[n];
}
for(int n = 0;n < N;n++)
for(int k = 0;k < c;k++) {
t[n][k] = st[n][k];
}
}
//输入层到隐含层权值初始化
void ini_weight_HI(double wHI[nH][d]) {
for(int j = 0;j < nH;j++)
for(int i = 0;i < d;i++) {
weight_HI[j] = wHI[j];
old_weight_HI[j] = wHI[j];
}
}
//隐含层到输出层权值初始化
void ini_weight_OH(double wOH[c][nH]) {
for(int k = 0;k < c;k++)
for(int j = 0;j < nH;j++) {
weight_OH[k][j] = wOH[k][j];
old_weight_OH[k][j] = wOH[k][j];
}
}
//输入层到隐含层权值初始化
void ini_dweight_HI() {
for(int j = 0;j < nH;j++)
for(int i = 0;i < d;i++) {
dweight_HI[j] = 0;
}
}
//隐含层到输出层权值初始化
void ini_dweight_OH() {
for(int k = 0;k < c;k++)
for(int j = 0;j < nH;j++) {
dweight_OH[k][j] = 0;
}
}
//输入层到隐含层权值初始化
void ini_old_dweight_HI() {
for(int j = 0;j < nH;j++)
for(int i = 0;i < d;i++) {
old_dweight_HI[j] = 0;
}
}
//隐含层到输出层权值初始化
void ini_old_dweight_OH() {
for(int k = 0;k < c;k++)
for(int j = 0;j < nH;j++) {
old_dweight_OH[k][j] = 0;
}
}
//获取当前样本标准输出值
void obtain_t_now(double t[c]) { //获取当前样本标准输出值
for(int k = 0;k < c;k++) {
t_now[k] = t[k];
}
}
//获取当前随机选择的样本
void obtain_x(double tem_x[d]) { //获取当前随机选择的样本
for(int i = 0;i < d;i++) {
x = tem_x;
}
}
//计算y[j]以及net_j[j]
void obtain_y() {
y[0] = 1;
//
for(int j = 1;j < nH;j++) {
//净值初始为零
net_j[j] = 0;
//计算净值
for(int i = 0;i < d;i++) {
net_j[j] += weight_HI[j] * x;
}
//计算净值输出
y[j] = 1 / ( 1 + exp(-net_j[j]) );
}
}
//计算z[k]
void obtain_z() {
for(int k = 0;k < c;k++) {
//
net_k[k] = 0;
//
for(int j = 0;j < nH;j++) {
net_k[k] += weight_OH[k][j] * y[j];
}
z[k] = 1 / ( 1 + exp(-net_k[k]) );
}
}
//计算校正后输入层到隐含层的权值
void obtain_new_weight_HI(double rate) {
for(int j = 0;j < nH;j++) {
//
sensitity_j[j] = 0;
//
for(int k = 0;k < c;k++) {
sensitity_j[j] += y[j] * (1- y[j]) * weight_OH[k][j] * sensitity_k[k];
}
//
for(int i = 0;i < d;i++){
//
dweight_HI[j] = rate * sensitity_j[j] * x;
//
weight_HI[j] = weight_HI[j] + (momentum * dweight_HI[j] + (1 - momentum) * old_dweight_HI[j]);
//
old_dweight_HI[j] = dweight_HI[j];
}
}
}
//计算校正后隐含层到输出层的权值
void obtain_new_weight_OH(double rate) {
for(int k = 0;k < c;k++) {
//
sensitity_k[k] = (t_now[k] - z[k]) * z[k] * (1 - z[k]);
//
for(int j = 0;j < nH;j++){
//
dweight_OH[k][j] = rate * sensitity_k[k] * y[j];
//
weight_OH[k][j] = weight_OH[k][j] + (momentum * dweight_OH[k][j] + (1 - momentum) * old_dweight_OH[k][j]);
//
old_dweight_OH[k][j] = dweight_OH[k][j];
}
}
}
//判断迭代是否结束
int if_over() {
error = 0;
for(int n = 0;n < N;n++) {
obtain_x(samples[n]);
obtain_t_now(t[n]);
obtain_y();
obtain_z();
for(int k = 0;k < c;k++) {
error += fabs( 0.5 * pow( z[k] - t_now[k],2 ) );
}
}
if( (error) < error_limit ) return 1;
else return 0;
}
}; //分号;最容易误事 !
//
int main(){
//
double samples[N][d] = { {1,0,0,1},{1,0,0,0},{1,0,1,0},{1,0,1,1},{1,1,0,0},{1,1,0,1},{1,1,1,0},{1,1,1,1} }; //最基本的数组初始化也忘了 !
double t[N][c] = {0.1,0.9,0.1,0.9,0.1,0.9,0.9,0.1};
double test[8][4] = { {1,0,0,0},{1,1,1,1},{1,0.0,0.0,0.2},{1,0.0,0.0,0.8},{1,0.0,0.2,0.0},{1,0.0,0.8,0.0},{1,0.0,0.2,0.2},{1,0.0,0.8,0.8} };
//
weight w_obj(samples,t);
w_obj.ini_dweight_HI();
w_obj.ini_dweight_OH();
w_obj.ini_old_dweight_HI();
w_obj.ini_old_dweight_OH();
//
srand((unsigned)time(0));
//随机初始化权值weight_OH
double random_weight_OH[c][nH];
for(int k = 0;k < c;k++)
for(int j = 0;j < nH;j++) {
random_weight_OH[k][j] = (double)( rand() % 100 ) / 100 - 0.5;
}
w_obj.ini_weight_OH(random_weight_OH);
//随机初始化权值weight_HI
double random_weight_HI[nH][d];
for(int j = 0;j < nH;j++)
for(int i = 0;i < d;i++) {
random_weight_HI[j] = (double)( rand() % 100 ) / 100 - 0.5;
}
//
w_obj.ini_weight_HI(random_weight_HI);
w_obj.obtain_x(samples[n]);
w_obj.obtain_t_now(t[n]);
w_obj.obtain_y();
w_obj.obtain_z();
}
//
cout<<"Begin"<<endl;
int count = 0;
int num;
int if_over = 0;
while( !if_over ) {
num = rand() % N;
w_obj.obtain_x(samples[num]);
w_obj.obtain_t_now(t[num]);
w_obj.obtain_y();
w_obj.obtain_z();
w_obj.obtain_new_weight_OH(rate);
w_obj.obtain_new_weight_HI(rate);
if_over = w_obj.if_over();
count++; //保存迭代次数
}
getchar();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -