📄 net.h
字号:
#ifndef _NET_H_#define _NET_H_#include <iostream>#include <string.h>namespace NeuralNetwork{//网络计算中使用类型typedef double real;//从流对象读取数据模板template <class T>inline void readRaw(std::istream& in, T& obj){ in.read(reinterpret_cast<char*>(&obj), sizeof(T));}//从流对象中读取数组数据模板template <class T>inline void readRawArray(std::istream& in, T* array, int size){ in.read(reinterpret_cast<char*>(array), sizeof(T)*size);}//写数据到流对象模板template <class T>inline void writeRaw(std::ostream& out, const T& obj){ out.write(reinterpret_cast<const char*>(&obj), sizeof(T));}//写数组数据到流对象模板template <class T>inline void writeRawArray(std::ostream& out, const T* array, int size){ out.write(reinterpret_cast<const char*>(array), sizeof(T)*size);}//定义神经网络层类(提供给神经网络类使用)class NetLayer{public: //根据给定的神经元数units和已有的网络层preLayer(0表示没有) //创建一个新网络层 NetLayer(int initUnits, NetLayer* prevLayer); //从先前利用save()函数保存的流对象中复制加载网络层 NetLayer(std::istream& in, NetLayer* initPrevLayer); //释放保存权值的资源等 ~NetLayer(); //取得本层中的神经元数目 int getUnits() const; //取得第outputNum个神经元的输出 real getOutput(int outputNum) const; //设置指定神经元的输出误差 void setError(int errorNum, real value); //随机初始化权值 void randomizeWeights(); //权值置0 void clearWeights(); //保存权值, 以便以后restoreWeights()用 //仅能保存一组,一般是看起来最好的一组 void saveWeights(); //恢复由saveWeights()保存的权值 void restoreWeights(); //传播上层输出到本层输出 void propagate(real gain); //反馈本层误差到上层 //adjustWeights()将会使用这些信息 void backpropagate(real gain); //根据一组目标值计算本层输出误差 //存储,并计算出它们的均方误差(一般在输出层使用这个函数) real computeError(real gain, real target[]); //修正权值以减少由computeError/backpropagate调用所生成的误差 void adjustWeights(real momentum, real learningRate); //取得本层神经元输出值,存放到outputsHolder数组中 void getOutputs(real* outputsHolder); //设置本层神经元输出的值 void setOutputs(real* newValues); //保存网络到out流中, 以便以后加载用 void save(std::ostream& out); //释放训练时申请的资源 void doneTraining();private: //取得weightnum在unit unitNum中生成的权值 real& getWeight(int unitNum, int weightNum); //取得weightnum在unit unitNum中生成的权值增量 real& getDWeight(int unitNum, int weightNum);private: int units; // 本层神经元个数 int weightsPerUnit; //每个神经元中的权值数 real* output; //神经元输出 real* error; //神经元误差项 real* weight; //神经元的连接权值 real* weightSave; //停止训练所保存的权值 real* dWeight; //动量算法要用到的最后一次权值增量 NetLayer* prevLayer; //下一个网络层指针 //用于提高效率所用的缓冲区,仅能分配一次 real* weightIntermediate;};inline int NetLayer::getUnits() const{ return units;}inline real NetLayer::getOutput(int outputNum) const{ return output[outputNum];}inline void NetLayer::setError(int nodeNum, real value){ error[nodeNum] = value;}inline void NetLayer::setOutputs(real* newValues){ memcpy(output+1, newValues, sizeof(real)*units);}inline void NetLayer::getOutputs(real* outputsHolder){ memcpy(outputsHolder, output+1, sizeof(real)*units);}inline real& NetLayer::getWeight(int unitNum, int weightNum){ return weight[unitNum*weightsPerUnit + weightNum];}inline real& NetLayer::getDWeight(int unitNum, int weightNum){ return dWeight[unitNum*weightsPerUnit + weightNum];}inline void NetLayer::saveWeights(){ memcpy(weightSave, weight, (units+1)*weightsPerUnit*sizeof(real));}inline void NetLayer::restoreWeights(){ memcpy(weight, weightSave, (units+1)*weightsPerUnit*sizeof(real));}//定义生成神经网络所需的训练和测试样本的类//从这个类派生具体的类,然后将它们的实例化对象传递给autotrain和testclass ExampleFactory{public: //在给定数组中填入训练将使用的输入数据和期待输出 //训练数据都应该先使用numOfExamples()计算 virtual void getExample(int inputSize, real* input, int outputSize, real* output) = 0; //返回训练样本个数, 如果是随机生成, 请合理挑出些大的样本 virtual int numExamples() = 0;};//定义一个完整的多层反馈神经网络的类class Net{public: //通过给定节点数的神经层, 学习速率, 动量因子, sigmoid函数增量 //生成一个新的反馈神经网络 Net(int layers, int layerSizes[], real momentumFactor, real learningRate, real gain); //从已保存的流对象里面加载网络 Net(std::istream& in); //释放分配的资源 ~Net(); //随机初始化所有权值 void randomizeWeights(); //权值清0 void clearWeights(); //自动训练网络,直到测试集测试时达到最大值 //返回测试完成时的总误差 // - epochsBetweenTests 确定多少个测试被完成在测试过程中 // - cutOffError 确定在停止训练前超过最小误差的误差值(必须大于1) real autotrain(ExampleFactory &trainingExamples, ExampleFactory &testExamples, int epochsBetweenTests = 10, float cutOffError = 1.1); //通过input运行网络, 反馈产生一个output, 在autotrain()训练之后使用 void run(real* input, real* output); //使用给定的样本测试网络,返回总误差 real test(ExampleFactory &testExamples); //释放训练时分配的资源 void doneTraining(); //保存网络到对象流 void save(std::ostream& out);private: //保存权值, 以便以后restoreWeights()用 //仅能保存一组,一般是看起来最好的一组 void saveWeights(); //恢复由saveWeights()保存的权值 void restoreWeights(); //传播上层输出到本层输出 void propagate(); //反向传播输出误差 void backpropagate(); //计算并存储输出层误差 void computeOutputError(real* target); //修正权值, 减少backpropagate()和computeOutputError()记录的误差 void adjustWeights(); //设置输入值 void setInputs(real* inputs); //取得输出值并存储到outputs数组 void getOutputs(real* outputs); //训练单个样本 void simpleTrain(real* input, real* expectedOutput); //将一个完整的学习样本集训练epoch次 void train(int epochs, ExampleFactory &trainingExamples);private: int numLayers; //网络的层数 NetLayer** layer; //网络层集合 NetLayer* inputLayer; //输入层 NetLayer* outputLayer; //输出层 real momentumFactor; //动量因子 real learningRate; //学习速率 real gain; //sigmoid函数的增量 f(x)=1/(1+e-x) -x是幂数 real error; //网络总误差 //临时缓冲区, 在构造函数中一次申请,提高效率用 real* input; real* expectedOutput; real* actualOutput;}; }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -