本人的需求是:

通过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找的时间最久,血淋淋的教训。。。)
Python  CNN代码:Here。
然后加入下面代码。
theano对写权值的函数,注意它保存的是卷积核旋转180度后的权值,如果权值是二维的,那么行列互换(与c++的权值表示法统一)
[python]  view plain copy
  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. w = w.reshape((wshape[0], numpy.prod(wshape[1:])))
  17. w = w.tolist()
  18. b = b.tolist()
  19. data.append([w, b])
  20. i += 1
  21. return data
  22. def writefile(data, name = '../../tmp/src/data/theanocnn.json'):
  23. print ('writefile is ' + name)
  24. f = open(name, "wb")
  25. json.dump(data,f)
  26. f.close()

theano读权值

[python]  view plain copy
  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. def readwb(data, layers, nkerns):
  9. i = 0
  10. kernSize = len(nkerns)
  11. inputnum = 1
  12. for layer in layers:
  13. w, b = data[i]
  14. w = numpy.array(w, dtype='float32')
  15. b = numpy.array(b, dtype='float32')
  16. # print '..layer is', i
  17. # print w.shape
  18. if i >= kernSize:
  19. w = w.transpose()
  20. else:
  21. w = w.reshape((nkerns[i], inputnum, 5, 5))
  22. for k in xrange(nkerns[i]):
  23. for j in xrange(inputnum):
  24. c = w[k][j]
  25. w[k][j] = numpy.rot90(c, 2)
  26. inputnum = nkerns[i]
  27. # print '..readwb ,transpose and rot180'
  28. # print w.shape
  29. layer.W.set_value(w, borrow=True)
  30. layer.b.set_value(b, borrow=True)
  31. i += 1

测试样本由 手写数字库mnist生成,核心代码如下:

[python]  view plain copy
  1. def mnist2json_small(cnnName = 'mnist_small.json', validNumber = 10):
  2. dataset = '../../data/mnist.pkl'
  3. print '... loading data', dataset
  4. # Load the dataset
  5. f = open(dataset, 'rb')
  6. train_set, valid_set, test_set = cPickle.load(f)
  7. #print test_set
  8. f.close()
  9. def np2listSmall(train_set, number):
  10. trainfile = []
  11. trains, labels = train_set
  12. trainfile = []
  13. #如果注释掉下面,将生成number个验证样本
  14. number = len(labels)
  15. for one in trains[:number]:
  16. one = one.tolist()
  17. trainfile.append(one)
  18. labelfile = labels[:number].tolist()
  19. datafile = [trainfile, labelfile]
  20. return datafile
  21. smallData = valid_set
  22. print len(smallData)
  23. valid, validlabel = np2listSmall(smallData, validNumber)
  24. datafile = [valid, validlabel]
  25. basedir = '../../tmp/src/data/'
  26. # basedir = './'
  27. json.dump(datafile, open(basedir + cnnName, 'wb'))

个人收获:

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

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

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

C++代码

main.cpp

[cpp]  view plain copy
  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. 1、卷积神经网络的前向计算过程
  10. 2、mlp网络的前向与后向计算,也就是可以用来训练样本
  11. 需要注意的是:
  12. 如果为了复现theano的测试结果,那么隐藏层的激活函数要选用tanh;
  13. 否则,为了mlp的训练过程,激活函数要选择sigmoid
  14. */
  15. /************************************************************************/
  16. int main()
  17. {
  18. cout << "****cnn****" << endl;
  19. TestCnnTheano(28 * 28, 10);
  20. // TestMlpMnist对mlp训练样本进行测试
  21. //TestMlpMnist(28 * 28, 500, 10);
  22. return 0;
  23. }

neuralNetwork.h

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

neuralNetwork.cpp

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

cnn.h

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

cnn.cpp

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

featuremap.h

[cpp]  view plain copy
  1. #ifndef FEATUREMAP_H
  2. #define FEATUREMAP_H
  3. #include <cassert>
  4. #include <vector>
  5. using std::vector;
  6. class FeatureMap
  7. {
  8. public:
  9. FeatureMap(int iInputImageNumber, int iInputImageWidth, int iFeatureMapNumber, int iKernelWidth);
  10. ~FeatureMap();
  11. void Forward_propagation(double* );
  12. void Back_propagation(double* , double* , double );
  13. void Convolute(double *pdInputData);
  14. int GetFeatureMapSize()
  15. {
  16. return m_iFeatureMapSize;
  17. }
  18. int GetFeatureMapWidth()
  19. {
  20. return m_iFeatureMapWidth;
  21. }
  22. double* GetFeatureMapValue()
  23. {
  24. assert(m_pdOutputValue != NULL);
  25. return m_pdOutputValue;
  26. }
  27. void SetWeigh(const vector<double *> &vecWeigh);
  28. void PrintOutputData();
  29. double **m_ppdWeigh;
  30. double *m_pdBias;
  31. private:
  32. int m_iInputImageNumber;
  33. int m_iInputImageWidth;
  34. int m_iInputImageSize;
  35. int m_iFeatureMapNumber;
  36. int m_iFeatureMapWidth;
  37. int m_iFeatureMapSize;
  38. int m_iKernelWidth;
  39. //    double m_dBias;
  40. double *m_pdOutputValue;
  41. };
  42. #endif // FEATUREMAP_H

featuremap.cpp

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

poollayer.h

[cpp]  view plain copy
  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. private:
  15. int m_iOutImageNumber;
  16. int m_iPoolWidth;
  17. int m_iFeatureMapWidth;
  18. int m_iPoolSize;
  19. int m_iOutImageEdge;
  20. int m_iOutImageSize;
  21. double *m_pdOutData;
  22. double *m_pdBias;
  23. };
  24. #endif // POOLLAYER_H

poollayer.cpp

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

mlp.h

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

mlp.cpp

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

hiddenLayer.h

[cpp]  view plain copy
  1. #ifndef HIDDENLAYER_H
  2. #define HIDDENLAYER_H
  3. #include "neuralbase.h"
  4. class HiddenLayer: public NeuralBase
  5. {
  6. public:
  7. HiddenLayer(int n_i, int n_o);
  8. ~HiddenLayer();
  9. double* Forward_propagation(double* input_data);
  10. void Back_propagation(double *pdInputData, double *pdNextLayerDelta,
  11. double** ppdnextLayerW, int iNextLayerOutNum, double dLr);
  12. };
  13. #endif

hiddenLayer.cpp

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

logisticRegression.h

[cpp]  view plain copy
  1. #ifndef LOGISTICREGRESSIONLAYER
  2. #define LOGISTICREGRESSIONLAYER
  3. #include "neuralbase.h"
  4. typedef unsigned short WORD;
  5. class LogisticRegression: public NeuralBase
  6. {
  7. public:
  8. LogisticRegression(int n_i, int i_o, int);
  9. ~LogisticRegression();
  10. double* Forward_propagation(double* input_data);
  11. void Softmax(double* x);
  12. void Train(double *pdTrain, WORD usLabel, double dLr);
  13. void SetOldWb(double ppdWeigh[][3], double arriBias[8]);
  14. int Predict(double *);
  15. void MakeLabels(int* piMax, double (*pplabels)[8]);
  16. };
  17. void Test_lr();
  18. void Testwb();
  19. void Test_theano(const int m_iInput, const int m_iOut);
  20. #endif

logisticRegression.cpp

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

neuralbase.h

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

neuralbase.cpp

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

util.h

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

util.cpp

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

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

cnn_mlp_theano.py

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

