00001 #include "nn.h"
00002
00003 extern StreamOutput cout;
00004
00008 NN::NN()
00009 {
00010
00011 m_nrTargets = 0;
00012 m_nrInputs = 0;
00013 m_nrExamplesTrain = 0;
00014 m_nrExamplesProbe = 0;
00015 m_inputsTrain = 0;
00016 m_inputsProbe = 0;
00017 m_targetsTrain = 0;
00018 m_targetsProbe = 0;
00019 m_initWeightFactor = 0;
00020 m_globalEpochs = 0;
00021 m_RPROP_etaPos = 0;
00022 m_RPROP_etaNeg = 0;
00023 m_RPROP_updateMin = 0;
00024 m_RPROP_updateMax = 0;
00025 m_learnRate = 0;
00026 m_learnRateMin = 0;
00027 m_learnrateDecreaseRate = 0;
00028 m_learnrateDecreaseRateEpoch = 0;
00029 m_momentum = 0;
00030 m_weightDecay = 0;
00031 m_minUpdateBound = 0;
00032 m_batchSize = 0;
00033 m_scaleOutputs = 0;
00034 m_offsetOutputs = 0;
00035 m_maxEpochs = 0;
00036 m_useBLAS = 0;
00037 m_enableRPROP = 0;
00038 m_normalTrainStopping = 0;
00039 m_nrLayer = 0;
00040 m_neuronsPerLayer = 0;
00041 m_nrWeights = 0;
00042 m_nrOutputs = 0;
00043 m_nrLayWeights = 0;
00044 m_outputs = 0;
00045 m_outputsTmp = 0;
00046 m_derivates = 0;
00047 m_d1 = 0;
00048 m_weights = 0;
00049 m_weightsTmp0 = 0;
00050 m_weightsTmp1 = 0;
00051 m_weightsTmp2 = 0;
00052 m_weightsBatchUpdate = 0;
00053 m_weightsOld = 0;
00054 m_weightsOldOld = 0;
00055 m_deltaW = 0;
00056 m_deltaWOld = 0;
00057 m_adaptiveRPROPlRate = 0;
00058 m_enableL1Regularization = 0;
00059 m_errorFunctionMAE = 0;
00060 m_sumSquaredError = 0.0;
00061 m_sumSquaredErrorSamples = 0;
00062 m_nrLayWeightOffsets = 0;
00063 m_sumSquaredError = 0.0;
00064 m_sumSquaredErrorSamples = 0.0;
00065 m_activationFunctionType = 0;
00066 }
00067
00071 NN::~NN()
00072 {
00073 if ( m_neuronsPerLayer )
00074 delete[] m_neuronsPerLayer;
00075 m_neuronsPerLayer = 0;
00076 if ( m_nrLayWeights )
00077 delete[] m_nrLayWeights;
00078 m_nrLayWeights = 0;
00079 if ( m_outputs )
00080 delete[] m_outputs;
00081 m_outputs = 0;
00082 if ( m_outputsTmp )
00083 delete[] m_outputsTmp;
00084 m_outputsTmp = 0;
00085 if ( m_derivates )
00086 delete[] m_derivates;
00087 m_derivates = 0;
00088 if ( m_d1 )
00089 delete[] m_d1;
00090 m_d1 = 0;
00091 if ( m_weights )
00092 delete[] m_weights;
00093 m_weights = 0;
00094 if ( m_weightsTmp0 )
00095 delete[] m_weightsTmp0;
00096 m_weightsTmp0 = 0;
00097 if ( m_weightsTmp1 )
00098 delete[] m_weightsTmp1;
00099 m_weightsTmp1 = 0;
00100 if ( m_weightsTmp2 )
00101 delete[] m_weightsTmp2;
00102 m_weightsTmp2 = 0;
00103 if ( m_weightsBatchUpdate )
00104 delete[] m_weightsBatchUpdate;
00105 m_weightsBatchUpdate = 0;
00106 if ( m_weightsOld )
00107 delete[] m_weightsOld;
00108 m_weightsOld = 0;
00109 if ( m_weightsOldOld )
00110 delete[] m_weightsOldOld;
00111 m_weightsOldOld = 0;
00112 if ( m_deltaW )
00113 delete[] m_deltaW;
00114 m_deltaW = 0;
00115 if ( m_deltaWOld )
00116 delete[] m_deltaWOld;
00117 m_deltaWOld = 0;
00118 if ( m_adaptiveRPROPlRate )
00119 delete[] m_adaptiveRPROPlRate;
00120 m_adaptiveRPROPlRate = 0;
00121 if ( m_nrLayWeightOffsets )
00122 delete[] m_nrLayWeightOffsets;
00123 m_nrLayWeightOffsets = 0;
00124 }
00125
00131 void NN::enableErrorFunctionMAE ( bool en )
00132 {
00133 m_errorFunctionMAE = en;
00134 cout<<"errorFunctionMAE:"<<m_errorFunctionMAE<<endl;
00135 }
00136
00142 void NN::setNrTargets ( int n )
00143 {
00144 m_nrTargets = n;
00145 cout<<"nrTargets: "<<m_nrTargets<<endl;
00146 }
00147
00148
00154 void NN::setNrInputs ( int n )
00155 {
00156 m_nrInputs = n;
00157 cout<<"nrInputs: "<<m_nrInputs<<endl;
00158 }
00164 void NN::setNrExamplesTrain ( int n )
00165 {
00166 m_nrExamplesTrain = n;
00167
00168 }
00174 void NN::setNrExamplesProbe ( int n )
00175 {
00176 m_nrExamplesProbe = n;
00177 cout<<"nrExamplesProbe: "<<m_nrExamplesProbe<<endl;
00178 }
00184 void NN::setTrainInputs ( REAL* inputs )
00185 {
00186 m_inputsTrain = inputs;
00187
00188 }
00189
00195 void NN::setTrainTargets ( REAL* targets )
00196 {
00197 m_targetsTrain = targets;
00198
00199 }
00200
00206 void NN::setProbeInputs ( REAL* inputs )
00207 {
00208 m_inputsProbe = inputs;
00209
00210 }
00211
00217 void NN::setProbeTargets ( REAL* targets )
00218 {
00219 m_targetsProbe = targets;
00220
00221 }
00222
00228 void NN::setInitWeightFactor ( REAL factor )
00229 {
00230 m_initWeightFactor = factor;
00231 cout<<"initWeightFactor: "<<m_initWeightFactor<<endl;
00232 }
00233
00239 void NN::setLearnrate ( REAL learnrate )
00240 {
00241 m_learnRate = learnrate;
00242 cout<<"learnRate: "<<m_learnRate<<endl;
00243 }
00244
00250 void NN::setLearnrateMinimum ( REAL learnrateMin )
00251 {
00252 m_learnRateMin = learnrateMin;
00253 cout<<"learnRateMin: "<<m_learnRateMin<<endl;
00254 }
00255
00261 void NN::setLearnrateSubtractionValueAfterEverySample ( REAL learnrateDecreaseRate )
00262 {
00263 m_learnrateDecreaseRate = learnrateDecreaseRate;
00264 cout<<"learnrateDecreaseRate: "<<m_learnrateDecreaseRate<<endl;
00265 }
00266
00267
00273 void NN::setLearnrateSubtractionValueAfterEveryEpoch ( REAL learnrateDecreaseRate )
00274 {
00275 m_learnrateDecreaseRateEpoch = learnrateDecreaseRate;
00276 cout<<"learnrateDecreaseRateEpoch: "<<m_learnrateDecreaseRateEpoch<<endl;
00277 }
00278
00284 void NN::setMomentum ( REAL momentum )
00285 {
00286 m_momentum = momentum;
00287 cout<<"momentum: "<<m_momentum<<endl;
00288 }
00289
00295 void NN::setWeightDecay ( REAL weightDecay )
00296 {
00297 m_weightDecay = weightDecay;
00298 cout<<"weightDecay: "<<m_weightDecay<<endl;
00299 }
00300
00307 void NN::setBatchSize ( int size )
00308 {
00309 m_batchSize = size;
00310 cout<<"batchSize: "<<m_batchSize<<endl;
00311 }
00312
00318 void NN::setMinUpdateErrorBound ( REAL minUpdateBound )
00319 {
00320 m_minUpdateBound = minUpdateBound;
00321 cout<<"minUpdateBound: "<<m_minUpdateBound<<endl;
00322 }
00323
00329 void NN::setMaxEpochs ( int epochs )
00330 {
00331 m_maxEpochs = epochs;
00332 cout<<"maxEpochs: "<<m_maxEpochs<<endl;
00333 }
00334
00346 void NN::setRPROPPosNeg ( REAL etaPos, REAL etaNeg )
00347 {
00348 m_RPROP_etaPos = etaPos;
00349 m_RPROP_etaNeg = etaNeg;
00350 cout<<"RPROP_etaPos: "<<m_RPROP_etaPos<<" RPROP_etaNeg: "<<m_RPROP_etaNeg<<endl;
00351 }
00352
00360 void NN::setRPROPMinMaxUpdate ( REAL min, REAL max )
00361 {
00362 m_RPROP_updateMin = min;
00363 m_RPROP_updateMax = max;
00364 cout<<"RPROP_updateMin: "<<m_RPROP_updateMin<<" RPROP_updateMax: "<<m_RPROP_updateMax<<endl;
00365 }
00366
00375 void NN::setScaleOffset ( REAL scale, REAL offset )
00376 {
00377 m_scaleOutputs = scale;
00378 m_offsetOutputs = offset;
00379 cout<<"scaleOutputs: "<<m_scaleOutputs<<" offsetOutputs: "<<m_offsetOutputs<<" [transformation: output = outputNN * scale + offset]"<<endl;
00380 }
00381
00389 void NN::setNormalTrainStopping ( bool en )
00390 {
00391 m_normalTrainStopping = en;
00392 cout<<"normalTrainStopping: "<<m_normalTrainStopping<<endl;
00393 }
00394
00400 void NN::setL1Regularization ( bool en )
00401 {
00402 m_enableL1Regularization = en;
00403 cout<<"enableL1Regularization: "<<m_enableL1Regularization<<endl;
00404 }
00405
00414 void NN::enableRPROP ( bool en )
00415 {
00416 m_enableRPROP = en;
00417 cout<<"enableRPROP: "<<m_enableRPROP<<endl;
00418 }
00419
00427 void NN::useBLASforTraining ( bool enable )
00428 {
00429 m_useBLAS = enable;
00430 cout<<"useBLAS: "<<m_useBLAS<<endl;
00431 }
00432
00438 void NN::setActivationFunctionType( int type )
00439 {
00440 if(type==0)
00441 {
00442 cout<<"activationFunctionType: tanh"<<endl;
00443 m_activationFunctionType = 0;
00444 }
00445 else if(type==1)
00446 {
00447 cout<<"activationFunctionType: sin"<<endl;
00448 m_activationFunctionType = 1;
00449 }
00450 else if(type==2)
00451 {
00452 cout<<"activationFunctionType: tanhMod0"<<endl;
00453 m_activationFunctionType = 2;
00454 }
00455 else
00456 assert(false);
00457 }
00458
00468 int NN::getWeightIndex ( int layer, int neuron, int weight )
00469 {
00470 if ( layer == 0 )
00471 assert ( false );
00472
00473 int nrNeur = m_neuronsPerLayer[layer];
00474 int nrNeurPrev = m_neuronsPerLayer[layer-1];
00475 if ( neuron >= nrNeur )
00476 {
00477 cout<<"neuron:"<<neuron<<" nrNeur:"<<nrNeur<<endl;
00478 assert ( false );
00479 }
00480 if ( weight >= nrNeurPrev )
00481 {
00482 cout<<"weight:"<<weight<<" nrNeurPrev:"<<nrNeurPrev<<endl;
00483 assert ( false );
00484 }
00485
00486 int ind = m_nrLayWeightOffsets[layer];
00487 if ( layer == 1 )
00488 ind += 1 + weight + neuron* ( nrNeurPrev + 1 );
00489 else
00490 ind += weight + neuron* ( nrNeurPrev + 1 );
00491
00492 if ( ind >= m_nrWeights )
00493 {
00494 cout<<"ind:"<<ind<<" m_nrWeights:"<<m_nrWeights<<endl;
00495 assert ( false );
00496 }
00497
00498 return ind;
00499 }
00500
00509 int NN::getBiasIndex ( int layer, int neuron )
00510 {
00511 if ( layer == 0 )
00512 assert ( false );
00513
00514 int nrNeur = m_neuronsPerLayer[layer];
00515 int nrNeurPrev = m_neuronsPerLayer[layer-1];
00516 if ( neuron >= nrNeur )
00517 {
00518 cout<<"neuron:"<<neuron<<" nrNeur:"<<nrNeur<<endl;
00519 assert ( false );
00520 }
00521 int ind = m_nrLayWeightOffsets[layer];
00522 if ( layer == 1 )
00523 ind += neuron* ( nrNeurPrev + 1 );
00524 else
00525 ind += nrNeurPrev + neuron* ( nrNeurPrev + 1 );
00526
00527 if ( ind >= m_nrWeights )
00528 {
00529 cout<<"ind:"<<ind<<" m_nrWeights:"<<m_nrWeights<<endl;
00530 assert ( false );
00531 }
00532
00533 return ind;
00534 }
00535
00544 int NN::getOutputIndex ( int layer, int neuron )
00545 {
00546 if ( layer == 0 || layer > m_nrLayer )
00547 assert ( false );
00548
00549 if ( neuron >= m_neuronsPerLayer[layer] )
00550 assert ( false );
00551
00552 int ind = 0;
00553 for ( int i=0;i<layer;i++ )
00554 ind += m_neuronsPerLayer[i] + 1;
00555
00556 return ind + neuron;
00557 }
00558
00565 void NN::setNNStructure ( int nrLayer, int* neuronsPerLayer )
00566 {
00567 m_nrLayer = nrLayer;
00568 cout<<"nrLayer: "<<m_nrLayer<<endl;
00569
00570 cout<<"#layers: "<<m_nrLayer<<" ("<< ( m_nrLayer-1 ) <<" hidden layer, 1 output layer)"<<endl;
00571
00572
00573 m_neuronsPerLayer = new int[m_nrLayer+1];
00574 m_neuronsPerLayer[0] = m_nrInputs;
00575 for ( int i=0;i<m_nrLayer-1;i++ )
00576 m_neuronsPerLayer[1+i] = neuronsPerLayer[i];
00577 m_neuronsPerLayer[m_nrLayer] = m_nrTargets;
00578
00579 cout<<"Neurons per Layer: ";
00580 for ( int i=0;i<m_nrLayer+1;i++ )
00581 cout<<m_neuronsPerLayer[i]<<" ";
00582 cout<<endl;
00583
00584 cout<<"Outputs per Layer: ";
00585 for ( int i=0;i<m_nrLayer+1;i++ )
00586 cout<<m_neuronsPerLayer[i]+1<<" ";
00587 cout<<endl;
00588
00589 cout<<"OutOffsets per Layer: ";
00590 int cnt=0;
00591 for ( int i=0;i<m_nrLayer+1;i++ )
00592 {
00593 cout<<cnt<<" ";
00594 cnt += m_neuronsPerLayer[i]+1;
00595 }
00596 cout<<endl;
00597
00598
00599 m_nrWeights = 0;
00600 m_nrOutputs = m_neuronsPerLayer[0] + 1;
00601 m_nrLayWeights = new int[m_nrLayer+1];
00602 m_nrLayWeightOffsets = new int[m_nrLayer+2];
00603 m_nrLayWeights[0] = 0;
00604 for ( int i=0;i<m_nrLayer;i++ )
00605 {
00606 m_nrLayWeights[i+1] = m_neuronsPerLayer[i+1] * ( m_neuronsPerLayer[i]+1 );
00607 m_nrWeights += m_nrLayWeights[i+1];
00608 m_nrOutputs += m_neuronsPerLayer[i+1] + 1;
00609 }
00610
00611
00612 cout<<"Weights per Layer: ";
00613 for ( int i=0;i<m_nrLayer+1;i++ )
00614 cout<<m_nrLayWeights[i]<<" ";
00615 cout<<endl;
00616
00617 cout<<"WeightOffsets per Layer: ";
00618 m_nrLayWeightOffsets[0] = 0;
00619 for ( int i=0;i<m_nrLayer+1;i++ )
00620 {
00621 cout<<m_nrLayWeightOffsets[i]<<" ";
00622 m_nrLayWeightOffsets[i+1] = m_nrLayWeightOffsets[i] + m_nrLayWeights[i];
00623 }
00624 cout<<endl;
00625
00626 cout<<"nrOutputs="<<m_nrOutputs<<" nrWeights="<<m_nrWeights<<endl;
00627
00628
00629 m_outputs = new REAL[m_nrOutputs];
00630 m_outputsTmp = new REAL[m_nrTargets];
00631 m_derivates = new REAL[m_nrOutputs];
00632 m_d1 = new REAL[m_nrOutputs];
00633
00634 for ( int i=0;i<m_nrOutputs;i++ )
00635 {
00636 m_outputs[i] = 1.0;
00637 m_derivates[i] = 0.0;
00638 m_d1[i] = 0.0;
00639 }
00640
00641
00642 m_weights = new REAL[m_nrWeights];
00643 m_weightsTmp0 = new REAL[m_nrWeights];
00644 m_weightsTmp1 = new REAL[m_nrWeights];
00645 m_weightsTmp2 = new REAL[m_nrWeights];
00646 m_weightsBatchUpdate = new REAL[m_nrWeights];
00647 m_weightsOld = new REAL[m_nrWeights];
00648 m_weightsOldOld = new REAL[m_nrWeights];
00649 m_deltaW = new REAL[m_nrWeights];
00650
00651 m_deltaWOld = new REAL[m_nrWeights];
00652 m_adaptiveRPROPlRate = new REAL[m_nrWeights];
00653 for ( int i=0;i<m_nrWeights;i++ )
00654 {
00655 m_deltaWOld[i] = 0.0;
00656 m_adaptiveRPROPlRate[i] = m_learnRate;
00657 }
00658 for ( int i=0;i<m_nrWeights;i++ )
00659 m_weights[i] = m_weightsOld[i] = m_deltaW[i] = m_weightsTmp0[i] = m_weightsTmp1[i] = m_weightsTmp2[i] = 0.0;
00660
00661
00662
00663
00664 }
00665
00673 REAL NN::getInitWeight ( int fanIn )
00674 {
00675 double nr = 2.0* ( rand() / ( double ) RAND_MAX-0.5 );
00676 return ( 1.0/sqrt ( ( double ) fanIn ) ) * nr;
00677 }
00678
00684 void NN::initNNWeights ( time_t seed )
00685 {
00686 srand ( seed );
00687 cout<<"init weights ";
00688 REAL factor = m_initWeightFactor;
00689 int cnt = 0;
00690 for ( int i=0;i<m_nrLayer;i++ )
00691 {
00692 int n = m_neuronsPerLayer[i+1];
00693 int nprev = m_neuronsPerLayer[i] + 1;
00694 for ( int j=0;j<n;j++ )
00695 {
00696 for ( int k=0;k<nprev;k++ )
00697 {
00698 m_weights[cnt] = m_weightsOld[i] = m_weightsOldOld[i] = getInitWeight ( nprev ) * factor;
00699 cnt++;
00700 }
00701 }
00702 }
00703
00704
00705 if ( cnt != m_nrWeights )
00706 assert ( false );
00707 }
00708
00717 void NN::backpropBLAS ( REAL* input, REAL* target )
00718 {
00719 REAL sum0, d1;
00720
00721 int outputOffset = m_nrOutputs - m_neuronsPerLayer[m_nrLayer] - 1;
00722 int n0 = m_neuronsPerLayer[m_nrLayer-1];
00723 int outputOffsetPrev = outputOffset - n0 - 1;
00724 int outputOffsetNext = outputOffset;
00725
00726 int weightOffset = m_nrWeights - m_nrLayWeights[m_nrLayer];
00727 int weightOffsetNext, nP1;
00728
00729 REAL *deltaWPtr, *derivatesPtr, *weightsPtr, *outputsPtr, *d1Ptr, *d1Ptr0, targetConverted, error;
00730
00731
00732 for ( int i=0;i<m_nrTargets;i++ )
00733 {
00734 REAL out = m_outputs[outputOffset+i];
00735
00736 REAL errorTrain = out * m_scaleOutputs + m_offsetOutputs - target[i];
00737 m_sumSquaredError += errorTrain * errorTrain;
00738 m_sumSquaredErrorSamples += 1.0;
00739
00740 targetConverted = ( target[i] - m_offsetOutputs ) / m_scaleOutputs;
00741 error = out - targetConverted;
00742
00743 if ( m_errorFunctionMAE )
00744 error = error > 0.0? 1.0 : -1.0;
00745 d1 = error * m_derivates[outputOffset+i];
00746 m_d1[outputOffset+i] = d1;
00747 deltaWPtr = m_deltaW + weightOffset + i* ( n0+1 );
00748 if ( m_nrLayer==1 )
00749 {
00750 outputsPtr = input - 1;
00751 deltaWPtr[0] = d1;
00752 for ( int j=1;j<n0+1;j++ )
00753 deltaWPtr[j] = d1 * outputsPtr[j];
00754 }
00755 else
00756 {
00757 outputsPtr = m_outputs + outputOffsetPrev;
00758 for ( int j=0;j<n0+1;j++ )
00759 deltaWPtr[j] = d1 * outputsPtr[j];
00760 }
00761 }
00762
00763
00764 outputOffsetNext = outputOffset;
00765 outputOffset = outputOffsetPrev;
00766 n0 = m_neuronsPerLayer[m_nrLayer-2];
00767 outputOffsetPrev -= n0 + 1;
00768 weightOffset -= m_nrLayWeights[m_nrLayer-1];
00769 weightOffsetNext = m_nrWeights - m_nrLayWeights[m_nrLayer];
00770
00771 for ( int i=m_nrLayer-1;i>0;i-- )
00772 {
00773 int n = m_neuronsPerLayer[i];
00774 int nNext = m_neuronsPerLayer[i+1];
00775 int nPrev = m_neuronsPerLayer[i-1];
00776 nP1 = n+1;
00777
00778 d1Ptr0 = m_d1 + outputOffsetNext;
00779 derivatesPtr = m_derivates + outputOffset;
00780 weightsPtr = m_weights + weightOffsetNext;
00781 d1Ptr = m_d1 + outputOffset;
00782 deltaWPtr = m_deltaW + weightOffset;
00783 if ( i==1 )
00784 outputsPtr = input;
00785 else
00786 outputsPtr = m_outputs + outputOffsetPrev;
00787
00788
00789 CBLAS_GEMV ( CblasRowMajor, CblasTrans, nNext, n, 1.0, weightsPtr, nP1, d1Ptr0, 1, 0.0, d1Ptr, 1 );
00790 V_MUL ( n, d1Ptr, derivatesPtr, d1Ptr );
00791
00792
00793 for ( int j=0;j<n;j++ )
00794 {
00795 if ( i==1 )
00796 {
00797 V_COPY ( outputsPtr, deltaWPtr+1, nPrev );
00798 deltaWPtr[0] = 1.0;
00799 }
00800 else
00801 V_COPY ( outputsPtr, deltaWPtr, nPrev+1 );
00802 V_MULC ( deltaWPtr, d1Ptr[j], deltaWPtr, nPrev+1 );
00803 deltaWPtr += nPrev+1;
00804 }
00805
00806 outputOffsetNext = outputOffset;
00807 outputOffset = outputOffsetPrev;
00808 n0 = m_neuronsPerLayer[i-2];
00809 outputOffsetPrev -= n0 + 1;
00810 weightOffset -= m_nrLayWeights[i-1];
00811 weightOffsetNext -= m_nrLayWeights[i];
00812 }
00813 }
00814
00823 void NN::backprop ( REAL* input, REAL* target )
00824 {
00825 REAL sum0, d1;
00826
00827 int outputOffset = m_nrOutputs - m_neuronsPerLayer[m_nrLayer] - 1;
00828 int n0 = m_neuronsPerLayer[m_nrLayer-1];
00829 int outputOffsetPrev = outputOffset - n0 - 1;
00830 int outputOffsetNext = outputOffset;
00831
00832 int weightOffset = m_nrWeights - m_nrLayWeights[m_nrLayer];
00833 int weightOffsetNext, nP1;
00834
00835 REAL *deltaWPtr, *derivatesPtr, *weightsPtr, *outputsPtr, *d1Ptr, *d1Ptr0, targetConverted, error;
00836
00837
00838 for ( int i=0;i<m_nrTargets;i++ )
00839 {
00840 double out = m_outputs[outputOffset+i];
00841
00842 REAL errorTrain = out * m_scaleOutputs + m_offsetOutputs - target[i];
00843 m_sumSquaredError += errorTrain * errorTrain;
00844 m_sumSquaredErrorSamples++;
00845
00846 targetConverted = ( target[i] - m_offsetOutputs ) / m_scaleOutputs;
00847 error = out - targetConverted;
00848
00849 if ( m_errorFunctionMAE )
00850 error = error > 0.0? 1.0 : -1.0;
00851 d1 = error * m_derivates[outputOffset+i];
00852 m_d1[outputOffset+i] = d1;
00853 deltaWPtr = m_deltaW + weightOffset + i* ( n0+1 );
00854 if ( m_nrLayer==1 )
00855 {
00856 outputsPtr = input - 1;
00857 deltaWPtr[0] = d1;
00858 for ( int j=1;j<n0+1;j++ )
00859 deltaWPtr[j] = d1 * outputsPtr[j];
00860 }
00861 else
00862 {
00863 outputsPtr = m_outputs + outputOffsetPrev;
00864 for ( int j=0;j<n0+1;j++ )
00865 deltaWPtr[j] = d1 * outputsPtr[j];
00866 }
00867
00868 }
00869
00870
00871 outputOffsetNext = outputOffset;
00872 outputOffset = outputOffsetPrev;
00873 n0 = m_neuronsPerLayer[m_nrLayer-2];
00874 outputOffsetPrev -= n0 + 1;
00875 weightOffset -= m_nrLayWeights[m_nrLayer-1];
00876 weightOffsetNext = m_nrWeights - m_nrLayWeights[m_nrLayer];
00877
00878 for ( int i=m_nrLayer-1;i>0;i-- )
00879 {
00880 int n = m_neuronsPerLayer[i];
00881 int nNext = m_neuronsPerLayer[i+1];
00882 int nPrev = m_neuronsPerLayer[i-1];
00883 nP1 = n+1;
00884
00885 d1Ptr0 = m_d1 + outputOffsetNext;
00886 derivatesPtr = m_derivates + outputOffset;
00887 weightsPtr = m_weights + weightOffsetNext;
00888 d1Ptr = m_d1 + outputOffset;
00889 deltaWPtr = m_deltaW + weightOffset;
00890 if ( i==1 )
00891 outputsPtr = input - 1;
00892 else
00893 outputsPtr = m_outputs + outputOffsetPrev;
00894
00895 for ( int j=0;j<n;j++ )
00896 {
00897
00898 sum0 = 0.0;
00899 for ( int k=0;k<nNext;k++ )
00900 sum0 += d1Ptr0[k] * weightsPtr[k*nP1];
00901 sum0 *= *derivatesPtr;
00902 d1Ptr[j] = sum0;
00903
00904
00905 if ( i==1 )
00906 {
00907 deltaWPtr[0] = sum0;
00908 for ( int k=1;k<nPrev+1;k++ )
00909 deltaWPtr[k] = sum0 * outputsPtr[k];
00910 }
00911 else
00912 {
00913 for ( int k=0;k<nPrev+1;k++ )
00914 deltaWPtr[k] = sum0 * outputsPtr[k];
00915 }
00916 deltaWPtr += nPrev+1;
00917 weightsPtr ++;
00918 derivatesPtr++;
00919 }
00920
00921 outputOffsetNext = outputOffset;
00922 outputOffset = outputOffsetPrev;
00923 n0 = m_neuronsPerLayer[i-2];
00924 outputOffsetPrev -= n0 + 1;
00925 weightOffset -= m_nrLayWeights[i-1];
00926 weightOffsetNext -= m_nrLayWeights[i];
00927 }
00928
00929 }
00930
00938 void NN::forwardCalculationBLAS ( REAL* input )
00939 {
00940 int outputOffset = m_neuronsPerLayer[0]+1, outputOffsetPrev = 0;
00941 REAL tmp0, tmp1, sum0;
00942 REAL *outputPtr, *ptr0, *ptr1, *weightPtr = m_weights;
00943
00944 for ( int i=0;i<m_nrLayer;i++ )
00945 {
00946 int n = m_neuronsPerLayer[i+1];
00947 int nprev = m_neuronsPerLayer[i] + 1;
00948 int inputOffset = 0;
00949 ptr0 = m_outputs + outputOffset;
00950 ptr1 = m_derivates + outputOffset;
00951 if ( i==0 )
00952 {
00953 outputPtr = input;
00954 inputOffset = 1;
00955 }
00956 else
00957 outputPtr = m_outputs + outputOffsetPrev;
00958
00959
00960 CBLAS_GEMV ( CblasRowMajor, CblasNoTrans, n, nprev - inputOffset, 1.0, weightPtr + inputOffset, nprev, outputPtr, 1, 0.0, ptr0, 1 );
00961 if ( inputOffset )
00962 {
00963 for ( int j=0;j<n;j++ )
00964 ptr0[j] += weightPtr[j * nprev];
00965 }
00966
00967 if(m_activationFunctionType == 0)
00968 {
00969
00970 V_TANH ( n, ptr0, ptr0 );
00971 V_SQR ( n, ptr0, ptr1 );
00972 for ( int j=0;j<n;j++ )
00973 ptr1[j] = 1.0 - ptr1[j];
00974 }
00975 else if(m_activationFunctionType == 1)
00976 {
00977
00978 REAL piHalf = 1.570796326794897;
00979 for(int j=0;j<n;j++)
00980 {
00981 REAL v = ptr0[j], sign = v>0.0? 1.0 : -1.0;
00982 if(v > -piHalf && v < piHalf)
00983 {
00984 ptr0[j] = sin(v) + v * 0.01;
00985 ptr1[j] = cos(v) + sign * 0.01;
00986 }
00987 else
00988 {
00989 ptr0[j] = sign + v * 0.01;
00990 ptr1[j] = sign * 0.01;
00991 }
00992 }
00993 }
00994 else if(m_activationFunctionType == 2)
00995 {
00996
00997
00998 REAL mul = 0.5;
00999 for(int j=0;j<n;j++)
01000 {
01001 REAL v = ptr0[j], tanhV = tanh(v), tanhVNeg = -tanhV;
01002 if(v >= 0.0)
01003 {
01004 ptr0[j] = pow(v,1.0+tanhV*mul);
01005 ptr1[j] = pow(v,tanhV*mul)*(1.0+tanhV*mul)+ptr0[j]*log(v)*mul*(1.0-tanhV*tanhV);
01006 if(isnan(ptr1[j]) || isinf(ptr1[j]))
01007 ptr1[j] = 1.0;
01008 }
01009 else
01010 {
01011 ptr0[j] = -pow(-v,1.0+tanhVNeg*mul);
01012 ptr1[j] = -pow(-v,tanhVNeg*mul)*(1.0+tanhVNeg*mul)*(-1.0)+ptr0[j]*log(-v)*mul*(1.0-tanhV*tanhV)*(-1.0);
01013 if(isnan(ptr1[j]) || isinf(ptr1[j]))
01014 ptr1[j] = -1.0;
01015 }
01016 }
01017 }
01018 else
01019 assert(false);
01020
01021
01022 weightPtr += n*nprev;
01023 outputOffset += n+1;
01024 outputOffsetPrev += nprev;
01025
01026 }
01027
01028 }
01029
01037 void NN::forwardCalculation ( REAL* input )
01038 {
01039 int outputOffset = m_neuronsPerLayer[0] + 1, outputOffsetPrev = 0;
01040 REAL tmp0, tmp1, sum0;
01041 REAL *outputPtr, *ptr0, *ptr1, *weightPtr = m_weights;
01042 for ( int i=0;i<m_nrLayer;i++ )
01043 {
01044 int n = m_neuronsPerLayer[i+1];
01045 int nprev = m_neuronsPerLayer[i] + 1;
01046 int loopOffset = i==0? 1 : 0;
01047 ptr0 = m_outputs + outputOffset;
01048 ptr1 = m_derivates + outputOffset;
01049 if ( i==0 )
01050 outputPtr = input - loopOffset;
01051 else
01052 outputPtr = m_outputs + outputOffsetPrev;
01053 for ( int j=0;j<n;j++ )
01054 {
01055 sum0 = i==0? weightPtr[0] : 0.0;
01056 for ( int k=loopOffset;k<nprev;k++ )
01057 sum0 += weightPtr[k] * outputPtr[k];
01058 weightPtr += nprev;
01059
01060 if(m_activationFunctionType == 0)
01061 {
01062
01063 tmp0 = tanh ( sum0 );
01064 ptr0[j] = tmp0;
01065 ptr1[j] = ( 1.0 - tmp0*tmp0 );
01066 }
01067 else if(m_activationFunctionType == 1)
01068 {
01069
01070 REAL piHalf = 1.570796326794897;
01071 REAL v = ptr0[j], sign = v>0.0? 1.0 : -1.0;
01072 if(v > -piHalf && v < piHalf)
01073 {
01074 ptr0[j] = sin(v) + v * 0.01;
01075 ptr1[j] = cos(v) + sign * 0.01;
01076 }
01077 else
01078 {
01079 ptr0[j] = sign + v * 0.01;
01080 ptr1[j] = sign * 0.01;
01081 }
01082 }
01083 else if(m_activationFunctionType == 2)
01084 {
01085
01086
01087 REAL mul = 0.5;
01088 REAL v = ptr0[j], tanhV = tanh(v), tanhVNeg = -tanhV;
01089 if(v >= 0.0)
01090 {
01091 ptr0[j] = pow(v,1.0+tanhV*mul);
01092 ptr1[j] = pow(v,tanhV*mul)*(1.0+tanhV*mul)+ptr0[j]*log(v)*mul*(1.0-tanhV*tanhV);
01093 if(isnan(ptr1[j]) || isinf(ptr1[j]))
01094 ptr1[j] = 1.0;
01095 }
01096 else
01097 {
01098 ptr0[j] = -pow(-v,1.0+tanhVNeg*mul);
01099 ptr1[j] = -pow(-v,tanhVNeg*mul)*(1.0+tanhVNeg*mul)*(-1.0)+ptr0[j]*log(-v)*mul*(1.0-tanhV*tanhV)*(-1.0);
01100 if(isnan(ptr1[j]) || isinf(ptr1[j]))
01101 ptr1[j] = -1.0;
01102 }
01103 }
01104 else
01105 assert(false);
01106 }
01107 outputOffset += n+1;
01108 outputOffsetPrev += nprev;
01109 }
01110
01111 }
01112
01119 int NN::trainNN()
01120 {
01121 cout<<"Train the NN with "<<m_nrExamplesTrain<<" samples"<<endl;
01122 double rmseMin = 1e10, lastUpdate = 1e10, rmseProbeOld = 1e10, rmseTrain = 1e10, rmseProbe = 1e10;
01123 time_t t0 = time ( 0 );
01124 while ( 1 )
01125 {
01126 rmseProbeOld = rmseProbe;
01127 rmseTrain = getRMSETrain();
01128 rmseProbe = getRMSEProbe();
01129 lastUpdate = rmseProbeOld - rmseProbe;
01130
01131 cout<<"e:"<<m_globalEpochs<<" rmseTrain:"<<rmseTrain<<" rmseProbe:"<<rmseProbe<<" "<<flush;
01132
01133 if ( m_normalTrainStopping )
01134 {
01135 if ( rmseProbe < rmseMin )
01136 {
01137 rmseMin = rmseProbe;
01138 saveWeights();
01139 }
01140 else
01141 {
01142 cout<<"rmse rises."<<endl;
01143 return m_globalEpochs;
01144 }
01145 if ( m_minUpdateBound > fabs ( lastUpdate ) )
01146 {
01147 cout<<"min update too small (<"<<m_minUpdateBound<<")."<<endl;
01148 return m_globalEpochs;
01149 }
01150 }
01151 if ( m_maxEpochs == m_globalEpochs )
01152 {
01153 cout<<"max epochs reached."<<endl;
01154 return m_globalEpochs;
01155 }
01156
01157 trainOneEpoch();
01158
01159 cout<<"lRate:"<<m_learnRate<<" ";
01160 cout<<time ( 0 )-t0<<"[s]"<<endl;
01161 t0 = time ( 0 );
01162 }
01163 return -1;
01164 }
01165
01170 void NN::trainOneEpoch()
01171 {
01172 int batchCnt = 0;
01173 V_ZERO ( m_weightsBatchUpdate, m_nrWeights );
01174 m_sumSquaredError = 0.0;
01175 m_sumSquaredErrorSamples = 0.0;
01176
01177 for ( int i=0;i<m_nrExamplesTrain;i++ )
01178 {
01179 REAL* inputPtr = m_inputsTrain + i * m_nrInputs;
01180 REAL* targetPtr = m_targetsTrain + i * m_nrTargets;
01181
01182
01183 if ( m_useBLAS )
01184 forwardCalculationBLAS ( inputPtr );
01185 else
01186 forwardCalculation ( inputPtr );
01187
01188
01189 if ( m_useBLAS )
01190 backpropBLAS ( inputPtr, targetPtr );
01191 else
01192 backprop ( inputPtr, targetPtr );
01193
01194
01195 if ( m_batchSize > 1 )
01196 V_ADD ( m_nrWeights, m_deltaW, m_weightsBatchUpdate, m_weightsBatchUpdate );
01197
01198 batchCnt++;
01199
01200
01201 if ( batchCnt >= m_batchSize || i == m_nrExamplesTrain - 1 )
01202 {
01203
01204 batchCnt = 0;
01205 if ( m_batchSize > 1 )
01206 {
01207 V_COPY ( m_weightsBatchUpdate, m_deltaW, m_nrWeights );
01208 V_ZERO ( m_weightsBatchUpdate, m_nrWeights );
01209 }
01210
01211 if ( m_enableRPROP )
01212 {
01213
01214
01215
01216
01217
01218
01219
01220
01221 REAL dW, dWOld, sign, update, prod;
01222 for ( int j=0;j<m_nrWeights;j++ )
01223 {
01224 dW = m_deltaW[j];
01225 dWOld = m_deltaWOld[j];
01226 prod = dW * dWOld;
01227 sign = dW > 0.0? 1.0 : -1.0;
01228 if ( prod > 0.0 )
01229 {
01230 m_adaptiveRPROPlRate[j] *= m_RPROP_etaPos;
01231 if ( m_adaptiveRPROPlRate[j] > m_RPROP_updateMax )
01232 m_adaptiveRPROPlRate[j] = m_RPROP_updateMax;
01233 update = sign * m_adaptiveRPROPlRate[j];
01234 m_weights[j] -= update + m_weightDecay * m_weights[j];
01235 m_deltaWOld[j] = dW;
01236 }
01237 else if ( prod < 0.0 )
01238 {
01239 m_adaptiveRPROPlRate[j] *= m_RPROP_etaNeg;
01240 if ( m_adaptiveRPROPlRate[j] < m_RPROP_updateMin )
01241 m_adaptiveRPROPlRate[j] = m_RPROP_updateMin;
01242 m_deltaWOld[j] = 0.0;
01243 }
01244 else
01245 {
01246 update = sign * m_adaptiveRPROPlRate[j];
01247 m_weights[j] -= update + m_weightDecay * m_weights[j];
01248 m_deltaWOld[j] = dW;
01249 }
01250 }
01251 }
01252 else
01253 {
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281 V_MULC ( m_deltaW, m_learnRate, m_weightsTmp0, m_nrWeights );
01282
01283
01284 if ( m_weightDecay > 0.0 )
01285 {
01286 if ( m_enableL1Regularization )
01287 {
01288
01289
01290
01291 for ( int j=0;j<m_nrWeights;j++ )
01292 m_weightsTmp2[j] = 1.0;
01293 for ( int j=0;j<m_nrWeights;j++ )
01294 if ( m_weights[j]<0.0 )
01295 m_weightsTmp2[j] = -1.0;
01296
01297
01298
01299 CBLAS_AXPY ( m_nrWeights, m_weightDecay * m_learnRate, m_weightsTmp2, 1, m_weightsTmp0, 1 );
01300 }
01301 else
01302
01303
01304 CBLAS_AXPY ( m_nrWeights, m_weightDecay * m_learnRate, m_weights, 1, m_weightsTmp0, 1 );
01305 }
01306
01307
01308 if ( m_momentum > 0.0 )
01309 {
01310 V_MULC ( m_weightsTmp0, 1.0 - m_momentum, m_weightsTmp0, m_nrWeights );
01311 V_MULC ( m_weightsTmp1, m_momentum, m_weightsTmp1, m_nrWeights );
01312
01313
01314 V_ADD ( m_nrWeights, m_weightsTmp0, m_weightsTmp1, m_weightsTmp0 );
01315
01316 V_COPY ( m_weightsTmp0, m_weightsTmp1, m_nrWeights );
01317 }
01318
01319
01320 V_SUB ( m_nrWeights, m_weights, m_weightsTmp0, m_weights );
01321 }
01322 }
01323
01324
01325 m_learnRate -= m_learnrateDecreaseRate;
01326 if ( m_learnRate < m_learnRateMin )
01327 m_learnRate = m_learnRateMin;
01328
01329 }
01330
01331
01332 m_learnRate -= m_learnrateDecreaseRateEpoch;
01333 if ( m_learnRate < m_learnRateMin )
01334 m_learnRate = m_learnRateMin;
01335
01336
01337 m_globalEpochs++;
01338
01339 }
01340
01347 void NN::setGlobalEpochs ( int e )
01348 {
01349 m_globalEpochs = e;
01350 }
01351
01356 void NN::printLearnrate()
01357 {
01358 cout<<"lRate:"<<m_learnRate<<" "<<flush;
01359 }
01360
01365 void NN::saveWeights()
01366 {
01367
01368 }
01369
01377 void NN::predictSingleInput ( REAL* input, REAL* output )
01378 {
01379 REAL* inputPtr = input;
01380
01381
01382 if ( m_useBLAS )
01383 forwardCalculationBLAS ( inputPtr );
01384 else
01385 forwardCalculation ( inputPtr );
01386
01387
01388 REAL* outputPtr = m_outputs + m_nrOutputs - m_nrTargets - 1;
01389 for ( int i=0;i<m_nrTargets;i++ )
01390 output[i] = outputPtr[i] * m_scaleOutputs + m_offsetOutputs;
01391 }
01392
01401 REAL NN::calcRMSE ( REAL* inputs, REAL* targets, int examples )
01402 {
01403 double rmse = 0.0;
01404 for ( int i=0;i<examples;i++ )
01405 {
01406 REAL* inputPtr = inputs + i * m_nrInputs;
01407 REAL* targetPtr = targets + i * m_nrTargets;
01408
01409 predictSingleInput ( inputPtr, m_outputsTmp );
01410
01411 for ( int j=0;j<m_nrTargets;j++ )
01412 rmse += ( m_outputsTmp[j] - targetPtr[j] ) * ( m_outputsTmp[j] - targetPtr[j] );
01413 }
01414 rmse = sqrt ( rmse/ ( double ) ( examples*m_nrTargets ) );
01415 return rmse;
01416 }
01417
01423 REAL NN::getRMSETrain()
01424 {
01425 return calcRMSE ( m_inputsTrain, m_targetsTrain, m_nrExamplesTrain );
01426 }
01427
01433 REAL NN::getRMSEProbe()
01434 {
01435 return calcRMSE ( m_inputsProbe, m_targetsProbe, m_nrExamplesProbe );
01436 }
01437
01443 REAL* NN::getWeightPtr()
01444 {
01445 return m_weights;
01446 }
01447
01453 void NN::setWeights ( REAL* w )
01454 {
01455 cout<<"Set new weights"<<endl;
01456 for ( int i=0;i<m_nrWeights;i++ )
01457 m_weights[i] = w[i];
01458 }
01459
01465 int NN::getNrWeights()
01466 {
01467 return m_nrWeights;
01468 }