c++重写卷积网络的前向计算过程,复现theano的测试结果

来源:互联网 发布:caffe 用训练好的模型 编辑:程序博客网 时间:2024/04/29 16:44

转自http://blog.csdn.net/qiaofangjie/article/details/18042407

本人的需求是:

通过theano的cnn训练神经网络,将最终稳定的网络权值保存下来。c++实现cnn的前向计算过程,读取theano的权值,复现theano的测试结果

本人最终的成果是:

1、卷积神经网络的前向计算过程 
2、mlp网络的前向与后向计算,也就是可以用来训练样本

需要注意的是:
如果为了复现theano的测试结果,那么隐藏层的激活函数要选用tanh
否则,为了mlp的训练过程,激活函数要选择sigmoid

成果的展现:

下图是theano的训练以及测试结果,验证样本错误率为9.23%




下面是我的c++程序,验证错误率也是9.23%,完美复现theano的结果大笑





简单讲难点有两个:

1.theano的权值以及测试样本与c++如何互通?

2.theano的卷积的时候,上层输入的featuremap如何组合,映射到本层的每个像素点上?

在解决上述两点的过程中,走了很多的弯路:

为了用c++重现theano的测试结果,必须让c++能够读取theano保存的权值以及测试样本。
思考分析如下:
1.theano的权值是numpy格式,而它直接与c++交互,很困难,numpy的格式不好解析,网上资料很少
2.采用python做中间转换,实现1)的要求。后看theano代码,发现读入python的训练样本,不用转换成numpy数组,用本来python就可以了。但是python经过cPickle的dump文件,加了很多格式,不适合同c++交互。
3.用json转换,由于python和cpp都有json的接口,都转成json的格式,然后再交互。可是theano训练之后权值是numpy格式的,需要转成python数组,json才可以存到文件中。现在的问题是怎么把numpy转成python的list
4.为了解决3,找了一天,终于找到了numpy数组的tolist接口,可以将numpy数组转换成python的list。
5.现在python和c++都可以用json了。研究jsoncpp库的使用,将python的json文件读取。通过测试发现,库jsoncpp不适合读取大文件,很容易造成内存不足,效率极低,故不可取。
6.用c++写函数,自己解析json文件。并且通过pot文件生成训练与测试样本的时候,也直接用c++来生成,不需要转换成numpy数组的格式。
经过上述分析,解决了难点1。通过json格式实现c++与theano权值与测试样本的互通,并且自己写函数解析json文件

对于难点2,看一个典型的cnn网络图




难点2的详细描述如下:

  • Theano从S2到C3的时候,如何选择S2的featuremap进行组合?每次固定选取还是根据一定的算法动态组合?
  • Theano从C3到S4的pooling过程,令poolsize是(2*2),如何将C3的每4个像素变成S4的一个像素?
通过大量的分析,对比验证,发现以下结论:
  • Theano从S2到C3的时候,选择S2的所有featuremap进行组合
  • Theano从C3到S4的pooling过程,令poolsize是(2*2),,对于C3的每4个像素,选取最大值作为S4的一个像素
通过以上的分析,理论上初步已经弄清楚了。下面就是要根据理论编写代码,真正耗时的是代码的调试过程,总是复现不了theano的测试结果。
曾经不止一次的认为这是不可能复现的,鬼知道theano怎么搞的。
今天终于将代码调通,很是兴奋,于是有了这篇博客。
阻碍我实现结果的bug主要有两个,一个是理论上的不足,对theano卷积的细节把握不准确;一个是自己写代码时粗心,变量初始化错误。如下:
  • S2到C3卷积时,theano会对卷积核旋转180度之后,才会像下图这样进行卷积(本人刚接触这块,实在是不知道啊。。。)

  • C3到S4取像素最大值的时候,想当然认为像素都是正的,变量初始化为0,导致最终找最大值错误(这个bug找的时间最久,血淋淋的教训。。。)