c++重写卷积网络的前向计算过程,完美复现theano的测试结果相关推荐

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

    转自http://blog.csdn.net/qiaofangjie/article/details/18042407 本人的需求是: 通过theano的cnn训练神经网络,将最终稳定的网络权值保存下 ...

  2. 论文翻译:搜索人脸活体检测的中心差异卷积网络及实现代码

    搜索人脸活体检测的中心差异卷积网络 摘要 1. 绪论 2. 相关工作 人脸活体检测 卷积运算符 神经架构搜索 3. 方法论 3.1 中心差分卷积 基本卷积 基本卷积结合中心差分操作 中心差分卷积的实现 ...

  3. DNN:LSTM的前向计算和参数训练

    原文-LSTM的反向传播:深度学习(6)-长短期网路:此处仅摘抄一小段,建议拜访全文. LSTM的参数训练:https://www.jianshu.com/p/dcec3f07d3b5:LSTM的参数 ...

  4. 卷积神经网络中卷积运算的前向传播与反向传播推导

    文章作者:Tyan 博客:noahsnail.com  |  CSDN  |  [简书](http://www.jianshu.com/users/7731e83f3a4e/latest_articl ...

  5. Lesson 16.1016.1116.1216.13 卷积层的参数量计算,1x1卷积核分组卷积与深度可分离卷积全连接层 nn.Sequential全局平均池化,NiN网络复现

    二 架构对参数量/计算量的影响 在自建架构的时候,除了模型效果之外,我们还需要关注模型整体的计算效率.深度学习模型天生就需要大量数据进行训练,因此每次训练中的参数量和计算量就格外关键,因此在设计卷积网 ...

  6. 吴恩达神经网络和深度学习-学习笔记-30-相关符号和计算+单层卷积网络+简单卷积网络示例

    卷积相关的符号和计算 单层卷积网络 首先执行线性函数,然后所有元素相乘做卷积. 具体做法是运用线性函数,再加上偏差,然后应用激活函数Relu. 也即是说,通过神经网络的一层,把一个6×6×3维度的a[ ...

  7. 卷积神经网络卷积计算,卷积网络计算公式

    卷积运算的过程是什么?卷积计算的矩阵是怎么来的,如下图,这个卷积运算示意图怎么理解? 首先,卷积核相同,输入相同,输出的特征是一样的.只不过将输出的矩阵形式换成了列向量的形式. 实质上一般卷积运算与矩 ...

  8. STGCN时空图卷积网络:用于交通预测的深度学习框架

    时空图卷积网络:用于交通预测的深度学习框架 及时准确的交通预测对城市交通控制和引导至关重要.由于交通流的高度非线性和复杂性,传统的方法不能满足中长期预测任务的要求,往往忽略了空间和时间的相关性.本文提 ...

  9. 理解图卷积网络的节点分类

    理解图卷积网络的节点分类 在过去的十年中,神经网络取得了巨大的成功.但是,只能使用常规或欧几里得数据来实现神经网络的早期变体,而现实世界中的许多数据都具有非欧几里得的底层图形结构.数据结构的不规则性导 ...

最新文章

  1. mac 拷贝文件时报错 8060 解决方案
  2. ibmmq 通道命令_IBM MQ 从接收通道获取数据
  3. php服务器无法上传图片,IIS+php服务器无法上传图片解决办法_PHP教程
  4. [投资习惯对比]投资大师vs失败投资…
  5. js操作json方法总结
  6. os.environ 和 keras.json
  7. Guava学习笔记(六):Immutable(不可变)集合
  8. Spotfire调试经验——环比增长率的动态计算(Dynamic moving data percentage calculation in Spotfire visualization)
  9. 计算机怎么切换到音乐,win10系统如何快速切换到下一首歌曲?
  10. C语言实现FTP客户端(已编译,亲试可用~)
  11. 三种嵌入式操作系统比较和分析
  12. 模拟前端ADC芯片LH001-91,用于开发心电、脑电医疗设备
  13. VGA线 1080P之伤 中秋节篇
  14. mysql免费自学课程,自学SQL网(教程 视频 练习全套)
  15. 产品名称:iWX JAVA微信管理平台源码-微友1314
  16. 微信API接口、微信二次开发API调用
  17. [渝粤教育] 西南科技大学 美学原理 在线考试复习资料
  18. 【Linux下Ubuntu查看电脑cpu和显卡型号信息】
  19. 如何通过积分玩法,来提高活跃度以及转化
  20. 智能小区电动车充电站方案 充满自停:避免过充,保护充电安全

热门文章

  1. node+express实现文件上传功能
  2. memcache用法
  3. ADPCM 编码 及WAV解析 及实例
  4. 如何利用python解方程_Python 解方程的三种方法
  5. Spring Data JDBC自动生成的增删改查CRUD分页、排序SQL语句非常简洁没有多余的SQL
  6. Android View - RemoteViews
  7. 缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级等问题
  8. Explaining and Harnessing Adversarial Examples——论文的学习笔记01
  9. 怎么把启用计算机的d磁盘,Win10计算机怎么隐藏磁盘盘符?
  10. 关系与关系模式的区别——易懂