bp
头文件
/* * bp.h * * Created on: 2013年12月10日 * Author: sai */ #ifndef BP_H_ #define BP_H_ #include "linalgebra.h" #include <string> /****************************************************************************** 前向反馈神经网络,三层神经元(一个隐藏层) ******************************************************************************/ class BP3 { public: BP3(int inSize, int hideSize, int outSize); ~BP3(); void train(Vector sample[], Vector target[], int size); void calc(const Vector& sample); //根据输入计算各个神经元节点的值 void backPropagation(Vector& sample, Vector& answer); //训练权值 void readFile(const std::string& fileName); void saveFile(const std::string& fileName) const; void normalize(Vector aVec[], int size); void speedUp(); //protected: Vector vI; //输入层的值 Vector vH; //隐藏层的值 Vector vO; //输出层的值 Vector eH; //隐藏层误差 Vector eO; //输出层误差 Matrix wH; //每个输入层到中间层的权值 Matrix wO; //每个中间层到输出层的权值 Matrix dH; //上次wH的调整幅度 Matrix dO; //上次wO的调整幅度 Vector tH; //输入层到隐藏层的阈值 Vector tO; //隐藏层到输出层的阈值 int iSize; //输入层大小 int hSize; //隐藏层大小 int oSize; //输出层大小 double eta; //学习步长 double alpha; //动量项系数 }; #endif /* BP_H_ */
源文件
/* * bp.cpp * * Created on: 2013年12月10日 * Author: sai */ #include "bp.h" #include <iostream> #include <fstream> #include <cfloat> using namespace std; BP3::BP3(int inSize, int hideSize, int outSize) { eta = 0.3; alpha = 0.8; iSize = inSize; vI.resize(iSize); hSize = hideSize; vH.resize(hSize); wH.resize(hSize, iSize); for (int i=0; i<hSize; i++) for (int j=0; j<iSize; j++) wH.data[i][j] = 0.6 * rand() / RAND_MAX - 0.3; //权值初始化为[-0.3,0.3] tH.resize(hSize); eH.resize(hSize); dH.resize(hSize, iSize); dH.zero(); oSize = outSize; vO.resize(oSize); wO.resize(oSize, hSize); for (int i=0; i<oSize; i++) for (int j=0; j<hSize; j++) wO.data[i][j] = 0.6 * rand() / RAND_MAX - 0.3; tO.resize(oSize); eO.resize(oSize); dO.resize(oSize, hSize); dO.zero(); /* cout<<"wH:\n"<<wH<<endl <<"wO:\n"<<wO<<endl <<"dH:\n"<<dH<<endl <<"dO:\n"<<dO<<endl;*/ } BP3::~BP3() { } void BP3::normalize(Vector aVec[], int size) { Vector min(aVec[0].size()), max(aVec[0].size()); min.zero(); max.zero(); for (int i=0; i<size; i++) for (int j=0; j<aVec[j].size(); j++) if (aVec[i][j] > max[j]) max[j] = aVec[i][j]; else if (aVec[i][j] < min[j]) min[j] = aVec[i][j]; for (int i=0; i<size; i++) for (int j=0; j<aVec[j].size(); j++) aVec[i][j] = (aVec[i][j]-min[j]+0.001) / (max[j]-min[j]+0.001); /* for (int i=0; i<size; i++) { for (int j=0; j<aVec[j].size(); j++) cout<<aVec[i][j]<<'\t'; cout<<endl; }*/ } void BP3::speedUp() { for (int i=0; i<oSize; i++) if (vO[i] < 0.1) vO[i] = 0.1; else if (vO[i] > 0.9) vO[i] = 0.9; } void BP3::calc(const Vector& sample) { //输入层 vI = sample; //隐藏层 vH = wH * vI + tH; for (int i=0; i<hSize; i++) vH[i] = 1 / (1 + exp(-vH[i])); //输出层 vO = wO * vH - tO; for (int i=0; i<oSize; i++) vO[i] = 1 / (1 + exp(-vO[i])); } void BP3::backPropagation(Vector& sample, Vector& target) { //输出层调整 // eO = vO * (1-vO) * (target - vO); for (int i=0; i<oSize; i++) //输出层误差 eO[i] = vO[i] * (1-vO[i]) * (target[i] - vO[i]); dO = eta * eO * vH.transpose() + alpha * dO; //输出层权值修正量 wO += dO; //修正输出层权值 tO += eta * eO; //隐藏层调整 eH = eO.transpose() * wO; //隐藏层误差 // eH = vH * (1 - vH) * eH; for (int i=0; i<hSize; i++) eH[i] = vH[i] * (1-vH[i]) * eH[i]; dH = eta * eH * vI.transpose() + alpha * dH; //隐藏层权值修正量 wH += dH; //修正隐藏层权值 tH = eta * eH; } void BP3::train(Vector sample[], Vector target[], int size) { normalize(sample, size); for (int t=0; t<100000; t++) //训练次数 { for (int i=0; i<size; i++) { calc(sample[i]); //正向传播 // speedUp(); backPropagation(sample[i], target[i]); //反向传播 } double error = 0; for (int i=0; i<size; i++) { calc(sample[i]); for (int j=0; j<oSize; j++) error += fabs(vO[j] - target[i][j]); } cout<<error<<endl; } } void BP3::saveFile(const std::string& fileName) const { ofstream f(fileName.c_str(), ios::binary); f.write((char*)(&iSize), sizeof(int)); f.write((char*)(&hSize), sizeof(int)); f.write((char*)(&oSize), sizeof(int)); for (int i=0; i<hSize; i++) for (int j=0; j<iSize; j++) f.write((char*)(&wH[i][j]), sizeof(double)); for (int i=0; i<hSize; i++) f.write((char*)(&tH[i]), sizeof(int)); for (int i=0; i<oSize; i++) for (int j=0; j<hSize; j++) f.write((char*)(&wO[i][j]), sizeof(double)); for (int i=0; i<oSize; i++) f.write((char*)(&tO[i]), sizeof(int)); } void BP3::readFile(const std::string& fileName) { ifstream f(fileName.c_str(), ios::binary); if (!f) { cerr<<"文件不存在,错误发生在函数"<<__FUNCTION__<<endl; return; } f.read((char*)(&iSize), sizeof(int)); f.read((char*)(&hSize), sizeof(int)); f.read((char*)(&oSize), sizeof(int)); vI.resize(iSize); vH.resize(hSize); wH.resize(hSize, iSize); for (int i=0; i<hSize; i++) for (int j=0; j<iSize; j++) f.read((char*)(&wH[i][j]), sizeof(double)); tH.resize(hSize); for (int i=0; i<hSize; i++) f.read((char*)(&tH[i]), sizeof(int)); eH.resize(hSize); dH.resize(hSize, iSize); dH.zero(); vO.resize(oSize); wO.resize(oSize, hSize); for (int i=0; i<oSize; i++) for (int j=0; j<hSize; j++) f.read((char*)(&wO[i][j]), sizeof(double)); tO.resize(oSize); for (int i=0; i<oSize; i++) f.read((char*)(&tO[i]), sizeof(int)); eO.resize(oSize); dO.resize(oSize, hSize); dO.zero(); }
浙公网安备 33010602011771号