2 #define GRT_DLL_EXPORTS 7 BernoulliRBM::BernoulliRBM(
const UINT numHiddenUnits,
const UINT maxNumEpochs,
const Float learningRate,
const Float learningRateUpdate,
const Float momentum,
const bool useScaling,
const bool randomiseTrainingOrder) :
MLBase(
"BernoulliRBM")
10 this->numHiddenUnits = numHiddenUnits;
11 this->maxNumEpochs = maxNumEpochs;
12 this->learningRate = learningRate;
13 this->learningRateUpdate = learningRateUpdate;
14 this->momentum = momentum;
15 this->useScaling = useScaling;
16 this->randomiseTrainingOrder = randomiseTrainingOrder;
17 randomizeWeightsForTraining =
true;
24 BernoulliRBM::~BernoulliRBM(){
30 if( !
predict_(inputData,outputData) ){
40 errorLog <<
"predict_(VectorFloat &inputData,VectorFloat &outputData) - Failed to run prediction - the model has not been trained." << std::endl;
44 if( inputData.size() != numVisibleUnits ){
45 errorLog <<
"predict_(VectorFloat &inputData,VectorFloat &outputData) - Failed to run prediction - the input data size (" << inputData.size() <<
")";
46 errorLog <<
" does not match the number of visible units (" << numVisibleUnits <<
"). " << std::endl;
50 if( outputData.size() != numHiddenUnits ){
51 outputData.
resize( numHiddenUnits );
56 for(UINT i=0; i<numVisibleUnits; i++){
57 inputData[i] = grt_scale(inputData[i],ranges[i].minValue,ranges[i].maxValue,0.0,1.0);
63 for(UINT i=0; i<numHiddenUnits; i++){
65 for(UINT j=0; j<numVisibleUnits; j++) {
66 x += weightsMatrix[i][j] * inputData[j];
68 outputData[i] = grt_sigmoid( x + hiddenLayerBias[i] );
77 errorLog <<
"predict_(const MatrixFloat &inputData,MatrixFloat &outputData,const UINT rowIndex) - Failed to run prediction - the model has not been trained." << std::endl;
81 if( inputData.
getNumCols() != numVisibleUnits ){
82 errorLog <<
"predict_(const MatrixFloat &inputData,MatrixFloat &outputData,const UINT rowIndex) -";
83 errorLog <<
" Failed to run prediction - the number of columns in the input matrix (" << inputData.
getNumCols() <<
")";
84 errorLog <<
" does not match the number of visible units (" << numVisibleUnits <<
")." << std::endl;
88 if( outputData.
getNumCols() != numHiddenUnits ){
89 errorLog <<
"predict_(const MatrixFloat &inputData,MatrixFloat &outputData,const UINT rowIndex) -";
90 errorLog <<
" Failed to run prediction - the number of columns in the output matrix (" << outputData.
getNumCols() <<
")";
91 errorLog <<
" does not match the number of hidden units (" << numHiddenUnits <<
")." << std::endl;
97 for(UINT j=0; j<numHiddenUnits; j++){
99 for(UINT i=0; i<numVisibleUnits; i++) {
100 x += weightsMatrix[j][i] * inputData[rowIndex][i];
102 outputData[rowIndex][j] = grt_sigmoid( x + hiddenLayerBias[j] );
110 const UINT numTrainingSamples = data.
getNumRows();
112 numOutputDimensions = numHiddenUnits;
113 numVisibleUnits = numInputDimensions;
115 trainingLog <<
"NumInputDimensions: " << numInputDimensions << std::endl;
116 trainingLog <<
"NumOutputDimensions: " << numOutputDimensions << std::endl;
118 if( randomizeWeightsForTraining ){
121 weightsMatrix.resize(numHiddenUnits, numVisibleUnits);
123 Float a = 1.0 / numVisibleUnits;
124 for(UINT i=0; i<numHiddenUnits; i++) {
125 for(UINT j=0; j<numVisibleUnits; j++) {
126 weightsMatrix[i][j] = rand.getRandomNumberUniform(-a, a);
131 visibleLayerBias.resize( numVisibleUnits );
132 hiddenLayerBias.resize( numHiddenUnits );
133 std::fill(visibleLayerBias.begin(),visibleLayerBias.end(),0);
134 std::fill(hiddenLayerBias.begin(),hiddenLayerBias.end(),0);
137 if( weightsMatrix.getNumRows() != numHiddenUnits ){
138 errorLog <<
"train_(MatrixFloat &data) - Weights matrix row size does not match the number of hidden units!" << std::endl;
141 if( weightsMatrix.getNumCols() != numVisibleUnits ){
142 errorLog <<
"train_(MatrixFloat &data) - Weights matrix row size does not match the number of visible units!" << std::endl;
145 if( visibleLayerBias.size() != numVisibleUnits ){
146 errorLog <<
"train_(MatrixFloat &data) - Visible layer bias size does not match the number of visible units!" << std::endl;
149 if( hiddenLayerBias.size() != numHiddenUnits ){
150 errorLog <<
"train_(MatrixFloat &data) - Hidden layer bias size does not match the number of hidden units!" << std::endl;
161 for(UINT i=0; i<numTrainingSamples; i++){
162 for(UINT j=0; j<numInputDimensions; j++){
163 data[i][j] = grt_scale(data[i][j], ranges[j].minValue, ranges[j].maxValue, 0.0, 1.0);
169 const UINT numBatches =
static_cast<UINT
>( ceil( Float(numTrainingSamples)/batchSize ) );
174 for(UINT i=0; i<numBatches; i++){
175 batchIndexs[i].startIndex = startIndex;
176 batchIndexs[i].endIndex = startIndex + batchSize;
179 if( batchIndexs[i].endIndex >= numTrainingSamples ){
180 batchIndexs[i].endIndex = numTrainingSamples;
184 batchIndexs[i].batchSize = batchIndexs[i].endIndex - batchIndexs[i].startIndex;
187 startIndex = batchIndexs[i].endIndex;
191 UINT i,j,n,epoch,noChangeCounter = 0;
193 Float alpha = learningRate;
202 MatrixFloat tmpW( numHiddenUnits, numVisibleUnits );
211 MatrixFloat cDiff( numHiddenUnits, numVisibleUnits );
214 VectorFloat visibleLayerBiasVelocity( numVisibleUnits );
215 VectorFloat hiddenLayerBiasVelocity( numHiddenUnits );
219 std::fill(visibleLayerBiasVelocity.begin(),visibleLayerBiasVelocity.end(),0);
220 std::fill(hiddenLayerBiasVelocity.begin(),hiddenLayerBiasVelocity.end(),0);
223 for(UINT i=0; i<numTrainingSamples; i++) indexList[i] = i;
224 if( randomiseTrainingOrder ){
225 std::random_shuffle(indexList.begin(), indexList.end());
230 for(epoch=0; epoch<maxNumEpochs; epoch++) {
235 std::random_shuffle(batchIndexs.begin(),batchIndexs.end());
238 for(UINT k=0; k<numBatches; k+=batchStepSize){
241 v1.
resize( batchIndexs[k].batchSize, numVisibleUnits );
242 h1.
resize( batchIndexs[k].batchSize, numHiddenUnits );
243 v2.
resize( batchIndexs[k].batchSize, numVisibleUnits );
244 h2.
resize( batchIndexs[k].batchSize, numHiddenUnits );
247 Float **w_p = weightsMatrix.getDataPointer();
255 Float *vlb_p = &visibleLayerBias[0];
256 Float *hlb_p = &hiddenLayerBias[0];
260 for(i=batchIndexs[k].startIndex; i<batchIndexs[k].endIndex; i++){
261 for(j=0; j<numVisibleUnits; j++){
262 v1_p[index][j] = data_p[ indexList[i] ][j];
268 for(i=0; i<numHiddenUnits; i++)
269 for(j=0; j<numVisibleUnits; j++)
270 wT_p[j][i] = w_p[i][j];
274 for(n=0; n<batchIndexs[k].batchSize; n++){
275 for(i=0; i<numHiddenUnits; i++){
276 h1_p[n][i] = sigmoidRandom( h1_p[n][i] + hlb_p[i] );
282 for(n=0; n<batchIndexs[k].batchSize; n++){
283 for(i=0; i<numVisibleUnits; i++){
284 v2_p[n][i] = sigmoidRandom( v2_p[n][i] + vlb_p[i] );
290 for(n=0; n<batchIndexs[k].batchSize; n++){
291 for(i=0; i<numHiddenUnits; i++){
292 h2_p[n][i] = grt_sigmoid( h2_p[n][i] + hlb_p[i] );
302 for(j=0; j<numVisibleUnits; j++){
304 for(i=0; i<batchIndexs[k].batchSize; i++){
305 vDiffSum[j] += vDiff[i][j];
311 for(j=0; j<numHiddenUnits; j++){
313 for(i=0; i<batchIndexs[k].batchSize; i++){
314 hDiffSum[j] += hDiff[i][j];
322 for(i=0; i<numHiddenUnits; i++){
323 for(j=0; j<numVisibleUnits; j++){
324 vW_p[i][j] = ((momentum * vW_p[i][j]) + (alpha * cDiff[i][j])) / batchIndexs[k].batchSize;
327 for(i=0; i<numVisibleUnits; i++){
328 visibleLayerBiasVelocity[i] = ((momentum * visibleLayerBiasVelocity[i]) + (alpha * vDiffSum[i])) / batchIndexs[k].batchSize;
330 for(i=0; i<numHiddenUnits; i++){
331 hiddenLayerBiasVelocity[i] = ((momentum * hiddenLayerBiasVelocity[i]) + (alpha * hDiffSum[i])) / batchIndexs[k].batchSize;
335 weightsMatrix.add( vW );
338 for(i=0; i<numVisibleUnits; i++){
339 visibleLayerBias[i] += visibleLayerBiasVelocity[i];
343 for(i=0; i<numHiddenUnits; i++){
344 hiddenLayerBias[i] += hiddenLayerBiasVelocity[i];
349 for(i=0; i<batchIndexs[k].batchSize; i++){
350 for(j=0; j<numVisibleUnits; j++){
351 err += SQR( v1[i][j] - v2[i][j] );
355 error += err / batchIndexs[k].batchSize;
358 delta = lastError - error;
361 trainingLog <<
"Epoch: " << epoch+1 <<
"/" << maxNumEpochs;
362 trainingLog <<
" Epoch time: " << (timer.
getMilliSeconds()-startTime)/1000.0 <<
" seconds";
363 trainingLog <<
" Learning rate: " << alpha;
364 trainingLog <<
" Momentum: " << momentum;
365 trainingLog <<
" Average reconstruction error: " << error;
366 trainingLog <<
" Delta: " << delta << std::endl;
369 alpha *= learningRateUpdate;
372 trainingResults.push_back(trainingResult);
373 trainingResultsObserverManager.notifyObservers( trainingResult );
376 if( fabs(delta) < minChange ){
377 if( ++noChangeCounter >= minNumEpochs ){
378 trainingLog <<
"Stopping training. MinChange limit reached!" << std::endl;
381 }
else noChangeCounter = 0;
384 trainingLog <<
"Training complete after " << epoch <<
" epochs. Total training time: " << timer.
getMilliSeconds()/1000.0 <<
" seconds" << std::endl;
404 weightsMatrix.clear();
405 weightsMatrix.clear();
406 visibleLayerBias.clear();
407 hiddenLayerBias.clear();
417 randomizeWeightsForTraining =
true;
426 errorLog <<
"save(fstream &file) - The file is not open!" << std::endl;
431 file<<
"GRT_BERNOULLI_RBM_MODEL_FILE_V1.1\n";
434 errorLog <<
"save(fstream &file) - Failed to save base settings to file!" << std::endl;
438 file <<
"NumVisibleUnits: " << numVisibleUnits << std::endl;
439 file <<
"NumHiddenUnits: " << numHiddenUnits << std::endl;
440 file <<
"BatchSize: " << batchSize << std::endl;
441 file <<
"BatchStepSize: " << batchStepSize << std::endl;
442 file <<
"LearningRate: " << learningRate << std::endl;
443 file <<
"LearningRateUpdate: " << learningRateUpdate << std::endl;
444 file <<
"Momentum: " << momentum << std::endl;
445 file <<
"RandomizeWeightsForTraining: " << randomizeWeightsForTraining << std::endl;
447 file <<
"Ranges: \n";
448 for(UINT n=0; n<ranges.size(); n++){
449 file << ranges[n].minValue <<
"\t" << ranges[n].maxValue << std::endl;
454 file <<
"WeightsMatrix: " << std::endl;
455 for(UINT i=0; i<weightsMatrix.getNumRows(); i++){
456 for(UINT j=0; j<weightsMatrix.getNumCols(); j++){
457 file << weightsMatrix[i][j];
458 if( j < weightsMatrix.getNumCols()-1 ) file <<
" ";
463 file <<
"VisibleLayerBias: ";
464 for(
unsigned int i=0; i<visibleLayerBias.size(); i++){
465 file << visibleLayerBias[i];
466 if( i < visibleLayerBias.size()-1 ) file <<
" ";
470 file <<
"HiddenLayerBias: ";
471 for(
unsigned int i=0; i<hiddenLayerBias.size(); i++){
472 file << hiddenLayerBias[i];
473 if( i < hiddenLayerBias.size()-1 ) file <<
" ";
485 errorLog <<
"load(fstream &file) - The file is not open!" << std::endl;
494 if( word ==
"GRT_BERNOULLI_RBM_MODEL_FILE_V1.0" ){
495 return loadLegacyModelFromFile( file );
498 if( word !=
"GRT_BERNOULLI_RBM_MODEL_FILE_V1.1" ){
499 errorLog <<
"load(fstream &file) - Failed to read file header!" << std::endl;
504 errorLog <<
"load(fstream &file) - Failed to load base settings to file!" << std::endl;
510 if( word !=
"NumVisibleUnits:" ){
511 errorLog <<
"load(fstream &file) - Failed to read NumVisibleUnits header!" << std::endl;
514 file >> numVisibleUnits;
518 if( word !=
"NumHiddenUnits:" ){
519 errorLog <<
"load(fstream &file) - Failed to read NumHiddenUnits header!" << std::endl;
522 file >> numHiddenUnits;
526 if( word !=
"BatchSize:" ){
527 errorLog <<
"load(fstream &file) - Failed to read BatchSize header!" << std::endl;
534 if( word !=
"BatchStepSize:" ){
535 errorLog <<
"load(fstream &file) - Failed to read BatchStepSize header!" << std::endl;
538 file >> batchStepSize;
542 if( word !=
"LearningRate:" ){
543 errorLog <<
"load(fstream &file) - Failed to read LearningRate header!" << std::endl;
546 file >> learningRate;
550 if( word !=
"LearningRateUpdate:" ){
551 errorLog <<
"load(fstream &file) - Failed to read LearningRateUpdate header!" << std::endl;
554 file >> learningRateUpdate;
558 if( word !=
"Momentum:" ){
559 errorLog <<
"load(fstream &file) - Failed to read Momentum header!" << std::endl;
566 if( word !=
"RandomizeWeightsForTraining:" ){
567 errorLog <<
"load(fstream &file) - Failed to read RandomizeWeightsForTraining header!" << std::endl;
570 file >> randomizeWeightsForTraining;
574 if( word !=
"Ranges:" ){
575 errorLog <<
"load(fstream &file) - Failed to read Ranges header!" << std::endl;
578 ranges.
resize(numInputDimensions);
579 for(UINT n=0; n<ranges.size(); n++){
580 file >> ranges[n].minValue;
581 file >> ranges[n].maxValue;
589 if( word !=
"WeightsMatrix:" ){
590 errorLog <<
"load(fstream &file) - Failed to read WeightsMatrix header!" << std::endl;
593 weightsMatrix.resize(numHiddenUnits, numVisibleUnits);
595 for(UINT i=0; i<weightsMatrix.getNumRows(); i++){
596 for(UINT j=0; j<weightsMatrix.getNumCols(); j++){
597 file >> weightsMatrix[i][j];
603 if( word !=
"VisibleLayerBias:" ){
604 errorLog <<
"load(fstream &file) - Failed to read VisibleLayerBias header!" << std::endl;
607 visibleLayerBias.resize(numVisibleUnits);
609 for(
unsigned int i=0; i<visibleLayerBias.size(); i++){
610 file >> visibleLayerBias[i];
615 if( word !=
"HiddenLayerBias:" ){
616 errorLog <<
"load(fstream &file) - Failed to read HiddenLayerBias header!" << std::endl;
619 hiddenLayerBias.resize(numHiddenUnits);
621 for(
unsigned int i=0; i<hiddenLayerBias.size(); i++){
622 file >> hiddenLayerBias[i];
635 std::cout <<
"WeightsMatrix: \n";
636 for(UINT i=0; i<numVisibleUnits; i++) {
637 for(UINT j=0; j<numHiddenUnits; j++) {
638 std::cout << weightsMatrix[j][i] <<
"\t";
640 std::cout << std::endl;
642 std::cout << std::endl;
644 std::cout <<
"visible layer bias: ";
645 for(UINT j=0; j<numVisibleUnits; j++) {
646 std::cout << visibleLayerBias[j] <<
"\t";
648 std::cout << std::endl;
650 std::cout <<
"hidden layer bias: ";
651 for(UINT j=0; j<numHiddenUnits; j++) {
652 std::cout << hiddenLayerBias[j] <<
"\t";
654 std::cout << std::endl;
659 bool BernoulliRBM::getRandomizeWeightsForTraining()
const{
660 return randomizeWeightsForTraining;
663 UINT BernoulliRBM::getNumVisibleUnits()
const{
664 return numVisibleUnits;
667 UINT BernoulliRBM::getNumHiddenUnits()
const{
668 return numHiddenUnits;
671 const MatrixFloat& BernoulliRBM::getWeights()
const{
672 return weightsMatrix;
679 bool BernoulliRBM::setNumHiddenUnits(
const UINT numHiddenUnits){
680 this->numHiddenUnits = numHiddenUnits;
685 bool BernoulliRBM::setMomentum(
const Float momentum){
686 this->momentum = momentum;
690 bool BernoulliRBM::setLearningRateUpdate(
const Float learningRateUpdate){
691 this->learningRateUpdate = learningRateUpdate;
695 bool BernoulliRBM::setRandomizeWeightsForTraining(
const bool randomizeWeightsForTraining){
696 this->randomizeWeightsForTraining = randomizeWeightsForTraining;
700 bool BernoulliRBM::setBatchSize(
const UINT batchSize){
701 this->batchSize = batchSize;
705 bool BernoulliRBM::setBatchStepSize(
const UINT batchStepSize){
706 this->batchStepSize = batchStepSize;
713 UINT numGibbsSteps = 0;
716 errorLog <<
"load(fstream &file) - Failed to load base settings to file!" << std::endl;
722 if( word !=
"NumVisibleUnits:" ){
723 errorLog <<
"load(fstream &file) - Failed to read NumVisibleUnits header!" << std::endl;
726 file >> numVisibleUnits;
730 if( word !=
"NumHiddenUnits:" ){
731 errorLog <<
"load(fstream &file) - Failed to read NumHiddenUnits header!" << std::endl;
734 file >> numHiddenUnits;
738 if( word !=
"NumTrainingEpochs:" ){
739 errorLog <<
"load(fstream &file) - Failed to read NumTrainingEpochs header!" << std::endl;
742 file >> maxNumEpochs;
746 if( word !=
"NumGibbsSteps:" ){
747 errorLog <<
"load(fstream &file) - Failed to read NumGibbsSteps header!" << std::endl;
750 file >> numGibbsSteps;
754 if( word !=
"LearningRate:" ){
755 errorLog <<
"load(fstream &file) - Failed to read LearningRate header!" << std::endl;
758 file >> learningRate;
762 if( word !=
"LearningRateUpdate:" ){
763 errorLog <<
"load(fstream &file) - Failed to read LearningRateUpdate header!" << std::endl;
766 file >> learningRateUpdate;
770 if( word !=
"Momentum:" ){
771 errorLog <<
"load(fstream &file) - Failed to read Momentum header!" << std::endl;
778 if( word !=
"RandomizeWeightsForTraining:" ){
779 errorLog <<
"load(fstream &file) - Failed to read RandomizeWeightsForTraining header!" << std::endl;
782 file >> randomizeWeightsForTraining;
786 if( word !=
"Ranges:" ){
787 errorLog <<
"load(fstream &file) - Failed to read Ranges header!" << std::endl;
790 ranges.
resize(numInputDimensions);
791 for(UINT n=0; n<ranges.size(); n++){
792 file >> ranges[n].minValue;
793 file >> ranges[n].maxValue;
801 if( word !=
"WeightsMatrix:" ){
802 errorLog <<
"load(fstream &file) - Failed to read WeightsMatrix header!" << std::endl;
805 weightsMatrix.resize(numHiddenUnits, numVisibleUnits);
807 for(UINT i=0; i<weightsMatrix.getNumRows(); i++){
808 for(UINT j=0; j<weightsMatrix.getNumCols(); j++){
809 file >> weightsMatrix[i][j];
815 if( word !=
"VisibleLayerBias:" ){
816 errorLog <<
"load(fstream &file) - Failed to read VisibleLayerBias header!" << std::endl;
819 visibleLayerBias.resize(numVisibleUnits);
821 for(
unsigned int i=0; i<visibleLayerBias.getSize(); i++){
822 file >> visibleLayerBias[i];
827 if( word !=
"HiddenLayerBias:" ){
828 errorLog <<
"load(fstream &file) - Failed to read HiddenLayerBias header!" << std::endl;
831 hiddenLayerBias.resize(numHiddenUnits);
833 for(
unsigned int i=0; i<hiddenLayerBias.getSize(); i++){
834 file >> hiddenLayerBias[i];
bool setClassificationResult(unsigned int trainingIteration, Float accuracy, MLBase *trainer)
bool saveBaseSettingsToFile(std::fstream &file) const
virtual bool save(std::fstream &file) const
bool predict_(VectorFloat &inputData)
virtual bool resize(const unsigned int size)
This class implements a Bernoulli Restricted Boltzmann machine.
signed long getMilliSeconds()
bool setAllValues(const T &value)
bool subtract(const MatrixFloat &b)
bool loadBaseSettingsFromFile(std::fstream &file)
unsigned int getNumRows() const
bool loadLegacyModelFromFile(std::fstream &file)
<Tell the compiler we are using the base class predict method to stop hidden virtual function warning...
unsigned int getNumCols() const
T ** getDataPointer() const
virtual bool print() const
Vector< MinMax > getRanges() const
virtual bool load(std::fstream &file)
virtual bool train_(MatrixFloat &data)
virtual bool resize(const unsigned int r, const unsigned int c)
MatrixFloat multiple(const Float value) const
This is the main base class that all GRT machine learning algorithms should inherit from...
virtual bool predict_(VectorFloat &inputVector)