BP 神经网络 C++实现
来源:互联网 发布:sqlserver怎么用 编辑:程序博客网 时间:2024/05/19 12:26
BP.h
#ifndef _BP_H_#define _BP_H_ #include <vector> #define LAYER 3 //三层神经网络#define NUM 10 //每层的最多节点数 #define A 30.0#define B 10.0 //A和B是S型函数的参数#define ITERS 1000 //最大训练次数#define ETA_W 0.0035 //权值调整率#define ETA_B 0.001 //阀值调整率#define ERROR 0.002 //单个样本允许的误差#define ACCU 0.005 //每次迭代允许的误差 #define Type double#define Vector std::vector struct Data{ Vector<Type> x; //输入数据 Vector<Type> y; //输出数据}; class BP{ public: void GetData(const Vector<Data>); void Train(); Vector<Type> ForeCast(const Vector<Type>); private: void InitNetWork(); //初始化网络 void GetNums(); //获取输入、输出和隐含层节点数 void ForwardTransfer(); //正向传播子过程 void ReverseTransfer(int); //逆向传播子过程 void CalcDelta(int); //计算w和b的调整量 void UpdateNetWork(); //更新权值和阀值 Type GetError(int); //计算单个样本的误差 Type GetAccu(); //计算所有样本的精度 Type Sigmoid(const Type); //计算Sigmoid的值 private: int in_num; //输入层节点数 int ou_num; //输出层节点数 int hd_num; //隐含层节点数 Vector<Data> data; //输入输出数据 Type w[LAYER][NUM][NUM]; //BP网络的权值 Type b[LAYER][NUM]; //BP网络节点的阀值 Type x[LAYER][NUM]; //每个神经元的值经S型函数转化后的输出值,输入层就为原值 Type d[LAYER][NUM]; //记录delta学习规则中delta的值}; #endif //_BP_H_
BP.CPP
#include <string.h>#include <stdio.h>#include <math.h>#include <assert.h>#include "BP.h"//获取训练所有样本数据void BP::GetData(const Vector<Data> _data){data = _data;}//开始进行训练void BP::Train(){printf("Begin to train BP NetWork!\n");GetNums();InitNetWork(); int num = data.size();for(int iter = 0; iter <= ITERS; iter++){for(int cnt = 0; cnt < num; cnt++){//第一层输入节点赋值for(int i = 0; i < in_num; i++)x[0][i] = data.at(cnt).x[i];while(1){ForwardTransfer(); if(GetError(cnt) < ERROR) //如果误差比较小,则针对单个样本跳出循环break; ReverseTransfer(cnt); }}printf("This is the %d th trainning NetWork !\n", iter);Type accu = GetAccu();printf("All Samples Accuracy is %lf\n", accu);if(accu < ACCU) break;}printf("The BP NetWork train End!\n");}//根据训练好的网络来预测输出值Vector<Type> BP::ForeCast(const Vector<Type> data){int n = data.size();assert(n == in_num); for(int i = 0; i < in_num; i++)x[0][i] = data[i]; ForwardTransfer();Vector<Type> v;for(int i = 0; i < ou_num; i++)v.push_back(x[2][i]);return v;}//获取网络节点数void BP::GetNums(){in_num = data[0].x.size(); //获取输入层节点数ou_num = data[0].y.size(); //获取输出层节点数 hd_num = (int)sqrt((in_num + ou_num) * 1.0) + 5; //获取隐含层节点数if(hd_num > NUM) hd_num = NUM; //隐含层数目不能超过最大设置}//初始化网络void BP::InitNetWork(){ memset(w, 0, sizeof(w)); //初始化权值和阀值为0,也可以初始化随机值memset(b, 0, sizeof(b));}//工作信号正向传递子过程void BP::ForwardTransfer(){//计算隐含层各个节点的输出值for(int j = 0; j < hd_num; j++){Type t = 0;for(int i = 0; i < in_num; i++)t += w[1][i][j] * x[0][i];t += b[1][j];x[1][j] = Sigmoid(t);}//计算输出层各节点的输出值for(int j = 0; j < ou_num; j++){Type t = 0;for(int i = 0; i < hd_num; i++)t += w[2][i][j] * x[1][i];t += b[2][j];x[2][j] = Sigmoid(t);}}//计算单个样本的误差Type BP::GetError(int cnt){Type ans = 0;for(int i = 0; i < ou_num; i++)ans += 0.5 * (x[2][i] - data.at(cnt).y[i]) * (x[2][i] - data.at(cnt).y[i]);return ans;}//误差信号反向传递子过程void BP::ReverseTransfer(int cnt){CalcDelta(cnt); UpdateNetWork();}//计算所有样本的精度Type BP::GetAccu(){Type ans = 0;int num = data.size();for(int i = 0; i < num; i++){int m = data.at(i).x.size();for(int j = 0; j < m; j++)x[0][j] = data.at(i).x[j]; ForwardTransfer();int n = data.at(i).y.size();for(int j = 0; j < n; j++) ans += 0.5 * (x[2][j] - data.at(i).y[j]) * (x[2][j] - data.at(i).y[j]);}return ans / num;}//计算调整量void BP::CalcDelta(int cnt){//计算输出层的delta值for(int i = 0; i < ou_num; i++)d[2][i] = (x[2][i] - data.at(cnt).y[i]) * x[2][i] * (A - x[2][i]) / (A * B);//计算隐含层的delta值for(int i = 0; i < hd_num; i++){Type t = 0;for(int j = 0; j < ou_num; j++)t += w[2][i][j] * d[2][j];d[1][i] = t * x[1][i] * (A - x[1][i]) / (A * B);}}//根据计算出的调整量对BP网络进行调整void BP::UpdateNetWork(){//隐含层和输出层之间权值和阀值调整for(int i = 0; i < hd_num; i++){for(int j = 0; j < ou_num; j++)w[2][i][j] -= ETA_W * d[2][j] * x[1][i]; }for(int i = 0; i < ou_num; i++)b[2][i] -= ETA_B * d[2][i];//输入层和隐含层之间权值和阀值调整for(int i = 0; i < in_num; i++){for(int j = 0; j < hd_num; j++)w[1][i][j] -= ETA_W * d[1][j] * x[0][i];}for(int i = 0; i < hd_num; i++)b[1][i] -= ETA_B * d[1][i];}//计算Sigmoid函数的值Type BP::Sigmoid(const Type x){return A / (1 + exp(-x / B));}
Test.CPP
#include <iostream>#include <string.h>#include <stdio.h> #include "BP.h" using namespace std; double sample[41][4]= { {0,0,0,0}, {5,1,4,19.020}, {5,3,3,14.150}, {5,5,2,14.360}, {5,3,3,14.150}, {5,3,2,15.390}, {5,3,2,15.390}, {5,5,1,19.680}, {5,1,2,21.060}, {5,3,3,14.150}, {5,5,4,12.680}, {5,5,2,14.360}, {5,1,3,19.610}, {5,3,4,13.650}, {5,5,5,12.430}, {5,1,4,19.020}, {5,1,4,19.020}, {5,3,5,13.390}, {5,5,4,12.680}, {5,1,3,19.610}, {5,3,2,15.390}, {1,3,1,11.110}, {1,5,2,6.521}, {1,1,3,10.190}, {1,3,4,6.043}, {1,5,5,5.242}, {1,5,3,5.724}, {1,1,4,9.766}, {1,3,5,5.870}, {1,5,4,5.406}, {1,1,3,10.190}, {1,1,5,9.545}, {1,3,4,6.043}, {1,5,3,5.724}, {1,1,2,11.250}, {1,3,1,11.110}, {1,3,3,6.380}, {1,5,2,6.521}, {1,1,1,16.000}, {1,3,2,7.219}, {1,5,3,5.724} }; int main(){ Vector<Data> data; for(int i = 0; i < 41; i++) { Data t; for(int j = 0; j < 3; j++) t.x.push_back(sample[i][j]); t.y.push_back(sample[i][3]); data.push_back(t); } BP *bp = new BP(); bp->GetData(data); bp->Train(); while(1) { Vector<Type> in; for(int i = 0; i < 3; i++) { Type v; scanf("%lf", &v); in.push_back(v); } Vector<Type> ou; ou = bp->ForeCast(in); printf("%lf\n", ou[0]); } return 0;}
阅读全文
0 0
- bp神经网络c语言实现
- BP神经网络-- C语言实现
- BP神经网络C代码实现
- BP神经网络-- C语言实现
- 【C++】神经网络BP算法实现
- 神经网络BP算法(C程序实现)
- BP神经网络-- C语言实现 上
- c语言实现3层bp神经网络
- BP神经网络-- C语言实现 上
- BP神经网络-- C语言实现 下
- BP神经网络C程序
- BP神经网络+c代码
- BP神经网络算法实现
- BP神经网络算法实现
- java实现BP神经网络
- Matlab实现BP神经网络
- matlab实现BP神经网络
- BP神经网络Python实现
- 多线程
- 判断条件短路问题
- centos7 ip设置
- wcf系列学习5天速成——第四天 wcf之分布式架构
- 一个完整的单例模式代码
- BP 神经网络 C++实现
- 移动端适配的解决方案
- 子串和
- uploadify上传文件 Firefox HTTP IO 302 错误
- LeetCode 72. Edit Distance
- 策略模式
- 调整数组使奇数全部位于偶数前面
- 根据GUID找到位于那张表,那一列
- 热更新,补丁修复---bugly