theano对写权值的函数,注意它保存的是卷积核旋转180度后的权值,如果权值是二维的,那么行列互换(与c++的权值表示法统一)
[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. def getDataJson(layers):  
  2.     data = []  
  3.     i = 0  
  4.     for layer in layers:  
  5.         w, b = layer.params  
  6.         # print '..layer is', i  
  7.         w, b = w.get_value(), b.get_value()  
  8.         wshape = w.shape  
  9.         # print '...the shape of w is', wshape  
  10.         if len(wshape) == 2:  
  11.             w = w.transpose()  
  12.         else:  
  13.             for k in xrange(wshape[0]):  
  14.                 for j in xrange(wshape[1]):  
  15.                     w[k][j] = numpy.rot90(w[k][j], 2)  
  16.   
  17.             w = w.reshape((wshape[0], numpy.prod(wshape[1:])))  
  18.           
  19.         w = w.tolist()  
  20.         b = b.tolist()  
  21.         data.append([w, b])  
  22.         i += 1  
  23.     return data  
  24.   
  25. def writefile(data, name = '../../tmp/src/data/theanocnn.json'):  
  26.     print ('writefile is ' + name)  
  27.     f = open(name, "wb")  
  28.     json.dump(data,f)  
  29.     f.close()  

theano读权值
[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. def readfile(layers, nkerns, name = '../../tmp/src/data/theanocnn.json'):  
  2.     # Load the dataset  
  3.     print ('readfile is ' + name)  
  4.     f = open(name, 'rb')  
  5.     data = json.load(f)  
  6.     f.close()  
  7.     readwb(data, layers, nkerns)  
  8.   
  9. def readwb(data, layers, nkerns):  
  10.     i = 0  
  11.     kernSize = len(nkerns)  
  12.     inputnum = 1  
  13.     for layer in layers:  
  14.         w, b = data[i]  
  15.         w = numpy.array(w, dtype='float32')  
  16.         b = numpy.array(b, dtype='float32')  
  17.   
  18.         # print '..layer is', i  
  19.         # print w.shape  
  20.         if i >= kernSize:  
  21.             w = w.transpose()  
  22.         else:  
  23.             w = w.reshape((nkerns[i], inputnum, 55))  
  24.             for k in xrange(nkerns[i]):  
  25.                 for j in xrange(inputnum):  
  26.                     c = w[k][j]  
  27.                     w[k][j] = numpy.rot90(c, 2)  
  28.             inputnum = nkerns[i]  
  29.         # print '..readwb ,transpose and rot180'  
  30.         # print w.shape  
  31.         layer.W.set_value(w, borrow=True)  
  32.         layer.b.set_value(b, borrow=True)  
  33.         i += 1  

测试样本由手写数字库mnist生成,核心代码如下:
[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. def mnist2json_small(cnnName = 'mnist_small.json', validNumber = 10):  
  2.     dataset = '../../data/mnist.pkl'  
  3.     print '... loading data', dataset  
  4.   
  5.     # Load the dataset  
  6.     f = open(dataset, 'rb')  
  7.     train_set, valid_set, test_set = cPickle.load(f)  
  8.     #print test_set  
  9.     f.close()  
  10.     def np2listSmall(train_set, number):  
  11.         trainfile = []  
  12.         trains, labels = train_set  
  13.         trainfile = []  
  14.         #如果注释掉下面,将生成number个验证样本  
  15.         number = len(labels)  
  16.         for one in trains[:number]:  
  17.             one = one.tolist()  
  18.             trainfile.append(one)  
  19.         labelfile = labels[:number].tolist()  
  20.         datafile = [trainfile, labelfile]  
  21.         return datafile  
  22.     smallData = valid_set  
  23.     print len(smallData)  
  24.     valid, validlabel = np2listSmall(smallData, validNumber)  
  25.     datafile = [valid, validlabel]  
  26.     basedir = '../../tmp/src/data/'  
  27.     # basedir = './'  
  28.     json.dump(datafile, open(basedir + cnnName, 'wb'))  

个人收获:
  1. 面对较难的任务,逐步分解,各个击破
  2. 解决问题的过程中,如果此路不通,要马上寻找其它思路,就像当年做数学证明题一样
  3. 态度要积极,不要轻言放弃,尽全力完成任务
  4. 代码调试时,应该首先构造较为全面的测试用例,这样可以迅速定位bug

本人的需求以及实现时的困难已经基本描述清楚,如果还有别的小问题,我相信大家花点比俺少很多很多大哭的时间就可以解决,下面开始贴代码大笑

如果不想自己建工程,这里有vs2008的c++代码,自己按照theano生成一下权值就可以读入运行了

C++代码



main.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include "mlp.h"  
  3. #include "util.h"  
  4. #include "testinherit.h"  
  5. #include "neuralNetwork.h"  
  6. using namespace std;  
  7.   
  8. /************************************************************************/  
  9. /* 本程序实现了 
  10. 1、卷积神经网络的前向计算过程  
  11. 2、mlp网络的前向与后向计算,也就是可以用来训练样本 
  12. 需要注意的是: 
  13. 如果为了复现theano的测试结果,那么隐藏层的激活函数要选用tanh; 
  14. 否则,为了mlp的训练过程,激活函数要选择sigmoid 
  15.  
  16. */  
  17. /************************************************************************/  
  18. int main()  
  19. {  
  20.   
  21.     cout << "****cnn****" << endl;  
  22.     TestCnnTheano(28 * 28, 10);  
  23.     // TestMlpMnist对mlp训练样本进行测试  
  24.     //TestMlpMnist(28 * 28, 500, 10);  
  25.     return 0;  
  26. }  



neuralNetwork.h

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef NEURALNETWORK_H  
  2. #define NEURALNETWORK_H  
  3.   
  4. #include "mlp.h"  
  5. #include "cnn.h"  
  6. #include <vector>  
  7. using std::vector;  
  8.   
  9. /************************************************************************/  
  10. /* 这是一个卷积神经网络                                                                     */  
  11. /************************************************************************/  
  12. class NeuralNetWork  
  13. {  
  14. public:  
  15.     NeuralNetWork(int iInput, int iOut);  
  16.     ~NeuralNetWork();  
  17.     void Predict(double** in_data, int n);  
  18.   
  19.   
  20.     double CalErrorRate(const vector<double *> &vecvalid, const vector<WORD> &vecValidlabel);  
  21.   
  22.     void Setwb(vector< vector<double*> > &vvAllw, vector< vector<double> > &vvAllb);  
  23.     void SetTrainNum(int iNum);  
  24.   
  25.     int Predict(double *pInputData);  
  26.     //    void Forward_propagation(double** ppdata, int n);  
  27.     double* Forward_propagation(double *);  
  28.   
  29. private:  
  30.     int m_iSampleNum; //样本数量  
  31.     int m_iInput; //输入维数  
  32.     int m_iOut; //输出维数  
  33.       
  34.     vector<CnnLayer *> vecCnns;   
  35.     Mlp *m_pMlp;  
  36. };  
  37. void TestCnnTheano(const int iInput, const int iOut);  
  38.   
  39. #endif  


neuralNetwork.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "neuralNetwork.h"  
  2.   
  3. #include <iostream>  
  4. #include "util.h"  
  5. #include <iomanip>  
  6.   
  7. using namespace std;  
  8.   
  9. NeuralNetWork::NeuralNetWork(int iInput, int iOut):m_iSampleNum(0), m_iInput(iInput), m_iOut(iOut), m_pMlp(NULL)  
  10. {  
  11.     int iFeatureMapNumber = 20, iPoolWidth = 2, iInputImageWidth = 28, iKernelWidth = 5, iInputImageNumber = 1;  
  12.   
  13.     CnnLayer *pCnnLayer = new CnnLayer(m_iSampleNum, iInputImageNumber, iInputImageWidth, iFeatureMapNumber, iKernelWidth, iPoolWidth);  
  14.     vecCnns.push_back(pCnnLayer);  
  15.   
  16.     iInputImageNumber = 20;  
  17.     iInputImageWidth = 12;  
  18.     iFeatureMapNumber = 50;  
  19.     pCnnLayer = new CnnLayer(m_iSampleNum, iInputImageNumber, iInputImageWidth, iFeatureMapNumber, iKernelWidth, iPoolWidth);  
  20.     vecCnns.push_back(pCnnLayer);  
  21.   
  22.     const int ihiddenSize = 1;  
  23.     int phidden[ihiddenSize] = {500};  
  24.     // construct LogisticRegression  
  25.     m_pMlp = new Mlp(m_iSampleNum, iFeatureMapNumber * 4 * 4, m_iOut, ihiddenSize, phidden);  
  26.   
  27. }  
  28.   
  29. NeuralNetWork::~NeuralNetWork()  
  30. {  
  31.   
  32.     for (vector<CnnLayer*>::iterator it = vecCnns.begin(); it != vecCnns.end(); ++it)  
  33.     {  
  34.         delete *it;  
  35.     }  
  36.     delete m_pMlp;  
  37. }  
  38.   
  39. void NeuralNetWork::SetTrainNum(int iNum)  
  40. {  
  41.     m_iSampleNum = iNum;  
  42.   
  43.     for (size_t i = 0; i < vecCnns.size(); ++i)  
  44.     {  
  45.         vecCnns[i]->SetTrainNum(iNum);  
  46.     }  
  47.     m_pMlp->SetTrainNum(iNum);  
  48.       
  49. }  
  50.   
  51. int NeuralNetWork::Predict(double *pdInputdata)  
  52. {  
  53.     double *pdPredictData = NULL;  
  54.     pdPredictData = Forward_propagation(pdInputdata);  
  55.   
  56.     int iResult = -1;  
  57.       
  58.       
  59.     iResult = m_pMlp->m_pLogisticLayer->Predict(pdPredictData);  
  60.   
  61.     return iResult;  
  62. }  
  63.   
  64. double* NeuralNetWork::Forward_propagation(double *pdInputData)  
  65. {  
  66.     double *pdPredictData = pdInputData;  
  67.   
  68.     vector<CnnLayer*>::iterator it;  
  69.     CnnLayer *pCnnLayer;  
  70.     for (it = vecCnns.begin(); it != vecCnns.end(); ++it)  
  71.     {  
  72.         pCnnLayer = *it;  
  73.         pCnnLayer->Forward_propagation(pdPredictData);  
  74.         pdPredictData = pCnnLayer->GetOutputData();  
  75.     }  
  76.     //此时pCnnLayer指向最后一个卷积层,pdInputData是卷积层的最后输出  
  77.     //暂时忽略mlp的前向计算,以后加上  
  78.     pdPredictData = m_pMlp->Forward_propagation(pdPredictData);  
  79.     return pdPredictData;  
  80. }  
  81.   
  82. void NeuralNetWork::Setwb(vector< vector<double*> > &vvAllw, vector< vector<double> > &vvAllb)  
  83. {  
  84.     for (size_t i = 0; i < vecCnns.size(); ++i)  
  85.     {  
  86.         vecCnns[i]->Setwb(vvAllw[i], vvAllb[i]);  
  87.     }  
  88.       
  89.     size_t iLayerNum = vvAllw.size();  
  90.     for (size_t i = vecCnns.size(); i < iLayerNum - 1; ++i)  
  91.     {  
  92.         int iHiddenIndex = 0;  
  93.         m_pMlp->m_ppHiddenLayer[iHiddenIndex]->Setwb(vvAllw[i], vvAllb[i]);  
  94.         ++iHiddenIndex;  
  95.     }  
  96.     m_pMlp->m_pLogisticLayer->Setwb(vvAllw[iLayerNum - 1], vvAllb[iLayerNum - 1]);  
  97. }  
  98. double NeuralNetWork::CalErrorRate(const vector<double *> &vecvalid, const vector<WORD> &vecValidlabel)  
  99. {  
  100.     cout << "Predict------------" << endl;  
  101.     int iErrorNumber = 0, iValidNumber = vecValidlabel.size();  
  102.     //iValidNumber = 1;  
  103.     for (int i = 0; i < iValidNumber; ++i)  
  104.     {  
  105.         int iResult = Predict(vecvalid[i]);  
  106.         //cout << i << ",valid is " << iResult << " label is " << vecValidlabel[i] << endl;  
  107.         if (iResult != vecValidlabel[i])  
  108.         {  
  109.             ++iErrorNumber;  
  110.         }  
  111.     }  
  112.   
  113.     cout << "the num of error is " << iErrorNumber << endl;  
  114.     double dErrorRate = (double)iErrorNumber / iValidNumber;  
  115.     cout << "the error rate of Train sample by softmax is " << setprecision(10) << dErrorRate * 100 << "%" << endl;  
  116.   
  117.     return dErrorRate;  
  118. }  
  119.   
  120. /************************************************************************/  
  121. /*  
  122. 测试样本采用mnist库,此cnn的结构与theano教程上的一致,即 
  123. 输入是28*28图像,接下来是2个卷积层(卷积+pooling),featuremap个数分别是20和50, 
  124. 然后是全连接层(500个神经元),最后输出层10个神经元 
  125.  
  126. */  
  127. /************************************************************************/  
  128. void TestCnnTheano(const int iInput, const int iOut)  
  129. {  
  130.     //构建卷积神经网络  
  131.     NeuralNetWork neural(iInput, iOut);  
  132.     //存取theano的权值  
  133.     vector< vector<double*> > vvAllw;  
  134.     vector< vector<double> > vvAllb;  
  135.     //存取测试样本与标签  
  136.     vector<double*> vecValid;  
  137.     vector<WORD> vecLabel;  
  138.     //保存theano权值与测试样本的文件  
  139.     const char *szTheanoWeigh = "../../data/theanocnn.json", *szTheanoTest = "../../data/mnist_validall.json";  
  140.     //将每次权值的第二维(列宽)保存到vector中,用于读取json文件  
  141.     vector<int> vecSecondDimOfWeigh;  
  142.     vecSecondDimOfWeigh.push_back(5 * 5);  
  143.     vecSecondDimOfWeigh.push_back(20 * 5 * 5);  
  144.     vecSecondDimOfWeigh.push_back(50 * 4 * 4);  
  145.     vecSecondDimOfWeigh.push_back(500);  
  146.   
  147.     cout << "loadwb ---------" << endl;  
  148.     //读取权值  
  149.     LoadWeighFromJson(vvAllw, vvAllb, szTheanoWeigh, vecSecondDimOfWeigh);  
  150.     //将权值设置到cnn中  
  151.     neural.Setwb(vvAllw, vvAllb);  
  152.     //读取测试文件           
  153.     LoadTestSampleFromJson(vecValid, vecLabel, szTheanoTest, iInput);  
  154.     //设置测试样本的总量  
  155.     int iVaildNum = vecValid.size();  
  156.     neural.SetTrainNum(iVaildNum);  
  157.     //前向计算cnn的错误率,输出结果  
  158.     neural.CalErrorRate(vecValid, vecLabel);  
  159.       
  160.     //释放测试文件所申请的空间  
  161.     for (vector<double*>::iterator cit = vecValid.begin(); cit != vecValid.end(); ++cit)  
  162.     {  
  163.         delete [](*cit);  
  164.     }  
  165. }  




cnn.h

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef CNN_H  
  2. #define CNN_H  
  3. #include "featuremap.h"  
  4. #include "poollayer.h"  
  5.   
  6. #include <vector>  
  7.   
  8. using std::vector;  
  9.   
  10. typedef unsigned short WORD;  
  11. /** 
  12. *本卷积模拟theano的测试过程 
  13. *当输入层是num个featuremap时,本层卷积层假设有featureNum个featuremap。 
  14. *对于本层每个像素点选取,上一层num个featuremap一起组合,并且没有bias 
  15. *然后本层输出到pooling层,pooling只对poolsize内的像素取最大值,然后加上bias,总共有featuremap个bias值 
  16. */  
  17. class CnnLayer  
  18. {  
  19. public:  
  20.     CnnLayer(int iSampleNum, int iInputImageNumber, int iInputImageWidth, int iFeatureMapNumber,  
  21.         int iKernelWidth, int iPoolWidth);  
  22.     ~CnnLayer();  
  23.     void Forward_propagation(double *pdInputData);  
  24.     void Back_propagation(double* , double* , double );  
  25.   
  26.     void Train(double *x, WORD y, double dLr);  
  27.     int Predict(double *);  
  28.   
  29.     void Setwb(vector<double*> &vpdw, vector<double> &vdb);  
  30.     void SetInputAllData(double **ppInputAllData, int iInputNum);  
  31.     void SetTrainNum(int iSampleNumber);  
  32.     void PrintOutputData();  
  33.   
  34.     double* GetOutputData();  
  35. private:  
  36.     int m_iSampleNum;  
  37.   
  38.     FeatureMap *m_pFeatureMap;  
  39.     PoolLayer *m_pPoolLayer;  
  40.     //反向传播时所需值  
  41.     double **m_ppdDelta;  
  42.     double *m_pdInputData;  
  43.     double *m_pdOutputData;  
  44. };  
  45. void TestCnn();  
  46.   
  47. #endif // CNN_H  

cnn.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "cnn.h"  
  2. #include "util.h"  
  3. #include <cassert>  
  4.   
  5. CnnLayer::CnnLayer(int iSampleNum, int iInputImageNumber, int iInputImageWidth, int iFeatureMapNumber,  
  6.                    int iKernelWidth, int iPoolWidth):  
  7.     m_iSampleNum(iSampleNum), m_pdInputData(NULL), m_pdOutputData(NULL)  
  8. {  
  9.     m_pFeatureMap = new FeatureMap(iInputImageNumber, iInputImageWidth, iFeatureMapNumber, iKernelWidth);  
  10.     int iFeatureMapWidth =  iInputImageWidth - iKernelWidth + 1;  
  11.     m_pPoolLayer = new PoolLayer(iFeatureMapNumber, iPoolWidth, iFeatureMapWidth);  
  12.      
  13. }  
  14.   
  15. CnnLayer::~CnnLayer()  
  16. {  
  17.     delete m_pFeatureMap;  
  18.     delete m_pPoolLayer;  
  19. }  
  20.   
  21. void CnnLayer::Forward_propagation(double *pdInputData)  
  22. {  
  23.     m_pFeatureMap->Convolute(pdInputData);  
  24.     m_pPoolLayer->Convolute(m_pFeatureMap->GetFeatureMapValue());  
  25.     m_pdOutputData = m_pPoolLayer->GetOutputData();  
  26.     /************************************************************************/  
  27.     /* 调试卷积过程的各阶段结果,调通后删除                                                                     */  
  28.     /************************************************************************/  
  29.     /*m_pFeatureMap->PrintOutputData(); 
  30.     m_pPoolLayer->PrintOutputData();*/  
  31. }  
  32.   
  33. void CnnLayer::SetInputAllData(double **ppInputAllData, int iInputNum)  
  34. {  
  35.       
  36. }  
  37.   
  38. double* CnnLayer::GetOutputData()  
  39. {  
  40.     assert(NULL != m_pdOutputData);  
  41.   
  42.     return m_pdOutputData;  
  43. }  
  44.   
  45. void CnnLayer::Setwb(vector<double*> &vpdw, vector<double> &vdb)  
  46. {  
  47.     m_pFeatureMap->SetWeigh(vpdw);  
  48.     m_pPoolLayer->SetBias(vdb);  
  49.       
  50. }  
  51.   
  52. void CnnLayer::SetTrainNum( int iSampleNumber )  
  53. {  
  54.     m_iSampleNum = iSampleNumber;  
  55. }  
  56.   
  57. void CnnLayer::PrintOutputData()  
  58. {  
  59.     m_pFeatureMap->PrintOutputData();  
  60.     m_pPoolLayer->PrintOutputData();  
  61.   
  62. }  
  63. void TestCnn()  
  64. {  
  65.     const int iFeatureMapNumber = 2, iPoolWidth = 2, iInputImageWidth = 8, iKernelWidth = 3, iInputImageNumber = 2;  
  66.   
  67.     double *pdImage = new double[iInputImageWidth * iInputImageWidth * iInputImageNumber];  
  68.     double arrInput[iInputImageNumber][iInputImageWidth * iInputImageWidth];  
  69.   
  70.     MakeCnnSample(arrInput, pdImage, iInputImageWidth, iInputImageNumber);  
  71.   
  72.     double *pdKernel = new double[3 * 3 * iInputImageNumber];  
  73.     double arrKernel[3 * 3 * iInputImageNumber];  
  74.     MakeCnnWeigh(pdKernel, iInputImageNumber) ;  
  75.       
  76.   
  77.     CnnLayer cnn(3, iInputImageNumber, iInputImageWidth, iFeatureMapNumber, iKernelWidth, iPoolWidth);  
  78.   
  79.     vector <double*> vecWeigh;  
  80.     vector <double> vecBias;  
  81.     for (int i = 0; i < iFeatureMapNumber; ++i)  
  82.     {  
  83.         vecBias.push_back(1.0);  
  84.     }  
  85.     vecWeigh.push_back(pdKernel);  
  86.     for (int i = 0; i < 3 * 3 * 2; ++i)  
  87.     {  
  88.         arrKernel[i] = i;  
  89.     }  
  90.     vecWeigh.push_back(arrKernel);  
  91.     cnn.Setwb(vecWeigh, vecBias);  
  92.       
  93.     cnn.Forward_propagation(pdImage);  
  94.     cnn.PrintOutputData();  
  95.       
  96.   
  97.   
  98.     delete []pdKernel;  
  99.     delete []pdImage;  
  100.   
  101. }  


featuremap.h

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef FEATUREMAP_H  
  2. #define FEATUREMAP_H  
  3.   
  4. #include <cassert>  
  5. #include <vector>  
  6. using std::vector;  
  7.   
  8. class FeatureMap  
  9. {  
  10. public:  
  11.     FeatureMap(int iInputImageNumber, int iInputImageWidth, int iFeatureMapNumber, int iKernelWidth);  
  12.     ~FeatureMap();  
  13.     void Forward_propagation(double* );  
  14.     void Back_propagation(double* , double* , double );  
  15.   
  16.   
  17.     void Convolute(double *pdInputData);  
  18.   
  19.     int GetFeatureMapSize()  
  20.     {  
  21.         return m_iFeatureMapSize;  
  22.     }  
  23.   
  24.     int GetFeatureMapWidth()  
  25.     {  
  26.         return m_iFeatureMapWidth;  
  27.     }  
  28.   
  29.     double* GetFeatureMapValue()  
  30.     {  
  31.         assert(m_pdOutputValue != NULL);  
  32.         return m_pdOutputValue;  
  33.     }  
  34.   
  35.     void SetWeigh(const vector<double *> &vecWeigh);  
  36.     void PrintOutputData();  
  37.   
  38.     double **m_ppdWeigh;  
  39.     double *m_pdBias;  
  40.   
  41. private:  
  42.     int m_iInputImageNumber;  
  43.     int m_iInputImageWidth;  
  44.     int m_iInputImageSize;  
  45.     int m_iFeatureMapNumber;  
  46.     int m_iFeatureMapWidth;  
  47.     int m_iFeatureMapSize;  
  48.     int m_iKernelWidth;  
  49.       
  50. //    double m_dBias;  
  51.     double *m_pdOutputValue;  
  52. };  
  53.   
  54. #endif // FEATUREMAP_H  


featuremap.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "featuremap.h"  
  2. #include "util.h"  
  3. #include <cassert>  
  4.   
  5. FeatureMap::FeatureMap(int iInputImageNumber, int iInputImageWidth, int iFeatureMapNumber, int iKernelWidth):  
  6.     m_iInputImageNumber(iInputImageNumber),  
  7.     m_iInputImageWidth(iInputImageWidth),  
  8.     m_iFeatureMapNumber(iFeatureMapNumber),  
  9.     m_iKernelWidth(iKernelWidth)  
  10. {  
  11.     m_iFeatureMapWidth = m_iInputImageWidth - m_iKernelWidth + 1;  
  12.     m_iInputImageSize = m_iInputImageWidth * m_iInputImageWidth;  
  13.     m_iFeatureMapSize = m_iFeatureMapWidth * m_iFeatureMapWidth;  
  14.       
  15.   
  16.     int iKernelSize;  
  17.     iKernelSize = m_iKernelWidth * m_iKernelWidth;  
  18.   
  19.     double dbase = 1.0 / m_iInputImageSize;  
  20.     srand((unsigned)time(NULL));  
  21.       
  22.   
  23.     m_ppdWeigh = new double*[m_iFeatureMapNumber];  
  24.     m_pdBias = new double[m_iFeatureMapNumber];  
  25.   
  26.     for (int i = 0; i < m_iFeatureMapNumber; ++i)  
  27.     {  
  28.         m_ppdWeigh[i] = new double[m_iInputImageNumber * iKernelSize];  
  29.         for (int j = 0; j < m_iInputImageNumber * iKernelSize; ++j)  
  30.         {  
  31.             m_ppdWeigh[i][j] = uniform(-dbase, dbase);  
  32.         }  
  33.         //m_pdBias[i] = uniform(-dbase, dbase);  
  34.         //theano的卷积层貌似没有用到bias,它在pooling层使用  
  35.         m_pdBias[i] = 0;  
  36.     }  
  37.   
  38.     m_pdOutputValue = new double[m_iFeatureMapNumber * m_iFeatureMapSize];  
  39.       
  40. //    m_dBias = uniform(-dbase, dbase);  
  41. }  
  42.   
  43. FeatureMap::~FeatureMap()  
  44. {  
  45.     delete []m_pdOutputValue;  
  46.     delete []m_pdBias;  
  47.     for (int i = 0; i < m_iFeatureMapNumber; ++i)  
  48.     {  
  49.         delete []m_ppdWeigh[i];  
  50.     }  
  51.     delete []m_ppdWeigh;  
  52.       
  53. }  
  54.   
  55. void FeatureMap::SetWeigh(const vector<double *> &vecWeigh)  
  56. {  
  57.     assert(vecWeigh.size() == (DWORD)m_iFeatureMapNumber);  
  58.     for (int i = 0; i < m_iFeatureMapNumber; ++i)  
  59.     {  
  60.         delete []m_ppdWeigh[i];  
  61.         m_ppdWeigh[i] = vecWeigh[i];  
  62.     }  
  63. }  
  64.   
  65. /* 
  66.  
  67. 卷积计算 
  68. pdInputData:一维向量,包含若干个输入图像 
  69.  
  70. */  
  71. void FeatureMap::Convolute(double *pdInputData)  
  72. {  
  73.     for (int iMapIndex = 0; iMapIndex < m_iFeatureMapNumber; ++iMapIndex)  
  74.     {  
  75.         double dBias = m_pdBias[iMapIndex];  
  76.         //每一个featuremap  
  77.         for (int i = 0; i < m_iFeatureMapWidth; ++i)  
  78.         {  
  79.             for (int j = 0; j < m_iFeatureMapWidth; ++j)  
  80.             {  
  81.                 double dSum = 0.0;  
  82.                 int iInputIndex, iKernelIndex, iInputIndexStart, iKernelStart, iOutIndex;  
  83.                 //输出向量的索引计算  
  84.                 iOutIndex = iMapIndex * m_iFeatureMapSize + i * m_iFeatureMapWidth + j;  
  85.                 //分别计算每一个输入图像  
  86.                 for (int k = 0; k < m_iInputImageNumber; ++k)  
  87.                 {  
  88.                     //与kernel对应的输入图像的起始位置  
  89.                     //iInputIndexStart = k * m_iInputImageSize + j * m_iInputImageWidth + i;  
  90.                     iInputIndexStart = k * m_iInputImageSize + i * m_iInputImageWidth + j;  
  91.                     //kernel的起始位置  
  92.                     iKernelStart = k * m_iKernelWidth * m_iKernelWidth;  
  93.                     for (int m = 0; m < m_iKernelWidth; ++m)  
  94.                     {  
  95.                         for (int n = 0; n < m_iKernelWidth; ++n)  
  96.                         {  
  97.   
  98.                             //iKernelIndex = iKernelStart + n * m_iKernelWidth + m;  
  99.                             iKernelIndex = iKernelStart + m * m_iKernelWidth + n;  
  100.                             //i am not sure, is the expression of below correct?  
  101.                             iInputIndex = iInputIndexStart + m * m_iInputImageWidth + n;  
  102.   
  103.                             dSum += pdInputData[iInputIndex] * m_ppdWeigh[iMapIndex][iKernelIndex];  
  104.                         }//end n  
  105.                     }//end m  
  106.   
  107.                 }//end k  
  108.                 //加上偏置  
  109.                 //dSum += dBias;  
  110.                 m_pdOutputValue[iOutIndex] = dSum;        
  111.                   
  112.             }//end j  
  113.         }//end i  
  114.     }//end iMapIndex  
  115. }  
  116.   
  117. void FeatureMap::PrintOutputData()  
  118. {  
  119.      for (int i  = 0; i < m_iFeatureMapNumber; ++i)  
  120.      {  
  121.          cout << "featuremap " << i <<endl;  
  122.          for (int m = 0; m < m_iFeatureMapWidth; ++m)  
  123.          {  
  124.              for (int n = 0; n < m_iFeatureMapWidth; ++n)  
  125.              {  
  126.                  cout << m_pdOutputValue[i * m_iFeatureMapSize +m * m_iFeatureMapWidth +n] << ' ';  
  127.              }  
  128.              cout << endl;  
  129.                
  130.          }  
  131.          cout <<endl;  
  132.            
  133.      }  
  134.        
  135. }  


poollayer.h

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef POOLLAYER_H  
  2. #define POOLLAYER_H  
  3. #include <vector>  
  4. using std::vector;  
  5. class PoolLayer  
  6. {  
  7. public:  
  8.     PoolLayer(int iOutImageNumber, int iPoolWidth, int iFeatureMapWidth);  
  9.     ~PoolLayer();  
  10.     void Convolute(double *pdInputData);  
  11.     void SetBias(const vector<double> &vecBias);  
  12.     double* GetOutputData();  
  13.     void PrintOutputData();  
  14.       
  15. private:  
  16.     int m_iOutImageNumber;  
  17.     int m_iPoolWidth;  
  18.     int m_iFeatureMapWidth;  
  19.     int m_iPoolSize;  
  20.     int m_iOutImageEdge;  
  21.     int m_iOutImageSize;  
  22.       
  23.     double *m_pdOutData;  
  24.     double *m_pdBias;  
  25. };  
  26.   
  27. #endif // POOLLAYER_H  


poollayer.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "poollayer.h"  
  2. #include "util.h"  
  3. #include <cassert>  
  4.   
  5. PoolLayer::PoolLayer(int iOutImageNumber, int iPoolWidth, int iFeatureMapWidth):  
  6.     m_iOutImageNumber(iOutImageNumber),  
  7.     m_iPoolWidth(iPoolWidth),  
  8.     m_iFeatureMapWidth(iFeatureMapWidth)  
  9. {  
  10.     m_iPoolSize = m_iPoolWidth * m_iPoolWidth;  
  11.     m_iOutImageEdge = m_iFeatureMapWidth / m_iPoolWidth;  
  12.     m_iOutImageSize = m_iOutImageEdge * m_iOutImageEdge;  
  13.   
  14.     m_pdOutData = new double[m_iOutImageNumber * m_iOutImageSize];  
  15.     m_pdBias = new double[m_iOutImageNumber];  
  16.     /*for (int i = 0; i < m_iOutImageNumber; ++i) 
  17.     { 
  18.         m_pdBias[i] = 1; 
  19.     }*/  
  20.       
  21.   
  22. }  
  23.   
  24. PoolLayer::~PoolLayer()  
  25. {  
  26.     delete []m_pdOutData;  
  27.     delete []m_pdBias;  
  28. }  
  29.   
  30. void PoolLayer::Convolute(double *pdInputData)  
  31. {  
  32.     int iFeatureMapSize = m_iFeatureMapWidth * m_iFeatureMapWidth;  
  33.     for (int iOutImageIndex = 0; iOutImageIndex < m_iOutImageNumber; ++iOutImageIndex)  
  34.     {  
  35.         double dBias = m_pdBias[iOutImageIndex];  
  36.         for (int i = 0; i < m_iOutImageEdge; ++i)  
  37.         {  
  38.             for (int j = 0; j < m_iOutImageEdge; ++j)  
  39.             {  
  40.                 double dValue = 0.0;  
  41.                 int iInputIndex, iInputIndexStart, iOutIndex;  
  42.                 /************************************************************************/  
  43.                 /* 这里是最大的bug,dMaxPixel初始值设置为0,然后找最大值 
  44.                 ** 问题在于像素值有负数,导致后面一系列计算错误,实在是太难找了 
  45.                 /************************************************************************/  
  46.                 double dMaxPixel = INT_MIN ;  
  47.                 iOutIndex = iOutImageIndex * m_iOutImageSize + i * m_iOutImageEdge + j;  
  48.                 iInputIndexStart = iOutImageIndex * iFeatureMapSize + (i * m_iFeatureMapWidth + j) * m_iPoolWidth;  
  49.                 for (int m = 0; m < m_iPoolWidth; ++m)  
  50.                 {  
  51.                     for (int n = 0; n < m_iPoolWidth; ++n)  
  52.                     {  
  53.                         //                  int iPoolIndex = m * m_iPoolWidth + n;  
  54.                         //i am not sure, the expression of below is correct?  
  55.                         iInputIndex = iInputIndexStart + m * m_iFeatureMapWidth + n;  
  56.                         if (pdInputData[iInputIndex] > dMaxPixel)  
  57.                         {  
  58.                             dMaxPixel = pdInputData[iInputIndex];  
  59.                         }  
  60.                     }//end n  
  61.                 }//end m  
  62.                 dValue = dMaxPixel + dBias;  
  63.   
  64.                 assert(iOutIndex < m_iOutImageNumber * m_iOutImageSize);  
  65.                 //m_pdOutData[iOutIndex] = (dMaxPixel);  
  66.                 m_pdOutData[iOutIndex] = mytanh(dValue);  
  67.             }//end j  
  68.         }//end i  
  69.     }//end iOutImageIndex  
  70. }  
  71.   
  72. void PoolLayer::SetBias(const vector<double> &vecBias)  
  73. {  
  74.     assert(vecBias.size() == (DWORD)m_iOutImageNumber);  
  75.     for (int i = 0; i < m_iOutImageNumber; ++i)  
  76.     {  
  77.         m_pdBias[i] = vecBias[i];  
  78.     }  
  79. }  
  80.   
  81. double* PoolLayer::GetOutputData()  
  82. {  
  83.     assert(NULL != m_pdOutData);  
  84.     return m_pdOutData;  
  85. }  
  86.   
  87. void PoolLayer::PrintOutputData()  
  88. {  
  89.     for (int i  = 0; i < m_iOutImageNumber; ++i)  
  90.     {  
  91.         cout << "pool image " << i  <<endl;  
  92.         for (int m = 0; m < m_iOutImageEdge; ++m)  
  93.         {  
  94.             for (int n = 0; n < m_iOutImageEdge; ++n)  
  95.             {  
  96.                 cout << m_pdOutData[i * m_iOutImageSize + m * m_iOutImageEdge + n] << ' ';  
  97.             }  
  98.             cout << endl;  
  99.   
  100.         }  
  101.         cout <<endl;  
  102.   
  103.     }  
  104. }  


mlp.h

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef MLP_H  
  2. #define MLP_H  
  3.   
  4. #include "hiddenLayer.h"  
  5. #include "logisticRegression.h"  
  6.   
  7.   
  8.   
  9. class Mlp  
  10. {  
  11. public:  
  12.     Mlp(int n, int n_i, int n_o, int nhl, int *hls);  
  13.     ~Mlp();  
  14.   
  15.     //    void Train(double** in_data, double** in_label, double dLr, int epochs);  
  16.     void Predict(double** in_data, int n);  
  17.     void Train(double *x, WORD y, double dLr);  
  18.     void TrainAllSample(const vector<double*> &vecTrain, const vector<WORD> &vectrainlabel, double dLr);  
  19.     double CalErrorRate(const vector<double *> &vecvalid, const vector<WORD> &vecValidlabel);  
  20.     void Writewb(const char *szName);  
  21.     void Readwb(const char *szName);  
  22.   
  23.     void Setwb(vector< vector<double*> > &vvAllw, vector< vector<double> > &vvAllb);  
  24.     void SetTrainNum(int iNum);  
  25.   
  26.     int Predict(double *pInputData);  
  27.     //    void Forward_propagation(double** ppdata, int n);  
  28.     double* Forward_propagation(double *);  
  29.   
  30.     int* GetHiddenSize();  
  31.     int GetHiddenNumber();  
  32.     double *GetHiddenOutputData();  
  33.   
  34.     HiddenLayer **m_ppHiddenLayer;  
  35.     LogisticRegression *m_pLogisticLayer;  
  36.   
  37. private:  
  38.     int m_iSampleNum; //样本数量  
  39.     int m_iInput; //输入维数  
  40.     int m_iOut; //输出维数  
  41.     int m_iHiddenLayerNum; //隐层数目  
  42.     int* m_piHiddenLayerSize; //中间隐层的大小 e.g. {3,4}表示有两个隐层,第一个有三个节点,第二个有4个节点  
  43.   
  44.       
  45. };  
  46.   
  47. void mlp();  
  48. void TestMlpTheano(const int m_iInput, const int ihidden, const int m_iOut);  
  49. void TestMlpMnist(const int m_iInput, const int ihidden, const int m_iOut);  
  50.   
  51. #endif  


mlp.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <iostream>  
  2. #include "mlp.h"  
  3. #include "util.h"  
  4. #include <cassert>  
  5. #include <iomanip>  
  6.   
  7. using namespace std;  
  8.   
  9. const int m_iSamplenum = 8, innode = 3, outnode = 8;  
  10. Mlp::Mlp(int n, int n_i, int n_o, int nhl, int *hls)  
  11. {  
  12.     m_iSampleNum = n;  
  13.     m_iInput = n_i;  
  14.     m_iOut = n_o;  
  15.   
  16.     m_iHiddenLayerNum = nhl;  
  17.     m_piHiddenLayerSize = hls;  
  18.   
  19.     //构造网络结构  
  20.     m_ppHiddenLayer = new HiddenLayer* [m_iHiddenLayerNum];  
  21.     for(int i = 0; i < m_iHiddenLayerNum; ++i)  
  22.     {  
  23.         if(i == 0)  
  24.         {  
  25.             m_ppHiddenLayer[i] = new HiddenLayer(m_iInput, m_piHiddenLayerSize[i]);//第一个隐层  
  26.         }  
  27.         else  
  28.         {  
  29.             m_ppHiddenLayer[i] = new HiddenLayer(m_piHiddenLayerSize[i-1], m_piHiddenLayerSize[i]);//其他隐层  
  30.         }  
  31.     }  
  32.     if (m_iHiddenLayerNum > 0)  
  33.     {  
  34.         m_pLogisticLayer = new LogisticRegression(m_piHiddenLayerSize[m_iHiddenLayerNum - 1], m_iOut, m_iSampleNum);//最后的softmax层  
  35.     }  
  36.     else  
  37.     {  
  38.         m_pLogisticLayer = new LogisticRegression(m_iInput, m_iOut, m_iSampleNum);//最后的softmax层  
  39.   
  40.     }  
  41.       
  42. }  
  43.   
  44. Mlp::~Mlp()  
  45. {  
  46.     //二维指针分配的对象不一定是二维数组  
  47.     for(int i = 0; i < m_iHiddenLayerNum; ++i)  
  48.         delete m_ppHiddenLayer[i];  //删除的时候不能加[]  
  49.     delete[] m_ppHiddenLayer;  
  50.     //log_layer只是一个普通的对象指针,不能作为数组delete  
  51.     delete m_pLogisticLayer;//删除的时候不能加[]  
  52. }  
  53. void Mlp::TrainAllSample(const vector<double *> &vecTrain, const vector<WORD> &vectrainlabel, double dLr)  
  54. {  
  55.     cout << "Mlp::TrainAllSample" << endl;  
  56.     for (int j = 0; j < m_iSampleNum; ++j)  
  57.     {  
  58.         Train(vecTrain[j], vectrainlabel[j], dLr);  
  59.     }  
  60. }  
  61.   
  62. void Mlp::Train(double *pdTrain, WORD usLabel, double dLr)  
  63. {  
  64.   
  65.   
  66.     //    cout << "******pdLabel****" << endl;  
  67.     //  printArrDouble(ppdinLabel, m_iSampleNum, m_iOut);  
  68.   
  69.     double *pdLabel = new double[m_iOut];  
  70.     MakeOneLabel(usLabel, pdLabel, m_iOut);  
  71.   
  72.     //前向传播阶段  
  73.     for(int n = 0; n < m_iHiddenLayerNum; ++ n)  
  74.     {  
  75.         if(n == 0) //第一个隐层直接输入数据  
  76.         {  
  77.             m_ppHiddenLayer[n]->Forward_propagation(pdTrain);  
  78.         }  
  79.         else //其他隐层用前一层的输出作为输入数据  
  80.         {  
  81.             m_ppHiddenLayer[n]->Forward_propagation(m_ppHiddenLayer[n-1]->m_pdOutdata);  
  82.         }  
  83.     }  
  84.     //softmax层使用最后一个隐层的输出作为输入数据  
  85.     m_pLogisticLayer->Forward_propagation(m_ppHiddenLayer[m_iHiddenLayerNum-1]->m_pdOutdata);  
  86.   
  87.   
  88.     //反向传播阶段  
  89.     m_pLogisticLayer->Back_propagation(m_ppHiddenLayer[m_iHiddenLayerNum-1]->m_pdOutdata, pdLabel, dLr);  
  90.   
  91.     for(int n = m_iHiddenLayerNum-1; n >= 1; --n)  
  92.     {  
  93.         if(n == m_iHiddenLayerNum-1)  
  94.         {  
  95.             m_ppHiddenLayer[n]->Back_propagation(m_ppHiddenLayer[n-1]->m_pdOutdata,  
  96.                     m_pLogisticLayer->m_pdDelta, m_pLogisticLayer->m_ppdW, m_pLogisticLayer->m_iOut, dLr);  
  97.         }  
  98.         else  
  99.         {  
  100.             double *pdInputData;  
  101.             pdInputData = m_ppHiddenLayer[n-1]->m_pdOutdata;  
  102.   
  103.             m_ppHiddenLayer[n]->Back_propagation(pdInputData,  
  104.                                                 m_ppHiddenLayer[n+1]->m_pdDelta, m_ppHiddenLayer[n+1]->m_ppdW, m_ppHiddenLayer[n+1]->m_iOut, dLr);  
  105.         }  
  106.     }  
  107.     //这里该怎么写?  
  108.     if (m_iHiddenLayerNum > 1)  
  109.         m_ppHiddenLayer[0]->Back_propagation(pdTrain,  
  110.                                             m_ppHiddenLayer[1]->m_pdDelta, m_ppHiddenLayer[1]->m_ppdW, m_ppHiddenLayer[1]->m_iOut, dLr);  
  111.     else  
  112.         m_ppHiddenLayer[0]->Back_propagation(pdTrain,  
  113.                                             m_pLogisticLayer->m_pdDelta, m_pLogisticLayer->m_ppdW, m_pLogisticLayer->m_iOut, dLr);  
  114.   
  115.   
  116.     delete []pdLabel;  
  117. }  
  118. void Mlp::SetTrainNum(int iNum)  
  119. {  
  120.     m_iSampleNum = iNum;  
  121. }  
  122.   
  123. double* Mlp::Forward_propagation(double* pData)  
  124. {  
  125.     double *pdForwardValue = pData;  
  126.     for(int n = 0; n < m_iHiddenLayerNum; ++ n)  
  127.     {  
  128.         if(n == 0) //第一个隐层直接输入数据  
  129.         {  
  130.             pdForwardValue = m_ppHiddenLayer[n]->Forward_propagation(pData);  
  131.         }  
  132.         else //其他隐层用前一层的输出作为输入数据  
  133.         {  
  134.             pdForwardValue = m_ppHiddenLayer[n]->Forward_propagation(pdForwardValue);  
  135.         }  
  136.     }  
  137.     return pdForwardValue;  
  138.     //softmax层使用最后一个隐层的输出作为输入数据  
  139.     //    m_pLogisticLayer->Forward_propagation(m_ppHiddenLayer[m_iHiddenLayerNum-1]->m_pdOutdata);  
  140.   
  141.     //    m_pLogisticLayer->Predict(m_ppHiddenLayer[m_iHiddenLayerNum-1]->m_pdOutdata);  
  142.   
  143.      
  144. }  
  145.   
  146. int Mlp::Predict(double *pInputData)  
  147. {  
  148.     Forward_propagation(pInputData);  
  149.   
  150.     int iResult = m_pLogisticLayer->Predict(m_ppHiddenLayer[m_iHiddenLayerNum-1]->m_pdOutdata);  
  151.   
  152.     return iResult;  
  153.   
  154. }  
  155.   
  156. void Mlp::Setwb(vector< vector<double*> > &vvAllw, vector< vector<double> > &vvAllb)  
  157. {  
  158.     for (int i = 0; i < m_iHiddenLayerNum; ++i)  
  159.     {  
  160.         m_ppHiddenLayer[i]->Setwb(vvAllw[i], vvAllb[i]);  
  161.     }  
  162.     m_pLogisticLayer->Setwb(vvAllw[m_iHiddenLayerNum], vvAllb[m_iHiddenLayerNum]);  
  163. }  
  164.   
  165. void Mlp::Writewb(const char *szName)  
  166. {  
  167.     for(int i = 0; i < m_iHiddenLayerNum; ++i)  
  168.     {  
  169.         m_ppHiddenLayer[i]->Writewb(szName);  
  170.     }  
  171.     m_pLogisticLayer->Writewb(szName);  
  172.   
  173. }  
  174. double Mlp::CalErrorRate(const vector<double *> &vecvalid, const vector<WORD> &vecValidlabel)  
  175. {  
  176.     int iErrorNumber = 0, iValidNumber = vecValidlabel.size();  
  177.     for (int i = 0; i < iValidNumber; ++i)  
  178.     {  
  179.         int iResult = Predict(vecvalid[i]);  
  180.         if (iResult != vecValidlabel[i])  
  181.         {  
  182.             ++iErrorNumber;  
  183.         }  
  184.     }  
  185.   
  186.     cout << "the num of error is " << iErrorNumber << endl;  
  187.     double dErrorRate = (double)iErrorNumber / iValidNumber;  
  188.     cout << "the error rate of Train sample by softmax is " << setprecision(10) << dErrorRate * 100 << "%" << endl;  
  189.   
  190.     return dErrorRate;  
  191. }  
  192.   
  193. void Mlp::Readwb(const char *szName)  
  194. {  
  195.     long dcurpos = 0, dreadsize = 0;  
  196.     for(int i = 0; i < m_iHiddenLayerNum; ++i)  
  197.     {  
  198.         dreadsize = m_ppHiddenLayer[i]->Readwb(szName, dcurpos);  
  199.         cout << "hiddenlayer " << i + 1 << " read bytes: " << dreadsize << endl;  
  200.         if (-1 != dreadsize)  
  201.             dcurpos += dreadsize;  
  202.         else  
  203.         {  
  204.             cout << "read wb error from HiddenLayer" << endl;  
  205.             return;  
  206.         }  
  207.     }  
  208.     dreadsize = m_pLogisticLayer->Readwb(szName, dcurpos);  
  209.     if (-1 != dreadsize)  
  210.         dcurpos += dreadsize;  
  211.     else  
  212.     {  
  213.         cout << "read wb error from sofmaxLayer" << endl;  
  214.         return;  
  215.     }  
  216. }  
  217.   
  218. int* Mlp::GetHiddenSize()  
  219. {  
  220.     return m_piHiddenLayerSize;  
  221. }  
  222.   
  223. double* Mlp::GetHiddenOutputData()  
  224. {  
  225.     assert(m_iHiddenLayerNum > 0);  
  226.     return m_ppHiddenLayer[m_iHiddenLayerNum-1]->m_pdOutdata;  
  227. }  
  228.   
  229. int Mlp::GetHiddenNumber()  
  230. {  
  231.     return m_iHiddenLayerNum;  
  232. }  
  233.   
  234.   
  235.   
  236. //double **makeLabelSample(double **label_x)  
  237. double **makeLabelSample(double label_x[][outnode])  
  238. {  
  239.     double **pplabelSample;  
  240.     pplabelSample = new double*[m_iSamplenum];  
  241.     for (int i = 0; i < m_iSamplenum; ++i)  
  242.     {  
  243.         pplabelSample[i] = new double[outnode];  
  244.     }  
  245.   
  246.     for (int i = 0; i < m_iSamplenum; ++i)  
  247.     {  
  248.         for (int j = 0; j < outnode; ++j)  
  249.             pplabelSample[i][j] = label_x[i][j];  
  250.     }  
  251.     return pplabelSample;  
  252. }  
  253. double **maken_train(double train_x[][innode])  
  254. {  
  255.     double **ppn_train;  
  256.     ppn_train = new double*[m_iSamplenum];  
  257.     for (int i = 0; i < m_iSamplenum; ++i)  
  258.     {  
  259.         ppn_train[i] = new double[innode];  
  260.     }  
  261.   
  262.     for (int i = 0; i < m_iSamplenum; ++i)  
  263.     {  
  264.         for (int j = 0; j < innode; ++j)  
  265.             ppn_train[i][j] = train_x[i][j];  
  266.     }  
  267.     return ppn_train;  
  268. }  
  269.   
  270.   
  271. void TestMlpMnist(const int m_iInput, const int ihidden, const int m_iOut)  
  272. {  
  273.     const int ihiddenSize = 1;  
  274.     int phidden[ihiddenSize] = {ihidden};  
  275.     // construct LogisticRegression  
  276.     Mlp neural(m_iSamplenum, m_iInput, m_iOut, ihiddenSize, phidden);  
  277.   
  278.   
  279.     vector<double*> vecTrain, vecvalid;  
  280.   
  281.     vector<WORD> vecValidlabel, vectrainlabel;  
  282.   
  283.     LoadTestSampleFromJson(vecvalid, vecValidlabel, "../../data/mnist.json", m_iInput);  
  284.     LoadTestSampleFromJson(vecTrain, vectrainlabel, "../../data/mnisttrain.json", m_iInput);  
  285.   
  286.     // test  
  287.   
  288.     int itrainnum = vecTrain.size();  
  289.     neural.SetTrainNum(itrainnum);  
  290.   
  291.     const int iepochs = 1;  
  292.     const double dLr = 0.1;  
  293.     neural.CalErrorRate(vecvalid, vecValidlabel);  
  294.   
  295.     for (int i = 0; i < iepochs; ++i)  
  296.     {  
  297.         neural.TrainAllSample(vecTrain, vectrainlabel, dLr);  
  298.         neural.CalErrorRate(vecvalid, vecValidlabel);  
  299.   
  300.     }  
  301.   
  302.     for (vector<double*>::iterator cit = vecTrain.begin(); cit != vecTrain.end(); ++cit)  
  303.     {  
  304.         delete [](*cit);  
  305.     }  
  306.     for (vector<double*>::iterator cit = vecvalid.begin(); cit != vecvalid.end(); ++cit)  
  307.     {  
  308.         delete [](*cit);  
  309.     }  
  310. }  
  311.   
  312.   
  313. void TestMlpTheano(const int m_iInput, const int ihidden, const int m_iOut)  
  314. {  
  315.   
  316.     const int ihiddenSize = 1;  
  317.     int phidden[ihiddenSize] = {ihidden};  
  318.     // construct LogisticRegression  
  319.     Mlp neural(m_iSamplenum, m_iInput, m_iOut, ihiddenSize, phidden);  
  320.     vector<double*> vecTrain, vecw;  
  321.     vector<double> vecb;  
  322.     vector<WORD> vecLabel;  
  323.     vector< vector<double*> > vvAllw;  
  324.     vector< vector<double> > vvAllb;  
  325.     const char *pcfilename = "../../data/theanomlp.json";  
  326.       
  327.     vector<int> vecSecondDimOfWeigh;  
  328.     vecSecondDimOfWeigh.push_back(m_iInput);  
  329.     vecSecondDimOfWeigh.push_back(ihidden);  
  330.   
  331.     LoadWeighFromJson(vvAllw, vvAllb, pcfilename, vecSecondDimOfWeigh);  
  332.   
  333.     LoadTestSampleFromJson(vecTrain, vecLabel, "../../data/mnist_validall.json", m_iInput);  
  334.   
  335.   
  336.     cout << "loadwb ---------" << endl;  
  337.   
  338.     int itrainnum = vecTrain.size();  
  339.     neural.SetTrainNum(itrainnum);  
  340.   
  341.   
  342.     neural.Setwb(vvAllw, vvAllb);  
  343.   
  344.     cout << "Predict------------" << endl;  
  345.     neural.CalErrorRate(vecTrain, vecLabel);  
  346.       
  347.   
  348.     for (vector<double*>::iterator cit = vecTrain.begin(); cit != vecTrain.end(); ++cit)  
  349.     {  
  350.         delete [](*cit);  
  351.     }  
  352.   
  353. }  
  354.   
  355. void mlp()  
  356. {  
  357.     //输入样本  
  358.     double X[m_iSamplenum][innode]= {  
  359.         {0,0,0},{0,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{1,1,0},{1,1,1}  
  360.     };  
  361.   
  362.     double Y[m_iSamplenum][outnode]={  
  363.         {1, 0, 0, 0, 0, 0, 0, 0},  
  364.         {0, 1, 0, 0, 0, 0, 0, 0},  
  365.         {0, 0, 1, 0, 0, 0, 0, 0},  
  366.         {0, 0, 0, 1, 0, 0, 0, 0},  
  367.         {0, 0, 0, 0, 1, 0, 0, 0},  
  368.         {0, 0, 0, 0, 0, 1, 0, 0},  
  369.         {0, 0, 0, 0, 0, 0, 1, 0},  
  370.         {0, 0, 0, 0, 0, 0, 0, 1},  
  371.     };  
  372.     WORD pdLabel[outnode] = {0, 1, 2, 3, 4, 5, 6, 7};  
  373.     const int ihiddenSize = 2;  
  374.     int phidden[ihiddenSize] = {5, 5};  
  375.     //printArr(phidden, 1);  
  376.     Mlp neural(m_iSamplenum, innode, outnode, ihiddenSize, phidden);  
  377.     double **train_x, **ppdLabel;  
  378.     train_x = maken_train(X);  
  379.     //printArrDouble(train_x, m_iSamplenum, innode);  
  380.     ppdLabel = makeLabelSample(Y);  
  381.     for (int i = 0; i < 3500; ++i)  
  382.     {  
  383.         for (int j = 0; j < m_iSamplenum; ++j)  
  384.         {  
  385.             neural.Train(train_x[j], pdLabel[j], 0.1);  
  386.         }  
  387.     }  
  388.   
  389.     cout<<"trainning complete..."<<endl;  
  390.     for (int i = 0; i < m_iSamplenum; ++i)  
  391.         neural.Predict(train_x[i]);  
  392.     //szName存放权值  
  393.     //  const char *szName = "mlp55new.wb";  
  394.     //  neural.Writewb(szName);  
  395.   
  396.   
  397.     //  Mlp neural2(m_iSamplenum, innode, outnode, ihiddenSize, phidden);  
  398.     //  cout<<"Readwb start..."<<endl;  
  399.     //  neural2.Readwb(szName);  
  400.     //  cout<<"Readwb end..."<<endl;  
  401.   
  402.     //    cout << "----------after readwb________" << endl;  
  403.     //    for (int i = 0; i < m_iSamplenum; ++i)  
  404.     //        neural2.Forward_propagation(train_x[i]);  
  405.   
  406.     for (int i = 0; i != m_iSamplenum; ++i)  
  407.     {  
  408.         delete []train_x[i];  
  409.         delete []ppdLabel[i];  
  410.     }  
  411.     delete []train_x;  
  412.     delete []ppdLabel;  
  413.     cout<<endl;  
  414. }  


hiddenLayer.h

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef HIDDENLAYER_H  
  2. #define HIDDENLAYER_H  
  3.   
  4. #include "neuralbase.h"  
  5.   
  6. class HiddenLayer: public NeuralBase  
  7. {  
  8. public:  
  9.     HiddenLayer(int n_i, int n_o);  
  10.     ~HiddenLayer();  
  11.   
  12.     double* Forward_propagation(double* input_data);  
  13.       
  14.     void Back_propagation(double *pdInputData, double *pdNextLayerDelta,  
  15.                           double** ppdnextLayerW, int iNextLayerOutNum, double dLr);  
  16.       
  17.   
  18.   
  19. };  
  20.   
  21. #endif  


hiddenLayer.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <cmath>  
  2. #include <cassert>  
  3. #include <cstdlib>  
  4. #include <ctime>  
  5. #include <iostream>  
  6. #include "hiddenLayer.h"  
  7. #include "util.h"  
  8.   
  9. using namespace std;  
  10.   
  11.   
  12.   
  13. HiddenLayer::HiddenLayer(int n_i, int n_o): NeuralBase(n_i, n_o, 0)  
  14. {  
  15. }  
  16.   
  17. HiddenLayer::~HiddenLayer()  
  18. {  
  19.   
  20. }  
  21.   
  22. /************************************************************************/  
  23. /* 需要注意的是: 
  24. 如果为了复现theano的测试结果,那么隐藏层的激活函数要选用tanh; 
  25. 否则,为了mlp的训练过程,激活函数要选择sigmoid                                                                     */  
  26. /************************************************************************/  
  27. double* HiddenLayer::Forward_propagation(double* pdInputData)  
  28. {  
  29.     NeuralBase::Forward_propagation(pdInputData);  
  30.     for(int i = 0; i < m_iOut; ++i)  
  31.     {  
  32.        // m_pdOutdata[i] = sigmoid(m_pdOutdata[i]);  
  33.         m_pdOutdata[i] = mytanh(m_pdOutdata[i]);  
  34.   
  35.     }  
  36.     return m_pdOutdata;  
  37. }  
  38.   
  39. void HiddenLayer::Back_propagation(double *pdInputData, double *pdNextLayerDelta,  
  40.                                    double** ppdnextLayerW, int iNextLayerOutNum, double dLr)  
  41. {  
  42.     /* 
  43.     pdInputData          为输入数据 
  44.     *pdNextLayerDelta   为下一层的残差值delta,是一个大小为iNextLayerOutNum的数组 
  45.     **ppdnextLayerW      为此层到下一层的权值 
  46.     iNextLayerOutNum    实际上就是下一层的n_out 
  47.     dLr                  为学习率learning rate 
  48.     m_iSampleNum                   为训练样本总数 
  49.     */  
  50.   
  51.     //sigma元素个数应与本层单元个数一致,而网上代码有误  
  52.     //作者是没有自己测试啊,测试啊  
  53.     //double* sigma = new double[iNextLayerOutNum];  
  54.     double* sigma = new double[m_iOut];  
  55.     //double sigma[10];  
  56.     for(int i = 0; i < m_iOut; ++i)  
  57.         sigma[i] = 0.0;  
  58.   
  59.     for(int i = 0; i < iNextLayerOutNum; ++i)  
  60.     {  
  61.         for(int j = 0; j < m_iOut; ++j)  
  62.         {  
  63.             sigma[j] += ppdnextLayerW[i][j] * pdNextLayerDelta[i];  
  64.         }  
  65.     }  
  66.     //计算得到本层的残差delta  
  67.     for(int i = 0; i < m_iOut; ++i)  
  68.     {  
  69.         m_pdDelta[i] = sigma[i] * m_pdOutdata[i] * (1 - m_pdOutdata[i]);  
  70.     }  
  71.   
  72.     //调整本层的权值w  
  73.     for(int i = 0; i < m_iOut; ++i)  
  74.     {  
  75.         for(int j = 0; j < m_iInput; ++j)  
  76.         {  
  77.             m_ppdW[i][j] += dLr * m_pdDelta[i] * pdInputData[j];  
  78.         }  
  79.         m_pdBias[i] += dLr * m_pdDelta[i];  
  80.     }  
  81.     delete[] sigma;  
  82. }  


logisticRegression.h

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef LOGISTICREGRESSIONLAYER  
  2. #define LOGISTICREGRESSIONLAYER  
  3. #include "neuralbase.h"  
  4.   
  5. typedef unsigned short WORD;  
  6.   
  7. class LogisticRegression: public NeuralBase  
  8. {  
  9. public:  
  10.     LogisticRegression(int n_i, int i_o, int);  
  11.     ~LogisticRegression();  
  12.   
  13.     double* Forward_propagation(double* input_data);  
  14.     void Softmax(double* x);  
  15.     void Train(double *pdTrain, WORD usLabel, double dLr);  
  16.   
  17.   
  18.     void SetOldWb(double ppdWeigh[][3], double arriBias[8]);  
  19.     int Predict(double *);  
  20.   
  21.     void MakeLabels(int* piMax, double (*pplabels)[8]);  
  22. };  
  23.   
  24. void Test_lr();  
  25. void Testwb();  
  26. void Test_theano(const int m_iInput, const int m_iOut);  
  27. #endif  


logisticRegression.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <cmath>  
  2. #include <cassert>  
  3. #include <iomanip>  
  4. #include <ctime>  
  5. #include <iostream>  
  6. #include "logisticRegression.h"  
  7. #include "util.h"  
  8.   
  9. using namespace std;  
  10.   
  11.   
  12. LogisticRegression::LogisticRegression(int n_i, int n_o, int n_t): NeuralBase(n_i, n_o, n_t)  
  13. {  
  14.   
  15. }  
  16.   
  17. LogisticRegression::~LogisticRegression()  
  18. {  
  19.   
  20. }  
  21.   
  22.   
  23.   
  24. void LogisticRegression::Softmax(double* x)  
  25. {  
  26.     double _max = 0.0;  
  27.     double _sum = 0.0;  
  28.   
  29.     for(int i = 0; i < m_iOut; ++i)  
  30.     {  
  31.         if(_max < x[i])  
  32.             _max = x[i];  
  33.     }  
  34.     for(int i = 0; i < m_iOut; ++i)  
  35.     {  
  36.         x[i] = exp(x[i]-_max);  
  37.         _sum += x[i];  
  38.     }  
  39.   
  40.     for(int i = 0; i < m_iOut; ++i)  
  41.     {  
  42.         x[i] /= _sum;  
  43.     }  
  44. }  
  45.   
  46. double* LogisticRegression::Forward_propagation(double* pdinputdata)  
  47. {  
  48.     NeuralBase::Forward_propagation(pdinputdata);  
  49.     /************************************************************************/  
  50.     /* 调试                                                                     */  
  51.     /************************************************************************/  
  52.     //cout << "Forward_propagation from   LogisticRegression" << endl;  
  53.     //PrintOutputData();  
  54.     //cout << "over\n";  
  55.     Softmax(m_pdOutdata);  
  56.     return m_pdOutdata;  
  57. }  
  58.   
  59.   
  60. int LogisticRegression::Predict(double *pdtest)  
  61. {  
  62.     Forward_propagation(pdtest);  
  63.     /************************************************************************/  
  64.     /* 调试使用                                                                     */  
  65.     /************************************************************************/  
  66.     //PrintOutputData();  
  67.     int iResult = getMaxIndex(m_pdOutdata, m_iOut);  
  68.   
  69.     return iResult;  
  70.   
  71. }  
  72. void LogisticRegression::Train(double *pdTrain, WORD usLabel, double dLr)  
  73. {  
  74.     Forward_propagation(pdTrain);  
  75.     double *pdLabel = new double[m_iOut];  
  76.     MakeOneLabel(usLabel, pdLabel);  
  77.     Back_propagation(pdTrain, pdLabel, dLr);  
  78.   
  79.     delete []pdLabel;  
  80. }  
  81. //double LogisticRegression::CalErrorRate(const vector<double*> &vecvalid, const vector<WORD> &vecValidlabel)  
  82. //{  
  83. //    int iErrorNumber = 0, iValidNumber = vecValidlabel.size();  
  84. //    for (int i = 0; i < iValidNumber; ++i)  
  85. //    {  
  86. //        int iResult = Predict(vecvalid[i]);  
  87. //        if (iResult != vecValidlabel[i])  
  88. //        {  
  89. //            ++iErrorNumber;  
  90. //        }  
  91. //    }  
  92.   
  93. //    cout << "the num of error is " << iErrorNumber << endl;  
  94. //    double dErrorRate = (double)iErrorNumber / iValidNumber;  
  95. //    cout << "the error rate of Train sample by softmax is " << setprecision(10) << dErrorRate * 100 << "%" << endl;  
  96.   
  97. //    return dErrorRate;  
  98. //}  
  99.   
  100.   
  101.   
  102. void LogisticRegression::SetOldWb(double ppdWeigh[][3], double arriBias[8])  
  103. {  
  104.     for (int i = 0; i < m_iOut; ++i)  
  105.     {  
  106.         for (int j = 0; j < m_iInput; ++j)  
  107.             m_ppdW[i][j] = ppdWeigh[i][j];  
  108.         m_pdBias[i] = arriBias[i];  
  109.     }  
  110.     cout << "Setwb----------" << endl;  
  111.     printArrDouble(m_ppdW, m_iOut, m_iInput);  
  112.     printArr(m_pdBias, m_iOut);  
  113. }  
  114.   
  115. //void LogisticRegression::TrainAllSample(const vector<double*> &vecTrain, const vector<WORD> &vectrainlabel, double dLr)  
  116. //{  
  117. //    for (int j = 0; j < m_iSamplenum; ++j)  
  118. //    {  
  119. //        Train(vecTrain[j], vectrainlabel[j], dLr);  
  120. //    }  
  121. //}  
  122.   
  123. void LogisticRegression::MakeLabels(int* piMax, double (*pplabels)[8])  
  124. {  
  125.     for (int i = 0; i < m_iSamplenum; ++i)  
  126.     {  
  127.         for (int j = 0; j < m_iOut; ++j)  
  128.             pplabels[i][j] = 0;  
  129.         int k = piMax[i];  
  130.         pplabels[i][k] = 1.0;  
  131.     }  
  132. }  
  133. void Test_theano(const int m_iInput, const int m_iOut)  
  134. {  
  135.   
  136.     // construct LogisticRegression  
  137.     LogisticRegression classifier(m_iInput, m_iOut, 0);  
  138.   
  139.     vector<double*> vecTrain, vecvalid, vecw;  
  140.     vector<double> vecb;  
  141.     vector<WORD> vecValidlabel, vectrainlabel;  
  142.   
  143.     LoadTestSampleFromJson(vecvalid, vecValidlabel, "../.../../data/mnist.json", m_iInput);  
  144.     LoadTestSampleFromJson(vecTrain, vectrainlabel, "../.../../data/mnisttrain.json", m_iInput);  
  145.   
  146.      // test  
  147.   
  148.     int itrainnum = vecTrain.size();  
  149.     classifier.m_iSamplenum = itrainnum;  
  150.   
  151.     const int iepochs = 5;  
  152.     const double dLr = 0.1;  
  153.     for (int i = 0; i < iepochs; ++i)  
  154.     {  
  155.         classifier.TrainAllSample(vecTrain, vectrainlabel, dLr);  
  156.   
  157.         if (i % 2 == 0)  
  158.         {  
  159.             cout << "Predict------------" << i + 1 << endl;  
  160.             classifier.CalErrorRate(vecvalid, vecValidlabel);  
  161.   
  162.         }  
  163.     }  
  164.   
  165.   
  166.   
  167.     for (vector<double*>::iterator cit = vecTrain.begin(); cit != vecTrain.end(); ++cit)  
  168.     {  
  169.         delete [](*cit);  
  170.     }  
  171.     for (vector<double*>::iterator cit = vecvalid.begin(); cit != vecvalid.end(); ++cit)  
  172.     {  
  173.         delete [](*cit);  
  174.     }  
  175. }  
  176.   
  177. void Test_lr()  
  178. {  
  179.     srand(0);  
  180.   
  181.     double learning_rate = 0.1;  
  182.     double n_epochs = 200;  
  183.   
  184.     int test_N = 2;  
  185.     const int trainNum = 8, m_iInput = 3, m_iOut = 8;  
  186.     //int m_iOut = 2;  
  187.     double train_X[trainNum][m_iInput] = {  
  188.         {1, 1, 1},  
  189.         {1, 1, 0},  
  190.         {1, 0, 1},  
  191.         {1, 0, 0},  
  192.         {0, 1, 1},  
  193.         {0, 1, 0},  
  194.         {0, 0, 1},  
  195.         {0, 0, 0}  
  196.     };  
  197.     //sziMax存储的是最大值的下标  
  198.     int sziMax[trainNum];  
  199.     for (int i = 0; i < trainNum; ++i)  
  200.         sziMax[i] = trainNum - i - 1;  
  201.       
  202.     // construct LogisticRegression  
  203.     LogisticRegression classifier(m_iInput, m_iOut, trainNum);  
  204.   
  205.     // Train online  
  206.     for(int epoch=0; epoch<n_epochs; epoch++) {  
  207.         for(int i=0; i<trainNum; i++) {  
  208.             //classifier.trainEfficient(train_X[i], train_Y[i], learning_rate);  
  209.             classifier.Train(train_X[i], sziMax[i], learning_rate);  
  210.         }  
  211.     }  
  212.   
  213.     const char *pcfile = "test.wb";  
  214.     classifier.Writewb(pcfile);  
  215.   
  216.     LogisticRegression logistic(m_iInput, m_iOut, trainNum);  
  217.     logistic.Readwb(pcfile, 0);  
  218.     // test data  
  219.     double test_X[2][m_iOut] = {  
  220.         {1, 0, 1},  
  221.         {0, 0, 1}  
  222.     };  
  223.      // test  
  224.     cout << "before Readwb ---------" << endl;  
  225.     for(int i=0; i<test_N; i++) {  
  226.         classifier.Predict(test_X[i]);  
  227.         cout << endl;  
  228.     }  
  229.     cout << "after Readwb ---------" << endl;  
  230.     for(int i=0; i<trainNum; i++) {  
  231.         logistic.Predict(train_X[i]);  
  232.         cout << endl;  
  233.     }  
  234.     cout << "*********\n";  
  235.      
  236. }  
  237. void Testwb()  
  238. {  
  239.   
  240.   
  241. //    int test_N = 2;  
  242.     const int trainNum = 8, m_iInput = 3, m_iOut = 8;  
  243.     //int m_iOut = 2;  
  244.     double train_X[trainNum][m_iInput] = {  
  245.         {1, 1, 1},  
  246.         {1, 1, 0},  
  247.         {1, 0, 1},  
  248.         {1, 0, 0},  
  249.         {0, 1, 1},  
  250.         {0, 1, 0},  
  251.         {0, 0, 1},  
  252.         {0, 0, 0}  
  253.     };  
  254.     double arriBias[m_iOut] = {1, 2, 3, 3, 3, 3, 2, 1};  
  255.       
  256.       
  257.     // construct LogisticRegression  
  258.     LogisticRegression classifier(m_iInput, m_iOut, trainNum);  
  259.   
  260.     classifier.SetOldWb(train_X, arriBias);  
  261.   
  262.     const char *pcfile = "test.wb";  
  263.     classifier.Writewb(pcfile);  
  264.   
  265.     LogisticRegression logistic(m_iInput, m_iOut, trainNum);  
  266.     logistic.Readwb(pcfile, 0);  
  267.   
  268. }  


neuralbase.h

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef NEURALBASE_H  
  2. #define NEURALBASE_H  
  3.   
  4. #include <vector>  
  5. using std::vector;  
  6. typedef unsigned short WORD;  
  7.   
  8. class NeuralBase  
  9. {  
  10. public:  
  11.     NeuralBase(int , int , int);  
  12.     virtual ~NeuralBase();  
  13.   
  14.     virtual double* Forward_propagation(double* );  
  15.     virtual void Back_propagation(double* , double* , double );  
  16.   
  17.     virtual void Train(double *x, WORD y, double dLr);  
  18.     virtual int Predict(double *);  
  19.   
  20.   
  21.     void Callbackwb();  
  22.     void MakeOneLabel(int iMax, double *pdLabel);  
  23.   
  24.     void TrainAllSample(const vector<double*> &vecTrain, const vector<WORD> &vectrainlabel, double dLr);  
  25.   
  26.     double CalErrorRate(const vector<double*> &vecvalid, const vector<WORD> &vecValidlabel);  
  27.   
  28.     void Printwb();  
  29.     void Writewb(const char *szName);  
  30.     long Readwb(const char *szName, long);  
  31.     void Setwb(vector<double*> &vpdw, vector<double> &vdb);  
  32.     void PrintOutputData();  
  33.   
  34.   
  35.     int m_iInput;  
  36.     int m_iOut;  
  37.     int m_iSamplenum;  
  38.     double** m_ppdW;  
  39.     double* m_pdBias;  
  40.     //本层前向传播的输出值,也是最终的预测值  
  41.     double* m_pdOutdata;  
  42.     //反向传播时所需值  
  43.     double* m_pdDelta;  
  44. private:  
  45.     void _callbackwb();  
  46.   
  47. };  
  48.   
  49. #endif // NEURALBASE_H  


neuralbase.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "neuralbase.h"  
  2.   
  3. #include <cmath>  
  4. #include <cassert>  
  5. #include <ctime>  
  6.   
  7. #include <iomanip>  
  8. #include <iostream>  
  9.   
  10.   
  11. #include "util.h"  
  12.   
  13. using namespace std;  
  14.   
  15.   
  16. NeuralBase::NeuralBase(int n_i, int n_o, int n_t):m_iInput(n_i), m_iOut(n_o), m_iSamplenum(n_t)  
  17. {  
  18.     m_ppdW = new double* [m_iOut];  
  19.     for(int i = 0; i < m_iOut; ++i)  
  20.     {  
  21.         m_ppdW[i] = new double [m_iInput];  
  22.     }  
  23.     m_pdBias = new double [m_iOut];  
  24.   
  25.     double a = 1.0 / m_iInput;  
  26.   
  27.     srand((unsigned)time(NULL));  
  28.     for(int i = 0; i < m_iOut; ++i)  
  29.     {  
  30.         for(int j = 0; j < m_iInput; ++j)  
  31.             m_ppdW[i][j] = uniform(-a, a);  
  32.         m_pdBias[i] = uniform(-a, a);  
  33.     }  
  34.   
  35.     m_pdDelta = new double [m_iOut];  
  36.     m_pdOutdata = new double [m_iOut];  
  37. }  
  38.   
  39. NeuralBase::~NeuralBase()  
  40. {  
  41.     Callbackwb();  
  42.     delete[] m_pdOutdata;  
  43.     delete[] m_pdDelta;  
  44. }  
  45. void NeuralBase::Callbackwb()  
  46. {  
  47.     _callbackwb();  
  48. }  
  49. double NeuralBase::CalErrorRate(const vector<double *> &vecvalid, const vector<WORD> &vecValidlabel)  
  50. {  
  51.     int iErrorNumber = 0, iValidNumber = vecValidlabel.size();  
  52.     for (int i = 0; i < iValidNumber; ++i)  
  53.     {  
  54.         int iResult = Predict(vecvalid[i]);  
  55.         if (iResult != vecValidlabel[i])  
  56.         {  
  57.             ++iErrorNumber;  
  58.         }  
  59.     }  
  60.   
  61.     cout << "the num of error is " << iErrorNumber << endl;  
  62.     double dErrorRate = (double)iErrorNumber / iValidNumber;  
  63.     cout << "the error rate of Train sample by softmax is " << setprecision(10) << dErrorRate * 100 << "%" << endl;  
  64.   
  65.     return dErrorRate;  
  66. }  
  67. int NeuralBase::Predict(double *)  
  68. {  
  69.     cout << "NeuralBase::Predict(double *)" << endl;  
  70.     return 0;  
  71. }  
  72.   
  73. void NeuralBase::_callbackwb()  
  74. {  
  75.     for(int i=0; i < m_iOut; i++)  
  76.         delete []m_ppdW[i];  
  77.     delete[] m_ppdW;  
  78.     delete[] m_pdBias;  
  79. }  
  80.   
  81. void NeuralBase::Printwb()  
  82. {  
  83.     cout << "'****m_ppdW****\n";  
  84.     for(int i = 0; i < m_iOut; ++i)  
  85.     {  
  86.         for(int j = 0; j < m_iInput; ++j)  
  87.             cout << m_ppdW[i][j] << ' ';  
  88.         cout << endl;  
  89.     }  
  90.     cout << "'****m_pdBias****\n";  
  91.     for(int i = 0; i < m_iOut; ++i)  
  92.     {  
  93.         cout << m_pdBias[i] << ' ';  
  94.     }  
  95.     cout << endl;  
  96.     cout << "'****output****\n";  
  97.     for(int i = 0; i < m_iOut; ++i)  
  98.     {  
  99.         cout << m_pdOutdata[i] << ' ';  
  100.     }  
  101.     cout << endl;  
  102.   
  103. }  
  104.   
  105.   
  106. double* NeuralBase::Forward_propagation(double* input_data)  
  107. {  
  108.     for(int i = 0; i < m_iOut; ++i)  
  109.     {  
  110.         m_pdOutdata[i] = 0.0;  
  111.         for(int j = 0; j < m_iInput; ++j)  
  112.         {  
  113.             m_pdOutdata[i] += m_ppdW[i][j]*input_data[j];  
  114.         }  
  115.         m_pdOutdata[i] += m_pdBias[i];  
  116.     }  
  117.     return m_pdOutdata;  
  118. }  
  119.   
  120. void NeuralBase::Back_propagation(double* input_data, double* pdlabel, double dLr)  
  121. {  
  122.     for(int i = 0; i < m_iOut; ++i)  
  123.     {  
  124.         m_pdDelta[i] = pdlabel[i] - m_pdOutdata[i] ;  
  125.         for(int j = 0; j < m_iInput; ++j)  
  126.         {  
  127.             m_ppdW[i][j] += dLr * m_pdDelta[i] * input_data[j] / m_iSamplenum;  
  128.         }  
  129.         m_pdBias[i] += dLr * m_pdDelta[i] / m_iSamplenum;  
  130.     }  
  131. }  
  132. void NeuralBase::MakeOneLabel(int imax, double *pdlabel)  
  133. {  
  134.     for (int j = 0; j < m_iOut; ++j)  
  135.         pdlabel[j] = 0;  
  136.     pdlabel[imax] = 1.0;  
  137. }  
  138. void NeuralBase::Writewb(const char *szName)  
  139. {  
  140.     savewb(szName, m_ppdW, m_pdBias, m_iOut, m_iInput);  
  141. }  
  142. long NeuralBase::Readwb(const char *szName, long dstartpos)  
  143. {  
  144.     return loadwb(szName, m_ppdW, m_pdBias, m_iOut, m_iInput, dstartpos);  
  145. }  
  146.   
  147. void NeuralBase::Setwb(vector<double*> &vpdw, vector<double> &vdb)  
  148. {  
  149.     assert(vpdw.size() == (DWORD)m_iOut);  
  150.     for (int i = 0; i < m_iOut; ++i)  
  151.     {  
  152.         delete []m_ppdW[i];  
  153.         m_ppdW[i] = vpdw[i];  
  154.         m_pdBias[i] = vdb[i];  
  155.     }  
  156. }  
  157.   
  158. void NeuralBase::TrainAllSample(const vector<double *> &vecTrain, const vector<WORD> &vectrainlabel, double dLr)  
  159. {  
  160.     for (int j = 0; j < m_iSamplenum; ++j)  
  161.     {  
  162.         Train(vecTrain[j], vectrainlabel[j], dLr);  
  163.     }  
  164. }  
  165. void NeuralBase::Train(double *x, WORD y, double dLr)  
  166. {  
  167.     (void)x;  
  168.     (void)y;  
  169.     (void)dLr;  
  170.     cout << "NeuralBase::Train(double *x, WORD y, double dLr)" << endl;  
  171. }  
  172.   
  173. void NeuralBase::PrintOutputData()  
  174. {  
  175.     for (int i = 0; i < m_iOut; ++i)  
  176.     {  
  177.         cout << m_pdOutdata[i] << ' ';  
  178.     }  
  179.     cout << endl;  
  180.       
  181.   
  182. }  


util.h

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef UTIL_H  
  2. #define UTIL_H  
  3. #include <iostream>  
  4. #include <cstdio>  
  5. #include <cstdlib>  
  6. #include <ctime>  
  7. #include <vector>  
  8.   
  9. using namespace std;  
  10.   
  11.   
  12. typedef unsigned char BYTE;  
  13. typedef unsigned short WORD;  
  14. typedef unsigned int DWORD;  
  15.   
  16. double sigmoid(double x);  
  17. double mytanh(double dx);  
  18.   
  19. typedef struct stShapeWb  
  20. {  
  21.     stShapeWb(int w, int h):width(w), height(h){}  
  22.     int width;  
  23.     int height;  
  24. }ShapeWb_S;  
  25.   
  26. void MakeOneLabel(int iMax, double *pdLabel, int m_iOut);  
  27.   
  28. double uniform(double _min, double _max);  
  29. //void printArr(T *parr, int num);  
  30. //void printArrDouble(double **pparr, int row, int col);  
  31. void initArr(double *parr, int num);  
  32. int getMaxIndex(double *pdarr, int num);  
  33. void Printivec(const vector<int> &ivec);  
  34. void savewb(const char *szName, double **m_ppdW, double *m_pdBias,  
  35.              int irow, int icol);  
  36. long loadwb(const char *szName, double **m_ppdW, double *m_pdBias,  
  37.             int irow, int icol, long dstartpos);  
  38.   
  39. void TestLoadJson(const char *pcfilename);  
  40. bool LoadvtFromJson(vector<double*> &vecTrain, vector<WORD> &vecLabel, const char *filename, const int m_iInput);  
  41. bool LoadwbFromJson(vector<double*> &vecTrain, vector<double> &vecLabel, const char *filename, const int m_iInput);  
  42. bool LoadTestSampleFromJson(vector<double*> &vecTrain, vector<WORD> &vecLabel, const char *filename, const int m_iInput);  
  43. bool LoadwbByByte(vector<double*> &vecTrain, vector<double> &vecLabel, const char *filename, const int m_iInput);  
  44. bool LoadallwbByByte(vector< vector<double*> > &vvAllw, vector< vector<double> > &vvAllb, const char *filename,  
  45.                      const int m_iInput, const int ihidden, const int m_iOut);  
  46. bool LoadWeighFromJson(vector< vector<double*> > &vvAllw, vector< vector<double> > &vvAllb,  
  47.                      const char *filename, const vector<int> &vecSecondDimOfWeigh);  
  48. void MakeCnnSample(double arr[2][64], double *pdImage, int iImageWidth, int iNumOfImage );  
  49. void MakeCnnWeigh(double *, int iNumOfKernel);  
  50. template <typename T>  
  51. void printArr(T *parr, int num)  
  52. {  
  53.     cout << "****printArr****" << endl;  
  54.   
  55.     for (int i = 0; i < num; ++i)  
  56.         cout << parr[i] << ' ';  
  57.     cout << endl;  
  58. }  
  59. template <typename T>  
  60. void printArrDouble(T **pparr, int row, int col)  
  61. {  
  62.     cout << "****printArrDouble****" << endl;  
  63.     for (int i = 0; i < row; ++i)  
  64.     {  
  65.         for (int j = 0; j < col; ++j)  
  66.         {  
  67.             cout << pparr[i][j] << ' ';  
  68.         }  
  69.         cout << endl;  
  70.     }  
  71. }  
  72.   
  73.   
  74. #endif  


util.cpp

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "util.h"  
  2. #include <iostream>  
  3. #include <ctime>  
  4. #include <cmath>  
  5. #include <cassert>  
  6. #include <fstream>  
  7. #include <cstring>  
  8. #include <stack>  
  9. #include <iomanip>  
  10.   
  11. using namespace std;  
  12.   
  13. int getMaxIndex(double *pdarr, int num)  
  14. {  
  15.     double dmax = -1;  
  16.     int iMax = -1;  
  17.     for(int i = 0; i < num; ++i)  
  18.     {  
  19.         if (pdarr[i] > dmax)  
  20.         {  
  21.             dmax = pdarr[i];  
  22.             iMax = i;  
  23.         }  
  24.     }  
  25.     return iMax;  
  26. }  
  27.   
  28. double sigmoid(double dx)  
  29. {  
  30.     return 1.0/(1.0+exp(-dx));  
  31. }  
  32. double mytanh(double dx)  
  33. {  
  34.     double e2x = exp(2 * dx);  
  35.     return (e2x - 1) / (e2x + 1);  
  36. }  
  37.   
  38. double uniform(double _min, double _max)  
  39. {  
  40.     return rand()/(RAND_MAX + 1.0) * (_max - _min) + _min;  
  41. }  
  42.   
  43. void initArr(double *parr, int num)  
  44. {  
  45.     for (int i = 0; i < num; ++i)  
  46.         parr[i] = 0.0;  
  47. }  
  48.   
  49.   
  50.   
  51. void savewb(const char *szName, double **m_ppdW, double *m_pdBias,  
  52.              int irow, int icol)  
  53. {  
  54.     FILE *pf;  
  55.     if( (pf = fopen(szName, "ab" )) == NULL )   
  56.     {   
  57.         printf( "File coulkd not be opened " );   
  58.         return;  
  59.     }   
  60.   
  61.     int isizeofelem = sizeof(double);  
  62.     for (int i = 0; i < irow; ++i)  
  63.     {  
  64.         if (fwrite((const void*)m_ppdW[i], isizeofelem, icol, pf) != icol)  
  65.         {  
  66.             fputs ("Writing m_ppdW error",stderr);  
  67.             return;  
  68.         }  
  69.     }  
  70.     if (fwrite((const void*)m_pdBias, isizeofelem, irow, pf) != irow)  
  71.     {  
  72.         fputs ("Writing m_ppdW error",stderr);  
  73.         return;  
  74.     }  
  75.     fclose(pf);  
  76. }  
  77. long loadwb(const char *szName, double **m_ppdW, double *m_pdBias,  
  78.             int irow, int icol, long dstartpos)  
  79. {  
  80.     FILE *pf;  
  81.     long dtotalbyte = 0, dreadsize;  
  82.     if( (pf = fopen(szName, "rb" )) == NULL )   
  83.     {   
  84.         printf( "File coulkd not be opened " );   
  85.         return -1;  
  86.     }   
  87.     //让文件指针偏移到正确位置  
  88.     fseek(pf, dstartpos , SEEK_SET);  
  89.   
  90.     int isizeofelem = sizeof(double);  
  91.     for (int i = 0; i < irow; ++i)  
  92.     {  
  93.         dreadsize = fread((void*)m_ppdW[i], isizeofelem, icol, pf);  
  94.         if (dreadsize != icol)  
  95.         {  
  96.             fputs ("Reading m_ppdW error",stderr);  
  97.             return -1;  
  98.         }  
  99.         //每次成功读取,都要加到dtotalbyte中,最后返回  
  100.         dtotalbyte += dreadsize;  
  101.     }  
  102.     dreadsize = fread(m_pdBias, isizeofelem, irow, pf);  
  103.     if (dreadsize != irow)  
  104.     {  
  105.         fputs ("Reading m_pdBias error",stderr);  
  106.         return -1;  
  107.     }  
  108.     dtotalbyte += dreadsize;  
  109.     dtotalbyte *= isizeofelem;  
  110.     fclose(pf);  
  111.     return dtotalbyte;    
  112. }  
  113.   
  114. void Printivec(const vector<int> &ivec)  
  115. {  
  116.     for (vector<int>::const_iterator it = ivec.begin(); it != ivec.end(); ++it)  
  117.     {  
  118.         cout << *it << ' ';  
  119.     }  
  120.     cout << endl;  
  121. }  
  122. void TestLoadJson(const char *pcfilename)  
  123. {  
  124.     vector<double *> vpdw;  
  125.     vector<double> vdb;  
  126.     vector< vector<double*> > vvAllw;  
  127.     vector< vector<double> > vvAllb;  
  128.     int m_iInput = 28 * 28, ihidden = 500, m_iOut = 10;  
  129.     LoadallwbByByte(vvAllw, vvAllb, pcfilename, m_iInput, ihidden, m_iOut );  
  130.   
  131.   
  132. }  
  133.   
  134. //read vt from mnist, format is [[[], [],..., []],[1, 3, 5,..., 7]]  
  135. bool LoadvtFromJson(vector<double*> &vecTrain, vector<WORD> &vecLabel, const char *filename, const int m_iInput)  
  136. {  
  137.     cout << "loadvtFromJson" << endl;  
  138.     const int ciStackSize = 10;  
  139.     const int ciFeaturesize = m_iInput;  
  140.     int arriStack[ciStackSize], iTop = -1;  
  141.   
  142.     ifstream ifs;  
  143.     ifs.open(filename, ios::in);  
  144.     assert(ifs.is_open());  
  145.     BYTE ucRead, ucLeftbrace, ucRightbrace, ucComma, ucSpace;  
  146.     ucLeftbrace = '[';  
  147.     ucRightbrace = ']';  
  148.     ucComma = ',';  
  149.     ucSpace = '0';  
  150.     ifs >> ucRead;  
  151.     assert(ucRead == ucLeftbrace);  
  152.     //栈中全部存放左括号,用1代表,0说明清除  
  153.     arriStack[++iTop] = 1;  
  154.     //样本train开始  
  155.     ifs >> ucRead;  
  156.     assert(ucRead == ucLeftbrace);  
  157.     arriStack[++iTop] = 1;//iTop is 1  
  158.     int iIndex;  
  159.     bool isdigit = false;  
  160.     double dread, *pdvt;  
  161.     //load vt sample  
  162.     while (iTop > 0)  
  163.     {  
  164.         if (isdigit == false)  
  165.         {  
  166.             ifs >> ucRead;  
  167.             isdigit = true;  
  168.             if (ucRead == ucComma)  
  169.             {  
  170.                 //next char is space or leftbrace  
  171.                 //                ifs >> ucRead;  
  172.                 isdigit = false;  
  173.                 continue;  
  174.             }  
  175.             if (ucRead == ucSpace)  
  176.             {  
  177.                 //if pdvt is null, next char is leftbrace;  
  178.                 //else next char is double value  
  179.                 if (pdvt == NULL)  
  180.                     isdigit = false;  
  181.                 continue;  
  182.             }  
  183.             if (ucRead == ucLeftbrace)  
  184.             {  
  185.                 pdvt = new double[ciFeaturesize];  
  186.                 memset(pdvt, 0, ciFeaturesize * sizeof(double));  
  187.                 //iIndex数组下标  
  188.                 iIndex = 0;  
  189.                 arriStack[++iTop] = 1;  
  190.                 continue;  
  191.             }  
  192.   
  193.             if (ucRead == ucRightbrace)  
  194.             {  
  195.                 if (pdvt != NULL)  
  196.                 {  
  197.                     assert(iIndex == ciFeaturesize);  
  198.                     vecTrain.push_back(pdvt);  
  199.                     pdvt = NULL;  
  200.                 }  
  201.                 isdigit = false;  
  202.                 arriStack[iTop--] = 0;  
  203.                 continue;  
  204.             }  
  205.         }  
  206.         else  
  207.         {  
  208.             ifs >> dread;  
  209.             pdvt[iIndex++] = dread;  
  210.             isdigit = false;  
  211.         }  
  212.     };  
  213.     //next char is dot  
  214.     ifs >> ucRead;  
  215.     assert(ucRead == ucComma);  
  216.     cout << vecTrain.size() << endl;  
  217.     //读取label  
  218.     WORD usread;  
  219.     isdigit = false;  
  220.     while (iTop > -1 && ifs.eof() == false)  
  221.     {  
  222.         if (isdigit == false)  
  223.         {  
  224.             ifs >> ucRead;  
  225.             isdigit = true;  
  226.             if (ucRead == ucComma)  
  227.             {  
  228.                 //next char is space or leftbrace  
  229.                 //                ifs >> ucRead;  
  230. //                isdigit = false;  
  231.                 continue;  
  232.             }  
  233.             if (ucRead == ucSpace)  
  234.             {  
  235.                 //if pdvt is null, next char is leftbrace;  
  236.                 //else next char is double value  
  237.                 if (pdvt == NULL)  
  238.                     isdigit = false;  
  239.                 continue;  
  240.             }  
  241.             if (ucRead == ucLeftbrace)  
  242.             {  
  243.                 arriStack[++iTop] = 1;  
  244.                 continue;  
  245.             }  
  246.   
  247.             //右括号的下一个字符是右括号(最后一个字符)  
  248.             if (ucRead == ucRightbrace)  
  249.             {  
  250.                 isdigit = false;  
  251.                 arriStack[iTop--] = 0;  
  252.                 continue;  
  253.             }  
  254.         }  
  255.         else  
  256.         {  
  257.             ifs >> usread;  
  258.             vecLabel.push_back(usread);  
  259.             isdigit = false;  
  260.         }  
  261.     };  
  262.     assert(vecLabel.size() == vecTrain.size());  
  263.     assert(iTop == -1);  
  264.   
  265.     ifs.close();  
  266.   
  267.   
  268.     return true;  
  269. }  
  270. bool testjsonfloat(const char *filename)  
  271. {  
  272.     vector<double> vecTrain;  
  273.     cout << "testjsondouble" << endl;  
  274.     const int ciStackSize = 10;  
  275.     int arriStack[ciStackSize], iTop = -1;  
  276.   
  277.     ifstream ifs;  
  278.     ifs.open(filename, ios::in);  
  279.     assert(ifs.is_open());  
  280.   
  281.     BYTE ucRead, ucLeftbrace, ucRightbrace, ucComma;  
  282.     ucLeftbrace = '[';  
  283.     ucRightbrace = ']';  
  284.     ucComma = ',';  
  285.     ifs >> ucRead;  
  286.     assert(ucRead == ucLeftbrace);  
  287.     //栈中全部存放左括号,用1代表,0说明清除  
  288.     arriStack[++iTop] = 1;  
  289.     //样本train开始  
  290.     ifs >> ucRead;  
  291.     assert(ucRead == ucLeftbrace);  
  292.     arriStack[++iTop] = 1;//iTop is 1  
  293.     double fread;  
  294.     bool isdigit = false;  
  295.   
  296.   
  297.     while (iTop > -1)  
  298.     {  
  299.         if (isdigit == false)  
  300.         {  
  301.             ifs >> ucRead;  
  302.             isdigit = true;  
  303.             if (ucRead == ucComma)  
  304.             {  
  305.                 //next char is space or leftbrace  
  306.                 //                ifs >> ucRead;  
  307.                 isdigit = false;  
  308.                 continue;  
  309.             }  
  310.             if (ucRead == ' ')  
  311.                 continue;  
  312.             if (ucRead == ucLeftbrace)  
  313.             {  
  314.                 arriStack[++iTop] = 1;  
  315.                 continue;  
  316.             }  
  317.   
  318.             if (ucRead == ucRightbrace)  
  319.             {  
  320.                 isdigit = false;  
  321.                 //右括号的下一个字符是右括号(最后一个字符)  
  322.                 arriStack[iTop--] = 0;  
  323.                 continue;  
  324.             }  
  325.         }  
  326.         else  
  327.         {  
  328.             ifs >> fread;  
  329.             vecTrain.push_back(fread);  
  330.             isdigit = false;  
  331.         }  
  332.     }  
  333.   
  334.     ifs.close();  
  335.   
  336.   
  337.     return true;  
  338.   
  339. }  
  340.   
  341. bool LoadwbFromJson(vector<double*> &vecTrain, vector<double> &vecLabel, const char *filename, const int m_iInput)  
  342. {  
  343.     cout << "loadvtFromJson" << endl;  
  344.     const int ciStackSize = 10;  
  345.     const int ciFeaturesize = m_iInput;  
  346.     int arriStack[ciStackSize], iTop = -1;  
  347.   
  348.     ifstream ifs;  
  349.     ifs.open(filename, ios::in);  
  350.     assert(ifs.is_open());  
  351.     BYTE ucRead, ucLeftbrace, ucRightbrace, ucComma, ucSpace;  
  352.     ucLeftbrace = '[';  
  353.     ucRightbrace = ']';  
  354.     ucComma = ',';  
  355.     ucSpace = '0';  
  356.     ifs >> ucRead;  
  357.     assert(ucRead == ucLeftbrace);  
  358.     //栈中全部存放左括号,用1代表,0说明清除  
  359.     arriStack[++iTop] = 1;  
  360.     //样本train开始  
  361.     ifs >> ucRead;  
  362.     assert(ucRead == ucLeftbrace);  
  363.     arriStack[++iTop] = 1;//iTop is 1  
  364.     int iIndex;  
  365.     bool isdigit = false;  
  366.     double dread, *pdvt;  
  367.     //load vt sample  
  368.     while (iTop > 0)  
  369.     {  
  370.         if (isdigit == false)  
  371.         {  
  372.             ifs >> ucRead;  
  373.             isdigit = true;  
  374.             if (ucRead == ucComma)  
  375.             {  
  376.                 //next char is space or leftbrace  
  377.                 //                ifs >> ucRead;  
  378.                 isdigit = false;  
  379.                 continue;  
  380.             }  
  381.             if (ucRead == ucSpace)  
  382.             {  
  383.                 //if pdvt is null, next char is leftbrace;  
  384.                 //else next char is double value  
  385.                 if (pdvt == NULL)  
  386.                     isdigit = false;  
  387.                 continue;  
  388.             }  
  389.             if (ucRead == ucLeftbrace)  
  390.             {  
  391.                 pdvt = new double[ciFeaturesize];  
  392.                 memset(pdvt, 0, ciFeaturesize * sizeof(double));  
  393.                 //iIndex数组下标  
  394.                 iIndex = 0;  
  395.                 arriStack[++iTop] = 1;  
  396.                 continue;  
  397.             }  
  398.   
  399.             if (ucRead == ucRightbrace)  
  400.             {  
  401.                 if (pdvt != NULL)  
  402.                 {  
  403.                     assert(iIndex == ciFeaturesize);  
  404.                     vecTrain.push_back(pdvt);  
  405.                     pdvt = NULL;  
  406.                 }  
  407.                 isdigit = false;  
  408.                 arriStack[iTop--] = 0;  
  409.                 continue;  
  410.             }  
  411.         }  
  412.         else  
  413.         {  
  414.             ifs >> dread;  
  415.             pdvt[iIndex++] = dread;  
  416.             isdigit = false;  
  417.         }  
  418.     };  
  419.     //next char is dot  
  420.     ifs >> ucRead;  
  421.     assert(ucRead == ucComma);  
  422.     cout << vecTrain.size() << endl;  
  423.     //读取label  
  424.     double usread;  
  425.     isdigit = false;  
  426.     while (iTop > -1 && ifs.eof() == false)  
  427.     {  
  428.         if (isdigit == false)  
  429.         {  
  430.             ifs >> ucRead;  
  431.             isdigit = true;  
  432.             if (ucRead == ucComma)  
  433.             {  
  434.                 //next char is space or leftbrace  
  435.                 //                ifs >> ucRead;  
  436. //                isdigit = false;  
  437.                 continue;  
  438.             }  
  439.             if (ucRead == ucSpace)  
  440.             {  
  441.                 //if pdvt is null, next char is leftbrace;  
  442.                 //else next char is double value  
  443.                 if (pdvt == NULL)  
  444.                     isdigit = false;  
  445.                 continue;  
  446.             }  
  447.             if (ucRead == ucLeftbrace)  
  448.             {  
  449.                 arriStack[++iTop] = 1;  
  450.                 continue;  
  451.             }  
  452.   
  453.             //右括号的下一个字符是右括号(最后一个字符)  
  454.             if (ucRead == ucRightbrace)  
  455.             {  
  456.                 isdigit = false;  
  457.                 arriStack[iTop--] = 0;  
  458.                 continue;  
  459.             }  
  460.         }  
  461.         else  
  462.         {  
  463.             ifs >> usread;  
  464.             vecLabel.push_back(usread);  
  465.             isdigit = false;  
  466.         }  
  467.     };  
  468.     assert(vecLabel.size() == vecTrain.size());  
  469.     assert(iTop == -1);  
  470.   
  471.     ifs.close();  
  472.   
  473.   
  474.     return true;  
  475. }  
  476. bool vec2double(vector<BYTE> &vecDigit, double &dvalue)  
  477. {  
  478.     if (vecDigit.empty())  
  479.         return false;  
  480.     int ivecsize = vecDigit.size();  
  481.     const int iMaxlen = 50;  
  482.     char szdigit[iMaxlen];  
  483.     assert(iMaxlen > ivecsize);  
  484.     memset(szdigit, 0, iMaxlen);  
  485.     int i;  
  486.     for (i = 0; i < ivecsize; ++i)  
  487.         szdigit[i] = vecDigit[i];  
  488.     szdigit[i++] = '\0';  
  489.     vecDigit.clear();  
  490.     dvalue = atof(szdigit);  
  491.   
  492.     return true;  
  493. }  
  494. bool vec2short(vector<BYTE> &vecDigit, WORD &usvalue)  
  495. {  
  496.     if (vecDigit.empty())  
  497.         return false;  
  498.     int ivecsize = vecDigit.size();  
  499.     const int iMaxlen = 50;  
  500.     char szdigit[iMaxlen];  
  501.     assert(iMaxlen > ivecsize);  
  502.     memset(szdigit, 0, iMaxlen);  
  503.     int i;  
  504.     for (i = 0; i < ivecsize; ++i)  
  505.         szdigit[i] = vecDigit[i];  
  506.     szdigit[i++] = '\0';  
  507.     vecDigit.clear();  
  508.     usvalue = atoi(szdigit);  
  509.     return true;  
  510. }  
  511. void readDigitFromJson(ifstream &ifs, vector<double*> &vecTrain, vector<WORD> &vecLabel,  
  512.                        vector<BYTE> &vecDigit, double *&pdvt, int &iIndex,  
  513.                        const int ciFeaturesize, int *arrStack, int &iTop, bool bFirstlist)  
  514. {  
  515.     BYTE ucRead;  
  516.     WORD usvalue;  
  517.     double dvalue;  
  518.   
  519.   
  520.     const BYTE ucLeftbrace = '[', ucRightbrace = ']', ucComma = ',', ucSpace = ' ';  
  521.   
  522.     ifs.read((char*)(&ucRead), 1);  
  523.     switch (ucRead)  
  524.     {  
  525.         case ucLeftbrace:  
  526.         {  
  527.             if (bFirstlist)  
  528.             {  
  529.   
  530.                 pdvt = new double[ciFeaturesize];  
  531.                 memset(pdvt, 0, ciFeaturesize * sizeof(double));  
  532.                 iIndex = 0;  
  533.             }  
  534.             arrStack[++iTop] = 1;  
  535.             break;  
  536.         }  
  537.         case ucComma:  
  538.         {  
  539.             //next char is space or leftbrace  
  540.             if (bFirstlist)  
  541.             {  
  542.                 if (vecDigit.empty() == false)  
  543.                 {  
  544.                     vec2double(vecDigit, dvalue);  
  545.                     pdvt[iIndex++] = dvalue;  
  546.                 }  
  547.             }  
  548.             else  
  549.             {  
  550.                 if(vec2short(vecDigit, usvalue))  
  551.                     vecLabel.push_back(usvalue);  
  552.             }  
  553.             break;  
  554.         }  
  555.         case ucSpace:  
  556.             break;  
  557.         case ucRightbrace:  
  558.         {  
  559.             if (bFirstlist)  
  560.             {  
  561.                 if (pdvt != NULL)  
  562.                 {  
  563.   
  564.                     vec2double(vecDigit, dvalue);  
  565.                     pdvt[iIndex++] = dvalue;  
  566.                     vecTrain.push_back(pdvt);  
  567.                     pdvt = NULL;  
  568.                 }  
  569.                 assert(iIndex == ciFeaturesize);  
  570.             }  
  571.             else  
  572.             {  
  573.                 if(vec2short(vecDigit, usvalue))  
  574.                     vecLabel.push_back(usvalue);  
  575.             }  
  576.             arrStack[iTop--] = 0;  
  577.             break;  
  578.         }  
  579.         default:  
  580.         {  
  581.             vecDigit.push_back(ucRead);  
  582.             break;  
  583.         }  
  584.     }  
  585.   
  586. }  
  587. void readDoubleFromJson(ifstream &ifs, vector<double*> &vecTrain, vector<double> &vecLabel,  
  588.                        vector<BYTE> &vecDigit, double *&pdvt, int &iIndex,  
  589.                        const int ciFeaturesize, int *arrStack, int &iTop, bool bFirstlist)  
  590. {  
  591.     BYTE ucRead;  
  592.     double dvalue;  
  593.   
  594.   
  595.     const BYTE ucLeftbrace = '[', ucRightbrace = ']', ucComma = ',', ucSpace = ' ';  
  596.   
  597.     ifs.read((char*)(&ucRead), 1);  
  598.     switch (ucRead)  
  599.     {  
  600.         case ucLeftbrace:  
  601.         {  
  602.             if (bFirstlist)  
  603.             {  
  604.   
  605.                 pdvt = new double[ciFeaturesize];  
  606.                 memset(pdvt, 0, ciFeaturesize * sizeof(double));  
  607.                 iIndex = 0;  
  608.             }  
  609.             arrStack[++iTop] = 1;  
  610.             break;  
  611.         }  
  612.         case ucComma:  
  613.         {  
  614.             //next char is space or leftbrace  
  615.             if (bFirstlist)  
  616.             {  
  617.                 if (vecDigit.empty() == false)  
  618.                 {  
  619.                     vec2double(vecDigit, dvalue);  
  620.                     pdvt[iIndex++] = dvalue;  
  621.                 }  
  622.             }  
  623.             else  
  624.             {  
  625.                 if(vec2double(vecDigit, dvalue))  
  626.                     vecLabel.push_back(dvalue);  
  627.             }  
  628.             break;  
  629.         }  
  630.         case ucSpace:  
  631.             break;  
  632.         case ucRightbrace:  
  633.         {  
  634.             if (bFirstlist)  
  635.             {  
  636.                 if (pdvt != NULL)  
  637.                 {  
  638.   
  639.                     vec2double(vecDigit, dvalue);  
  640.                     pdvt[iIndex++] = dvalue;  
  641.                     vecTrain.push_back(pdvt);  
  642.                     pdvt = NULL;  
  643.                 }  
  644.                 assert(iIndex == ciFeaturesize);  
  645.             }  
  646.             else  
  647.             {  
  648.                 if(vec2double(vecDigit, dvalue))  
  649.                     vecLabel.push_back(dvalue);  
  650.             }  
  651.             arrStack[iTop--] = 0;  
  652.             break;  
  653.         }  
  654.         default:  
  655.         {  
  656.             vecDigit.push_back(ucRead);  
  657.             break;  
  658.         }  
  659.     }  
  660.   
  661. }  
  662.   
  663. bool LoadallwbByByte(vector< vector<double*> > &vvAllw, vector< vector<double> > &vvAllb, const char *filename,  
  664.                      const int m_iInput, const int ihidden, const int m_iOut)  
  665. {  
  666.     cout << "LoadallwbByByte" << endl;  
  667.     const int szistsize = 10;  
  668.     int ciFeaturesize = m_iInput;  
  669.     const BYTE ucLeftbrace = '[', ucRightbrace = ']', ucComma = ',', ucSpace = ' ';  
  670.     int arrStack[szistsize], iTop = -1, iIndex = 0;  
  671.   
  672.   
  673.     ifstream ifs;  
  674.     ifs.open(filename, ios::in | ios::binary);  
  675.     assert(ifs.is_open());  
  676.   
  677.   
  678.     double *pdvt;  
  679.     BYTE ucRead;  
  680.     ifs.read((char*)(&ucRead), 1);  
  681.     assert(ucRead == ucLeftbrace);  
  682.     //栈中全部存放左括号,用1代表,0说明清除  
  683.     arrStack[++iTop] = 1;  
  684.     ifs.read((char*)(&ucRead), 1);  
  685.     assert(ucRead == ucLeftbrace);  
  686.     arrStack[++iTop] = 1;//iTop is 1  
  687.     ifs.read((char*)(&ucRead), 1);  
  688.     assert(ucRead == ucLeftbrace);  
  689.     arrStack[++iTop] = 1;//iTop is 2  
  690.     vector<BYTE> vecDigit;  
  691.     vector<double *> vpdw;  
  692.     vector<double> vdb;  
  693.     while (iTop > 1 && ifs.eof() == false)  
  694.     {  
  695.         readDoubleFromJson(ifs, vpdw, vdb, vecDigit, pdvt, iIndex, m_iInput, arrStack, iTop, true);  
  696.     };  
  697.     //next char is dot  
  698.     ifs.read((char*)(&ucRead), 1);;  
  699.     assert(ucRead == ucComma);  
  700.     cout << vpdw.size() << endl;  
  701.     //next char is space  
  702.     while (iTop > 0 && ifs.eof() == false)  
  703.     {  
  704.         readDoubleFromJson(ifs, vpdw, vdb, vecDigit, pdvt, iIndex, m_iInput, arrStack, iTop, false);  
  705.     };  
  706.     assert(vpdw.size() == vdb.size());  
  707.     assert(iTop == 0);  
  708.     vvAllw.push_back(vpdw);  
  709.     vvAllb.push_back(vdb);  
  710.     //clear vpdw and pdb 's contents  
  711.     vpdw.clear();  
  712.     vdb.clear();  
  713.   
  714.     //next char is comma  
  715.     ifs.read((char*)(&ucRead), 1);;  
  716.     assert(ucRead == ucComma);  
  717.     //next char is space  
  718.     ifs.read((char*)(&ucRead), 1);;  
  719.     assert(ucRead == ucSpace);  
  720.   
  721.     ifs.read((char*)(&ucRead), 1);  
  722.     assert(ucRead == ucLeftbrace);  
  723.     arrStack[++iTop] = 1;//iTop is 1  
  724.     ifs.read((char*)(&ucRead), 1);  
  725.     assert(ucRead == ucLeftbrace);  
  726.     arrStack[++iTop] = 1;//iTop is 2  
  727.   
  728.     while (iTop > 1 && ifs.eof() == false)  
  729.     {  
  730.         readDoubleFromJson(ifs, vpdw, vdb, vecDigit, pdvt, iIndex, ihidden, arrStack, iTop, true);  
  731.     };  
  732.     //next char is dot  
  733.     ifs.read((char*)(&ucRead), 1);;  
  734.     assert(ucRead == ucComma);  
  735.     cout << vpdw.size() << endl;  
  736.     //next char is space  
  737.     while (iTop > -1 && ifs.eof() == false)  
  738.     {  
  739.         readDoubleFromJson(ifs, vpdw, vdb, vecDigit, pdvt, iIndex, ihidden, arrStack, iTop, false);  
  740.     };  
  741.     assert(vpdw.size() == vdb.size());  
  742.     assert(iTop == -1);  
  743.     vvAllw.push_back(vpdw);  
  744.     vvAllb.push_back(vdb);  
  745.     //clear vpdw and pdb 's contents  
  746.     vpdw.clear();  
  747.     vdb.clear();  
  748.     //close file  
  749.     ifs.close();  
  750.     return true;  
  751.   
  752.   
  753. }  
  754.   
  755. bool LoadWeighFromJson(vector< vector<double*> > &vvAllw, vector< vector<double> > &vvAllb,  
  756.                      const char *filename, const vector<int> &vecSecondDimOfWeigh)  
  757. {  
  758.     cout << "LoadWeighFromJson" << endl;  
  759.     const int szistsize = 10;  
  760.   
  761.     const BYTE ucLeftbrace = '[', ucRightbrace = ']', ucComma = ',', ucSpace = ' ';  
  762.     int arrStack[szistsize], iTop = -1, iIndex = 0;  
  763.   
  764.   
  765.     ifstream ifs;  
  766.     ifs.open(filename, ios::in | ios::binary);  
  767.     assert(ifs.is_open());  
  768.   
  769.   
  770.     double *pdvt;  
  771.     BYTE ucRead;  
  772.     ifs.read((char*)(&ucRead), 1);  
  773.     assert(ucRead == ucLeftbrace);  
  774.     //栈中全部存放左括号,用1代表,0说明清除  
  775.     arrStack[++iTop] = 1;  
  776.     ifs.read((char*)(&ucRead), 1);  
  777.     assert(ucRead == ucLeftbrace);  
  778.     arrStack[++iTop] = 1;//iTop is 1  
  779.     ifs.read((char*)(&ucRead), 1);  
  780.     assert(ucRead == ucLeftbrace);  
  781.     arrStack[++iTop] = 1;//iTop is 2  
  782.   
  783.     int iVecWeighSize = vecSecondDimOfWeigh.size();  
  784.     vector<BYTE> vecDigit;  
  785.     vector<double *> vpdw;  
  786.     vector<double> vdb;  
  787.     //读取iVecWeighSize个[w,b]  
  788.     for (int i = 0; i < iVecWeighSize; ++i)  
  789.     {  
  790.         int iDimesionOfWeigh = vecSecondDimOfWeigh[i];  
  791.         while (iTop > 1 && ifs.eof() == false)  
  792.         {  
  793.             readDoubleFromJson(ifs, vpdw, vdb, vecDigit, pdvt, iIndex, iDimesionOfWeigh, arrStack, iTop, true);  
  794.         };  
  795.         //next char is dot  
  796.         ifs.read((char*)(&ucRead), 1);;  
  797.         assert(ucRead == ucComma);  
  798.         cout << vpdw.size() << endl;  
  799.         //next char is space  
  800.         while (iTop > 0 && ifs.eof() == false)  
  801.         {  
  802.             readDoubleFromJson(ifs, vpdw, vdb, vecDigit, pdvt, iIndex, iDimesionOfWeigh, arrStack, iTop, false);  
  803.         };  
  804.         assert(vpdw.size() == vdb.size());  
  805.         assert(iTop == 0);  
  806.         vvAllw.push_back(vpdw);  
  807.         vvAllb.push_back(vdb);  
  808.         //clear vpdw and pdb 's contents  
  809.         vpdw.clear();  
  810.         vdb.clear();  
  811.         //如果最后一对[w,b]读取完毕,就退出,下一个字符是右括号']'  
  812.         if (i >= iVecWeighSize - 1)  
  813.         {  
  814.             break;  
  815.         }  
  816.   
  817.         //next char is comma  
  818.         ifs.read((char*)(&ucRead), 1);;  
  819.         assert(ucRead == ucComma);  
  820.         //next char is space  
  821.         ifs.read((char*)(&ucRead), 1);;  
  822.         assert(ucRead == ucSpace);  
  823.   
  824.         ifs.read((char*)(&ucRead), 1);  
  825.         assert(ucRead == ucLeftbrace);  
  826.         arrStack[++iTop] = 1;//iTop is 1  
  827.         ifs.read((char*)(&ucRead), 1);  
  828.         assert(ucRead == ucLeftbrace);  
  829.         arrStack[++iTop] = 1;//iTop is 2  
  830.     }  
  831.   
  832.       
  833.     ifs.read((char*)(&ucRead), 1);;  
  834.     assert(ucRead == ucRightbrace);  
  835.     --iTop;  
  836.     assert(iTop == -1);  
  837.       
  838.     //close file  
  839.     ifs.close();  
  840.     return true;  
  841.   
  842.       
  843. }  
  844.   
  845.   
  846. //read vt from mnszist, format is [[[], [],..., []],[1, 3, 5,..., 7]]  
  847. bool LoadTestSampleFromJson(vector<double*> &vecTrain, vector<WORD> &vecLabel, const char *filename, const int m_iInput)  
  848. {  
  849.     cout << "LoadTestSampleFromJson" << endl;  
  850.     const int szistsize = 10;  
  851.     const int ciFeaturesize = m_iInput;  
  852.     const BYTE ucLeftbrace = '[', ucRightbrace = ']', ucComma = ',', ucSpace = ' ';  
  853.     int arrStack[szistsize], iTop = -1, iIndex = 0;  
  854.   
  855.   
  856.     ifstream ifs;  
  857.     ifs.open(filename, ios::in | ios::binary);  
  858.     assert(ifs.is_open());  
  859.   
  860.   
  861.     double *pdvt;  
  862.     BYTE ucRead;  
  863.     ifs.read((char*)(&ucRead), 1);  
  864.     assert(ucRead == ucLeftbrace);  
  865.     //栈中全部存放左括号,用1代表,0说明清除  
  866.     arrStack[++iTop] = 1;  
  867.     ifs.read((char*)(&ucRead), 1);  
  868.     assert(ucRead == ucLeftbrace);  
  869.     arrStack[++iTop] = 1;//iTop is 1  
  870.     vector<BYTE> vecDigit;  
  871.     while (iTop > 0 && ifs.eof() == false)  
  872.     {  
  873.         readDigitFromJson(ifs, vecTrain, vecLabel, vecDigit, pdvt, iIndex, ciFeaturesize, arrStack, iTop, true);  
  874.     };  
  875.     //next char is dot  
  876.     ifs >> ucRead;  
  877.     assert(ucRead == ucComma);  
  878.     cout << vecTrain.size() << endl;  
  879.     //next char is space  
  880. //    ifs.read((char*)(&ucRead), 1);  
  881. //    ifs.read((char*)(&ucRead), 1);  
  882. //    assert(ucRead == ucLeftbrace);  
  883.     while (iTop > -1 && ifs.eof() == false)  
  884.     {  
  885.         readDigitFromJson(ifs, vecTrain, vecLabel, vecDigit, pdvt, iIndex, ciFeaturesize, arrStack, iTop, false);  
  886.     };  
  887.     assert(vecLabel.size() == vecTrain.size());  
  888.     assert(iTop == -1);  
  889.   
  890.     ifs.close();  
  891.   
  892.   
  893.     return true;  
  894. }  
  895. void MakeOneLabel(int iMax, double *pdLabel, int m_iOut)  
  896. {  
  897.     for (int j = 0; j < m_iOut; ++j)  
  898.         pdLabel[j] = 0;  
  899.     pdLabel[iMax] = 1.0;  
  900. }  
  901.   
  902. void MakeCnnSample(double arrInput[2][64], double *pdImage, int iImageWidth, int iNumOfImage)  
  903. {  
  904.     int iImageSize = iImageWidth * iImageWidth;  
  905.   
  906.     for (int k = 0; k < iNumOfImage; ++k)  
  907.     {  
  908.         int iStart = k *iImageSize;  
  909.         for (int i = 0; i < iImageWidth; ++i)  
  910.         {  
  911.             for (int j = 0; j < iImageWidth; ++j)  
  912.             {  
  913.                 int iIndex = iStart + i * iImageWidth + j;  
  914.                 pdImage[iIndex] = 1;  
  915.                 pdImage[iIndex] += i + j;  
  916.                 if (k > 0)  
  917.                     pdImage[iIndex] -= 1;  
  918.                 arrInput[k][i * iImageWidth +j] = pdImage[iIndex];  
  919.                 //pdImage[iIndex] /= 15.0   ;  
  920.   
  921.             }  
  922.         }  
  923.     }  
  924.       
  925.     cout << "input image is\n";  
  926.     for (int k = 0; k < iNumOfImage; ++k)  
  927.     {  
  928.         int iStart = k *iImageSize;  
  929.         cout << "k is " << k <<endl;  
  930.         for (int i = 0; i < iImageWidth; ++i)  
  931.         {  
  932.             for (int j = 0; j < iImageWidth; ++j)  
  933.             {  
  934.                 int iIndex =  i * iImageWidth + j;  
  935.                 double dValue = arrInput[k][iIndex];  
  936.                 cout << dValue << ' ';  
  937.   
  938.             }  
  939.             cout << endl;  
  940.   
  941.         }  
  942.         cout << endl;  
  943.   
  944.     }  
  945.       
  946.     cout << endl;  
  947. }  
  948.   
  949. void MakeCnnWeigh(double *pdKernel, int iNumOfKernel)  
  950. {  
  951.     const int iKernelWidth = 3;  
  952.     double iSum = 0;  
  953.     double arrKernel[iKernelWidth][iKernelWidth] = {{4, 7, 1},  
  954.                         {3, 8, 5},  
  955.                         {3, 2, 3}};  
  956.     double arr2[iKernelWidth][iKernelWidth] = {{6, 5, 4},  
  957.                                                 {5, 4, 3},  
  958.                                                 {4, 3, 2}};  
  959.     for (int k = 0; k < iNumOfKernel; ++k)  
  960.     {  
  961.         int iStart = k * iKernelWidth * iKernelWidth;  
  962.         for (int i = 0; i < iKernelWidth; ++i)  
  963.         {  
  964.             for (int j = 0; j < iKernelWidth; ++j)  
  965.             {  
  966.                 int iIndex = i * iKernelWidth + j + iStart;  
  967.                 pdKernel[iIndex] = i + j + 2;  
  968.                 if (k > 0)  
  969.                     pdKernel[iIndex] = arrKernel[i][j];  
  970.                 iSum += pdKernel[iIndex];  
  971.   
  972.             }  
  973.         }  
  974.     }  
  975.     cout << "sum is " << iSum << endl;  
  976.     for (int k = 0; k < iNumOfKernel; ++k)  
  977.     {  
  978.         cout << "kernel :" << k << endl;  
  979.         int iStart = k * iKernelWidth * iKernelWidth;  
  980.         for (int i = 0; i < iKernelWidth; ++i)  
  981.         {  
  982.             for (int j = 0; j < iKernelWidth; ++j)  
  983.             {  
  984.                 int iIndex = i * iKernelWidth + j + iStart;  
  985.                 //pdKernel[iIndex] /= (double)iSum;  
  986.                 cout << pdKernel[iIndex] << ' ';  
  987.   
  988.   
  989.             }  
  990.             cout << endl;  
  991.   
  992.         }  
  993.         cout << endl;  
  994.     }  
  995.   
  996.       
  997.    cout << endl;  
  998. }  


训练两轮,生成theano权值的代码

cnn_mlp_theano.py

[python] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #coding=utf-8  
  2.   
  3. import cPickle  
  4. import gzip  
  5. import os  
  6. import sys  
  7. import time  
  8. import json  
  9.   
  10. import numpy  
  11.   
  12. import theano  
  13. import theano.tensor as T  
  14. from theano.tensor.signal import downsample  
  15. from theano.tensor.nnet import conv  
  16.   
  17. from logistic_sgd import LogisticRegression, load_data  
  18. from mlp import HiddenLayer  
  19.   
  20.   
  21. class LeNetConvPoolLayer(object):  
  22.     """Pool Layer of a convolutional network """  
  23.   
  24.     def __init__(self, rng, input, filter_shape, image_shape, poolsize=(22)):  
  25.         """ 
  26.         Allocate a LeNetConvPoolLayer with shared variable internal parameters. 
  27.  
  28.         :type rng: numpy.random.RandomState 
  29.         :param rng: a random number generator used to initialize weights 
  30.  
  31.         :type input: theano.tensor.dtensor4 
  32.         :param input: symbolic image tensor, of shape image_shape 
  33.  
  34.         :type filter_shape: tuple or list of length 4 
  35.         :param filter_shape: (number of filters, num input feature maps, 
  36.                               filter height,filter width) 
  37.  
  38.         :type image_shape: tuple or list of length 4 
  39.         :param image_shape: (batch size, num input feature maps, 
  40.                              image height, image width) 
  41.  
  42.         :type poolsize: tuple or list of length 2 
  43.         :param poolsize: the downsampling (pooling) factor (#rows,#cols) 
  44.         """  
  45.   
  46.         assert image_shape[1] == filter_shape[1]  
  47.         self.input = input  
  48.   
  49.         # there are "num input feature maps * filter height * filter width"  
  50.         # inputs to each hidden unit  
  51.         fan_in = numpy.prod(filter_shape[1:])  
  52.         # each unit in the lower layer receives a gradient from:  
  53.         # "num output feature maps * filter height * filter width" /  
  54.         #   pooling size  
  55.         fan_out = (filter_shape[0] * numpy.prod(filter_shape[2:]) /  
  56.                    numpy.prod(poolsize))  
  57.         # initialize weights with random weights  
  58.         W_bound = numpy.sqrt(6. / (fan_in + fan_out))  
  59.         self.W = theano.shared(numpy.asarray(  
  60.             rng.uniform(low=-W_bound, high=W_bound, size=filter_shape),  
  61.             dtype=theano.config.floatX),  
  62.                                borrow=True)  
  63.   
  64.         # the bias is a 1D tensor -- one bias per output feature map  
  65.         b_values = numpy.zeros((filter_shape[0],), dtype=theano.config.floatX)  
  66.         self.b = theano.shared(value=b_values, borrow=True)  
  67.   
  68.         # convolve input feature maps with filters  
  69.         conv_out = conv.conv2d(input=input, filters=self.W,  
  70.                 filter_shape=filter_shape, image_shape=image_shape)  
  71.   
  72.         # downsample each feature map individually, using maxpooling  
  73.         pooled_out = downsample.max_pool_2d(input=conv_out,  
  74.                                             ds=poolsize, ignore_border=True)  
  75.   
  76.         # add the bias term. Since the bias is a vector (1D array), we first  
  77.         # reshape it to a tensor of shape (1,n_filters,1,1). Each bias will  
  78.         # thus be broadcasted across mini-batches and feature map  
  79.         # width & height  
  80.         self.output = T.tanh(pooled_out + self.b.dimshuffle('x'0'x''x'))  
  81.   
  82.         # store parameters of this layer  
  83.         self.params = [self.W, self.b]  
  84.   
  85. def getDataNumpy(layers):  
  86.     data = []  
  87.     for layer in layers:  
  88.         wb = layer.params  
  89.         w, b = wb[0].get_value(), wb[1].get_value()  
  90.         data.append([w, b])  
  91.     return data  
  92. def getDataJson(layers):  
  93.     data = []  
  94.     i = 0  
  95.     for layer in layers:  
  96.         w, b = layer.params  
  97.         # print '..layer is', i  
  98.         w, b = w.get_value(), b.get_value()  
  99.         wshape = w.shape  
  100.         # print '...the shape of w is', wshape  
  101.         if len(wshape) == 2:  
  102.             w = w.transpose()  
  103.         else:  
  104.             for k in xrange(wshape[0]):  
  105.                 for j in xrange(wshape[1]):  
  106.                     w[k][j] = numpy.rot90(w[k][j], 2)  
  107.   
  108.             w = w.reshape((wshape[0], numpy.prod(wshape[1:])))  
  109.   
  110.         w = w.tolist()  
  111.         b = b.tolist()  
  112.         data.append([w, b])  
  113.         i += 1  
  114.     return data  
  115.   
  116. def writefile(data, name = '../../tmp/src/data/theanocnn.json'):  
  117.     print ('writefile is ' + name)  
  118.     f = open(name, "wb")  
  119.     json.dump(data,f)  
  120.     f.close()  
  121. def readfile(layers, nkerns, name = '../../tmp/src/data/theanocnn.json'):  
  122.     # Load the dataset  
  123.     print ('readfile is ' + name)  
  124.     f = open(name, 'rb')  
  125.     data = json.load(f)  
  126.     f.close()  
  127.     readwb(data, layers, nkerns)  
  128.   
  129. def readwb(data, layers, nkerns):  
  130.     i = 0  
  131.     kernSize = len(nkerns)  
  132.     inputnum = 1  
  133.     for layer in layers:  
  134.         w, b = data[i]  
  135.         w = numpy.array(w, dtype='float32')  
  136.         b = numpy.array(b, dtype='float32')  
  137.   
  138.         # print '..layer is', i  
  139.         # print w.shape  
  140.         if i >= kernSize:  
  141.             w = w.transpose()  
  142.         else:  
  143.             w = w.reshape((nkerns[i], inputnum, 55))  
  144.             for k in xrange(nkerns[i]):  
  145.                 for j in xrange(inputnum):  
  146.                     c = w[k][j]  
  147.                     w[k][j] = numpy.rot90(c, 2)  
  148.             inputnum = nkerns[i]  
  149.         # print '..readwb ,transpose and rot180'  
  150.         # print w.shape  
  151.         layer.W.set_value(w, borrow=True)  
  152.         layer.b.set_value(b, borrow=True)  
  153.         i += 1  
  154. def loadwb(classifier, name='theanocnn.json'):  
  155.     data = json.load(open(name, 'rb'))  
  156.     w, b = data  
  157.     print type(w)  
  158.     w = numpy.array(w, dtype='float32').transpose()  
  159.     classifier.W.set_value(w, borrow=True)  
  160.     classifier.b.set_value(b, borrow=True)  
  161. def savewb(classifier, name='theanocnn.json'):  
  162.     w, b = classifier.params  
  163.     w = w.get_value().transpose().tolist()  
  164.     b = b.get_value().tolist()  
  165.     data = [w, b]  
  166.     json.dump(data, open(name, 'wb'))  
  167.       
  168.   
  169. def evaluate_lenet5(learning_rate=0.1, n_epochs=2,  
  170.                     dataset='../../data/mnist.pkl',  
  171.                     nkerns=[2050], batch_size=500):  
  172.     """ Demonstrates lenet on MNIST dataset 
  173.  
  174.     :type learning_rate: float 
  175.     :param learning_rate: learning rate used (factor for the stochastic 
  176.                           gradient) 
  177.  
  178.     :type n_epochs: int 
  179.     :param n_epochs: maximal number of epochs to run the optimizer 
  180.  
  181.     :type dataset: string 
  182.     :param dataset: path to the dataset used for training /testing (MNIST here) 
  183.  
  184.     :type nkerns: list of ints 
  185.     :param nkerns: number of kernels on each layer 
  186.     """  
  187.   
  188.     rng = numpy.random.RandomState(23455)  
  189.   
  190.     datasets = load_data(dataset)  
  191.   
  192.     train_set_x, train_set_y = datasets[0]  
  193.     valid_set_x, valid_set_y = datasets[1]  
  194.     test_set_x, test_set_y = datasets[2]  
  195.   
  196.     # compute number of minibatches for training, validation and testing  
  197.     n_train_batches = train_set_x.get_value(borrow=True).shape[0]  
  198.     n_valid_batches = valid_set_x.get_value(borrow=True).shape[0]  
  199.     n_test_batches = test_set_x.get_value(borrow=True).shape[0]  
  200.     n_train_batches /= batch_size  
  201.     n_valid_batches /= batch_size  
  202.     n_test_batches /= batch_size  
  203.   
  204.     # allocate symbolic variables for the data  
  205.     index = T.lscalar()  # index to a [mini]batch  
  206.     x = T.matrix('x')   # the data is presented as rasterized images  
  207.     y = T.ivector('y')  # the labels are presented as 1D vector of  
  208.                         # [int] labels  
  209.   
  210.     ishape = (2828)  # this is the size of MNIST images  
  211.   
  212.     ######################  
  213.     # BUILD ACTUAL MODEL #  
  214.     ######################  
  215.     print '... building the model'  
  216.   
  217.     # Reshape matrix of rasterized images of shape (batch_size,28*28)  
  218.     # to a 4D tensor, compatible with our LeNetConvPoolLayer  
  219.     layer0_input = x.reshape((batch_size, 12828))  
  220.   
  221.     # Construct the first convolutional pooling layer:  
  222.     # filtering reduces the image size to (28-5+1,28-5+1)=(24,24)  
  223.     # maxpooling reduces this further to (24/2,24/2) = (12,12)  
  224.     # 4D output tensor is thus of shape (batch_size,nkerns[0],12,12)  
  225.     layer0 = LeNetConvPoolLayer(rng, input=layer0_input,  
  226.             image_shape=(batch_size, 12828),  
  227.             filter_shape=(nkerns[0], 155), poolsize=(22))  
  228.   
  229.     # Construct the second convolutional pooling layer  
  230.     # filtering reduces the image size to (12-5+1,12-5+1)=(8,8)  
  231.     # maxpooling reduces this further to (8/2,8/2) = (4,4)  
  232.     # 4D output tensor is thus of shape (nkerns[0],nkerns[1],4,4)  
  233.     layer1 = LeNetConvPoolLayer(rng, input=layer0.output,  
  234.             image_shape=(batch_size, nkerns[0], 1212),  
  235.             filter_shape=(nkerns[1], nkerns[0], 55), poolsize=(22))  
  236.   
  237.     # the TanhLayer being fully-connected, it operates on 2D matrices of  
  238.     # shape (batch_size,num_pixels) (i.e matrix of rasterized images).  
  239.     # This will generate a matrix of shape (20,32*4*4) = (20,512)  
  240.     layer2_input = layer1.output.flatten(2)  
  241.   
  242.     # construct a fully-connected sigmoidal layer  
  243.     layer2 = HiddenLayer(rng, input=layer2_input, n_in=nkerns[1] * 4 * 4,  
  244.                          n_out=500, activation=T.tanh)  
  245.   
  246.     # classify the values of the fully-connected sigmoidal layer  
  247.     layer3 = LogisticRegression(input=layer2.output, n_in=500, n_out=10)  
  248.   
  249.     # the cost we minimize during training is the NLL of the model  
  250.     cost = layer3.negative_log_likelihood(y)  
  251.   
  252.     # create a function to compute the mistakes that are made by the model  
  253.     test_model = theano.function([index], layer3.errors(y),  
  254.              givens={  
  255.                 x: test_set_x[index * batch_size: (index + 1) * batch_size],  
  256.                 y: test_set_y[index * batch_size: (index + 1) * batch_size]})  
  257.   
  258.     validate_model = theano.function([index], layer3.errors(y),  
  259.             givens={  
  260.                 x: valid_set_x[index * batch_size: (index + 1) * batch_size],  
  261.                 y: valid_set_y[index * batch_size: (index + 1) * batch_size]})  
  262.   
  263.     # create a list of all model parameters to be fit by gradient descent  
  264.     params = layer3.params + layer2.params + layer1.params + layer0.params  
  265.   
  266.     # create a list of gradients for all model parameters  
  267.     grads = T.grad(cost, params)  
  268.     layers = [layer0, layer1, layer2, layer3]  
  269.   
  270.   
  271.     # train_model is a function that updates the model parameters by  
  272.     # SGD Since this model has many parameters, it would be tedious to  
  273.     # manually create an update rule for each model parameter. We thus  
  274.     # create the updates list by automatically looping over all  
  275.     # (params[i],grads[i]) pairs.  
  276.     updates = []  
  277.     for param_i, grad_i in zip(params, grads):  
  278.         updates.append((param_i, param_i - learning_rate * grad_i))  
  279.   
  280.     train_model = theano.function([index], cost, updates=updates,  
  281.           givens={  
  282.             x: train_set_x[index * batch_size: (index + 1) * batch_size],  
  283.             y: train_set_y[index * batch_size: (index + 1) * batch_size]})  
  284.   
  285.     ###############  
  286.     # TRAIN MODEL #  
  287.     ###############  
  288.     print '... training'  
  289.     # early-stopping parameters  
  290.     patience = 10000  # look as this many examples regardless  
  291.     patience_increase = 2  # wait this much longer when a new best is  
  292.                            # found  
  293.     improvement_threshold = 0.995  # a relative improvement of this much is  
  294.                                    # considered significant  
  295.     validation_frequency = min(n_train_batches, patience / 2)  
  296.                                   # go through this many  
  297.                                   # minibatche before checking the network  
  298.                                   # on the validation set; in this case we  
  299.                                   # check every epoch  
  300.   
  301.     best_params = None  
  302.     best_validation_loss = numpy.inf  
  303.     best_iter = 0  
  304.     test_score = 0.  
  305.     start_time = time.clock()  
  306.   
  307.     epoch = 0  
  308.     done_looping = False  
  309.   
  310.     while (epoch < n_epochs) and (not done_looping):  
  311.         epoch = epoch + 1  
  312.         print '...epoch is', epoch, 'writefile'  
  313.         writefile(getDataJson(layers))  
  314.         for minibatch_index in xrange(n_train_batches):  
  315.   
  316.             iter = (epoch - 1) * n_train_batches + minibatch_index  
  317.   
  318.             if iter % 100 == 0:  
  319.                 print 'training @ iter = ', iter  
  320.             cost_ij = train_model(minibatch_index)  
  321.   
  322.             if (iter + 1) % validation_frequency == 0:  
  323.   
  324.                 # compute zero-one loss on validation set  
  325.                 validation_losses = [validate_model(i) for i  
  326.                                      in xrange(n_valid_batches)]  
  327.                 this_validation_loss = numpy.mean(validation_losses)  
  328.                 print('epoch %i, minibatch %i/%i, validation error %f %%' % \  
  329.                       (epoch, minibatch_index + 1, n_train_batches, \  
  330.                        this_validation_loss * 100.))  
  331.   
  332.                 # if we got the best validation score until now  
  333.                 if this_validation_loss < best_validation_loss:  
  334.   
  335.                     #improve patience if loss improvement is good enough  
  336.                     if this_validation_loss < best_validation_loss *  \  
  337.                        improvement_threshold:  
  338.                         patience = max(patience, iter * patience_increase)  
  339.   
  340.                     # save best validation score and iteration number  
  341.                     best_validation_loss = this_validation_loss  
  342.                     best_iter = iter  
  343.   
  344.                     # test it on the test set  
  345.                     test_losses = [test_model(i) for i in xrange(n_test_batches)]  
  346.                     test_score = numpy.mean(test_losses)  
  347.                     print(('     epoch %i, minibatch %i/%i, test error of best '  
  348.                            'model %f %%') %  
  349.                           (epoch, minibatch_index + 1, n_train_batches,  
  350.                            test_score * 100.))  
  351.   
  352.             if patience <= iter:  
  353.                 done_looping = True  
  354.                 break  
  355.   
  356.     end_time = time.clock()  
  357.     print('Optimization complete.')  
  358.     print('Best validation score of %f %% obtained at iteration %i,'\  
  359.           'with test performance %f %%' %  
  360.           (best_validation_loss * 100., best_iter + 1, test_score * 100.))  
  361.     print >> sys.stderr, ('The code for file ' +  
  362.                           os.path.split(__file__)[1] +  
  363.                           ' ran for %.2fm' % ((end_time - start_time) / 60.))  
  364.     ''''' 
  365.     '''  
  366.   
  367.     readfile(layers, nkerns)  
  368.     validation_losses = [validate_model(i) for i  
  369.                          in xrange(n_valid_batches)]  
  370.     this_validation_loss = numpy.mean(validation_losses)  
  371.     print('validation error %f %%' % \  
  372.           (this_validation_loss * 100.))  
  373.   
  374. if __name__ == '__main__':  
  375.     evaluate_lenet5()  

0 0
原创粉丝点击