6 BernoulliRBM::BernoulliRBM(
const UINT numHiddenUnits,
const UINT maxNumEpochs,
const Float learningRate,
const Float learningRateUpdate,
const Float momentum,
const bool useScaling,
const bool randomiseTrainingOrder){
8 this->numHiddenUnits = numHiddenUnits;
9 this->maxNumEpochs = maxNumEpochs;
10 this->learningRate = learningRate;
11 this->learningRateUpdate = learningRateUpdate;
12 this->momentum = momentum;
13 this->useScaling = useScaling;
14 this->randomiseTrainingOrder = randomiseTrainingOrder;
15 randomizeWeightsForTraining =
true;
21 classType =
"BernoulliRBM";
22 debugLog.setProceedingText(
"[DEBUG BernoulliRBM]");
23 errorLog.setProceedingText(
"[ERROR BernoulliRBM]");
24 trainingLog.setProceedingText(
"[TRAINING BernoulliRBM]");
25 warningLog.setProceedingText(
"[WARNING BernoulliRBM]");
28 BernoulliRBM::~BernoulliRBM(){
34 if( !
predict_(inputData,outputData) ){
44 errorLog <<
"predict_(VectorFloat &inputData,VectorFloat &outputData) - Failed to run prediction - the model has not been trained." << std::endl;
48 if( inputData.size() != numVisibleUnits ){
49 errorLog <<
"predict_(VectorFloat &inputData,VectorFloat &outputData) - Failed to run prediction - the input data size (" << inputData.size() <<
")";
50 errorLog <<
" does not match the number of visible units (" << numVisibleUnits <<
"). " << std::endl;
54 if( outputData.size() != numHiddenUnits ){
55 outputData.
resize( numHiddenUnits );
60 for(UINT i=0; i<numVisibleUnits; i++){
61 inputData[i] = grt_scale(inputData[i],ranges[i].minValue,ranges[i].maxValue,0.0,1.0);
67 for(UINT i=0; i<numHiddenUnits; i++){
68 for(UINT j=0; j<numVisibleUnits; j++) {
69 x += weightsMatrix[i][j] * inputData[j];
71 outputData[i] = grt_sigmoid( x + hiddenLayerBias[i] );
80 errorLog <<
"predict_(const MatrixFloat &inputData,MatrixFloat &outputData,const UINT rowIndex) - Failed to run prediction - the model has not been trained." << std::endl;
84 if( inputData.
getNumCols() != numVisibleUnits ){
85 errorLog <<
"predict_(const MatrixFloat &inputData,MatrixFloat &outputData,const UINT rowIndex) -";
86 errorLog <<
" Failed to run prediction - the number of columns in the input matrix (" << inputData.
getNumCols() <<
")";
87 errorLog <<
" does not match the number of visible units (" << numVisibleUnits <<
")." << std::endl;
91 if( outputData.
getNumCols() != numHiddenUnits ){
92 errorLog <<
"predict_(const MatrixFloat &inputData,MatrixFloat &outputData,const UINT rowIndex) -";
93 errorLog <<
" Failed to run prediction - the number of columns in the output matrix (" << outputData.
getNumCols() <<
")";
94 errorLog <<
" does not match the number of hidden units (" << numHiddenUnits <<
")." << std::endl;
100 for(UINT j=0; j<numHiddenUnits; j++){
102 for(UINT i=0; i<numVisibleUnits; i++) {
103 x += weightsMatrix[j][i] * inputData[rowIndex][i];
105 outputData[rowIndex][j] = grt_sigmoid( x + hiddenLayerBias[j] );
113 const UINT numTrainingSamples = data.
getNumRows();
115 numOutputDimensions = numHiddenUnits;
116 numVisibleUnits = numInputDimensions;
118 trainingLog <<
"NumInputDimensions: " << numInputDimensions << std::endl;
119 trainingLog <<
"NumOutputDimensions: " << numOutputDimensions << std::endl;
121 if( randomizeWeightsForTraining ){
124 weightsMatrix.
resize(numHiddenUnits, numVisibleUnits);
126 Float a = 1.0 / numVisibleUnits;
127 for(UINT i=0; i<numHiddenUnits; i++) {
128 for(UINT j=0; j<numVisibleUnits; j++) {
134 visibleLayerBias.
resize( numVisibleUnits );
135 hiddenLayerBias.
resize( numHiddenUnits );
136 std::fill(visibleLayerBias.begin(),visibleLayerBias.end(),0);
137 std::fill(hiddenLayerBias.begin(),hiddenLayerBias.end(),0);
140 if( weightsMatrix.
getNumRows() != numHiddenUnits ){
141 errorLog <<
"train_(MatrixFloat &data) - Weights matrix row size does not match the number of hidden units!" << std::endl;
144 if( weightsMatrix.
getNumCols() != numVisibleUnits ){
145 errorLog <<
"train_(MatrixFloat &data) - Weights matrix row size does not match the number of visible units!" << std::endl;
148 if( visibleLayerBias.size() != numVisibleUnits ){
149 errorLog <<
"train_(MatrixFloat &data) - Visible layer bias size does not match the number of visible units!" << std::endl;
152 if( hiddenLayerBias.size() != numHiddenUnits ){
153 errorLog <<
"train_(MatrixFloat &data) - Hidden layer bias size does not match the number of hidden units!" << std::endl;
164 for(UINT i=0; i<numTrainingSamples; i++){
165 for(UINT j=0; j<numInputDimensions; j++){
166 data[i][j] = grt_scale(data[i][j], ranges[j].minValue, ranges[j].maxValue, 0.0, 1.0);
172 const UINT numBatches =
static_cast<UINT
>( ceil( Float(numTrainingSamples)/batchSize ) );
177 for(UINT i=0; i<numBatches; i++){
178 batchIndexs[i].startIndex = startIndex;
179 batchIndexs[i].endIndex = startIndex + batchSize;
182 if( batchIndexs[i].endIndex >= numTrainingSamples ){
183 batchIndexs[i].endIndex = numTrainingSamples;
187 batchIndexs[i].batchSize = batchIndexs[i].endIndex - batchIndexs[i].startIndex;
190 startIndex = batchIndexs[i].endIndex;
194 UINT i,j,n,epoch,noChangeCounter = 0;
196 Float alpha = learningRate;
202 TrainingResult trainingResult;
205 MatrixFloat tmpW( numHiddenUnits, numVisibleUnits );
214 MatrixFloat cDiff( numHiddenUnits, numVisibleUnits );
217 VectorFloat visibleLayerBiasVelocity( numVisibleUnits );
218 VectorFloat hiddenLayerBiasVelocity( numHiddenUnits );
222 std::fill(visibleLayerBiasVelocity.begin(),visibleLayerBiasVelocity.end(),0);
223 std::fill(hiddenLayerBiasVelocity.begin(),hiddenLayerBiasVelocity.end(),0);
226 for(UINT i=0; i<numTrainingSamples; i++) indexList[i] = i;
227 if( randomiseTrainingOrder ){
228 std::random_shuffle(indexList.begin(), indexList.end());
233 for(epoch=0; epoch<maxNumEpochs; epoch++) {
238 std::random_shuffle(batchIndexs.begin(),batchIndexs.end());
241 for(UINT k=0; k<numBatches; k+=batchStepSize){
244 v1.
resize( batchIndexs[k].batchSize, numVisibleUnits );
245 h1.
resize( batchIndexs[k].batchSize, numHiddenUnits );
246 v2.
resize( batchIndexs[k].batchSize, numVisibleUnits );
247 h2.
resize( batchIndexs[k].batchSize, numHiddenUnits );
258 Float *vlb_p = &visibleLayerBias[0];
259 Float *hlb_p = &hiddenLayerBias[0];
263 for(i=batchIndexs[k].startIndex; i<batchIndexs[k].endIndex; i++){
264 for(j=0; j<numVisibleUnits; j++){
265 v1_p[index][j] = data_p[ indexList[i] ][j];
271 for(i=0; i<numHiddenUnits; i++)
272 for(j=0; j<numVisibleUnits; j++)
273 wT_p[j][i] = w_p[i][j];
277 for(n=0; n<batchIndexs[k].batchSize; n++){
278 for(i=0; i<numHiddenUnits; i++){
279 h1_p[n][i] = sigmoidRandom( h1_p[n][i] + hlb_p[i] );
285 for(n=0; n<batchIndexs[k].batchSize; n++){
286 for(i=0; i<numVisibleUnits; i++){
287 v2_p[n][i] = sigmoidRandom( v2_p[n][i] + vlb_p[i] );
293 for(n=0; n<batchIndexs[k].batchSize; n++){
294 for(i=0; i<numHiddenUnits; i++){
295 h2_p[n][i] = grt_sigmoid( h2_p[n][i] + hlb_p[i] );
305 for(j=0; j<numVisibleUnits; j++){
307 for(i=0; i<batchIndexs[k].batchSize; i++){
308 vDiffSum[j] += vDiff[i][j];
314 for(j=0; j<numHiddenUnits; j++){
316 for(i=0; i<batchIndexs[k].batchSize; i++){
317 hDiffSum[j] += hDiff[i][j];
325 for(i=0; i<numHiddenUnits; i++){
326 for(j=0; j<numVisibleUnits; j++){
327 vW_p[i][j] = ((momentum * vW_p[i][j]) + (alpha * cDiff[i][j])) / batchIndexs[k].batchSize;
330 for(i=0; i<numVisibleUnits; i++){
331 visibleLayerBiasVelocity[i] = ((momentum * visibleLayerBiasVelocity[i]) + (alpha * vDiffSum[i])) / batchIndexs[k].batchSize;
333 for(i=0; i<numHiddenUnits; i++){
334 hiddenLayerBiasVelocity[i] = ((momentum * hiddenLayerBiasVelocity[i]) + (alpha * hDiffSum[i])) / batchIndexs[k].batchSize;
338 weightsMatrix.
add( vW );
341 for(i=0; i<numVisibleUnits; i++){
342 visibleLayerBias[i] += visibleLayerBiasVelocity[i];
346 for(i=0; i<numHiddenUnits; i++){
347 hiddenLayerBias[i] += hiddenLayerBiasVelocity[i];
352 for(i=0; i<batchIndexs[k].batchSize; i++){
353 for(j=0; j<numVisibleUnits; j++){
354 err += SQR( v1[i][j] - v2[i][j] );
358 error += err / batchIndexs[k].batchSize;
361 delta = lastError - error;
364 trainingLog <<
"Epoch: " << epoch+1 <<
"/" << maxNumEpochs;
365 trainingLog <<
" Epoch time: " << (timer.
getMilliSeconds()-startTime)/1000.0 <<
" seconds";
366 trainingLog <<
" Learning rate: " << alpha;
367 trainingLog <<
" Momentum: " << momentum;
368 trainingLog <<
" Average reconstruction error: " << error;
369 trainingLog <<
" Delta: " << delta << std::endl;
372 alpha *= learningRateUpdate;
374 trainingResult.setClassificationResult(epoch, error,
this);
375 trainingResults.push_back(trainingResult);
376 trainingResultsObserverManager.notifyObservers( trainingResult );
379 if( fabs(delta) < minChange ){
380 if( ++noChangeCounter >= minNumEpochs ){
381 trainingLog <<
"Stopping training. MinChange limit reached!" << std::endl;
384 }
else noChangeCounter = 0;
387 trainingLog <<
"Training complete after " << epoch <<
" epochs. Total training time: " << timer.
getMilliSeconds()/1000.0 <<
" seconds" << std::endl;
407 weightsMatrix.
clear();
408 weightsMatrix.
clear();
409 visibleLayerBias.clear();
410 hiddenLayerBias.clear();
420 randomizeWeightsForTraining =
true;
429 errorLog <<
"saveModelToFile(fstream &file) - The file is not open!" << std::endl;
434 file<<
"GRT_BERNOULLI_RBM_MODEL_FILE_V1.1\n";
437 errorLog <<
"saveModelToFile(fstream &file) - Failed to save base settings to file!" << std::endl;
441 file <<
"NumVisibleUnits: " << numVisibleUnits << std::endl;
442 file <<
"NumHiddenUnits: " << numHiddenUnits << std::endl;
443 file <<
"BatchSize: " << batchSize << std::endl;
444 file <<
"BatchStepSize: " << batchStepSize << std::endl;
445 file <<
"LearningRate: " << learningRate << std::endl;
446 file <<
"LearningRateUpdate: " << learningRateUpdate << std::endl;
447 file <<
"Momentum: " << momentum << std::endl;
448 file <<
"RandomizeWeightsForTraining: " << randomizeWeightsForTraining << std::endl;
450 file <<
"Ranges: \n";
451 for(UINT n=0; n<ranges.size(); n++){
452 file << ranges[n].minValue <<
"\t" << ranges[n].maxValue << std::endl;
457 file <<
"WeightsMatrix: " << std::endl;
458 for(UINT i=0; i<weightsMatrix.
getNumRows(); i++){
459 for(UINT j=0; j<weightsMatrix.
getNumCols(); j++){
460 file << weightsMatrix[i][j];
461 if( j < weightsMatrix.getNumCols()-1 ) file <<
" ";
466 file <<
"VisibleLayerBias: ";
467 for(
unsigned int i=0; i<visibleLayerBias.size(); i++){
468 file << visibleLayerBias[i];
469 if( i < visibleLayerBias.size()-1 ) file <<
" ";
473 file <<
"HiddenLayerBias: ";
474 for(
unsigned int i=0; i<hiddenLayerBias.size(); i++){
475 file << hiddenLayerBias[i];
476 if( i < hiddenLayerBias.size()-1 ) file <<
" ";
488 errorLog <<
"loadModelFromFile(fstream &file) - The file is not open!" << std::endl;
497 if( word ==
"GRT_BERNOULLI_RBM_MODEL_FILE_V1.0" ){
501 if( word !=
"GRT_BERNOULLI_RBM_MODEL_FILE_V1.1" ){
502 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read file header!" << std::endl;
507 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load base settings to file!" << std::endl;
513 if( word !=
"NumVisibleUnits:" ){
514 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumVisibleUnits header!" << std::endl;
517 file >> numVisibleUnits;
521 if( word !=
"NumHiddenUnits:" ){
522 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumHiddenUnits header!" << std::endl;
525 file >> numHiddenUnits;
529 if( word !=
"BatchSize:" ){
530 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read BatchSize header!" << std::endl;
537 if( word !=
"BatchStepSize:" ){
538 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read BatchStepSize header!" << std::endl;
541 file >> batchStepSize;
545 if( word !=
"LearningRate:" ){
546 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read LearningRate header!" << std::endl;
549 file >> learningRate;
553 if( word !=
"LearningRateUpdate:" ){
554 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read LearningRateUpdate header!" << std::endl;
557 file >> learningRateUpdate;
561 if( word !=
"Momentum:" ){
562 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read Momentum header!" << std::endl;
569 if( word !=
"RandomizeWeightsForTraining:" ){
570 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read RandomizeWeightsForTraining header!" << std::endl;
573 file >> randomizeWeightsForTraining;
577 if( word !=
"Ranges:" ){
578 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read Ranges header!" << std::endl;
581 ranges.
resize(numInputDimensions);
582 for(UINT n=0; n<ranges.size(); n++){
583 file >> ranges[n].minValue;
584 file >> ranges[n].maxValue;
592 if( word !=
"WeightsMatrix:" ){
593 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read WeightsMatrix header!" << std::endl;
596 weightsMatrix.
resize(numHiddenUnits, numVisibleUnits);
598 for(UINT i=0; i<weightsMatrix.
getNumRows(); i++){
599 for(UINT j=0; j<weightsMatrix.
getNumCols(); j++){
600 file >> weightsMatrix[i][j];
606 if( word !=
"VisibleLayerBias:" ){
607 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read VisibleLayerBias header!" << std::endl;
610 visibleLayerBias.
resize(numVisibleUnits);
612 for(
unsigned int i=0; i<visibleLayerBias.size(); i++){
613 file >> visibleLayerBias[i];
618 if( word !=
"HiddenLayerBias:" ){
619 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read HiddenLayerBias header!" << std::endl;
622 hiddenLayerBias.
resize(numHiddenUnits);
624 for(
unsigned int i=0; i<hiddenLayerBias.size(); i++){
625 file >> hiddenLayerBias[i];
638 std::cout <<
"WeightsMatrix: \n";
639 for(UINT i=0; i<numVisibleUnits; i++) {
640 for(UINT j=0; j<numHiddenUnits; j++) {
641 std::cout << weightsMatrix[j][i] <<
"\t";
643 std::cout << std::endl;
645 std::cout << std::endl;
647 std::cout <<
"visible layer bias: ";
648 for(UINT j=0; j<numVisibleUnits; j++) {
649 std::cout << visibleLayerBias[j] <<
"\t";
651 std::cout << std::endl;
653 std::cout <<
"hidden layer bias: ";
654 for(UINT j=0; j<numHiddenUnits; j++) {
655 std::cout << hiddenLayerBias[j] <<
"\t";
657 std::cout << std::endl;
662 bool BernoulliRBM::getRandomizeWeightsForTraining()
const{
663 return randomizeWeightsForTraining;
666 UINT BernoulliRBM::getNumVisibleUnits()
const{
667 return numVisibleUnits;
670 UINT BernoulliRBM::getNumHiddenUnits()
const{
671 return numHiddenUnits;
674 const MatrixFloat& BernoulliRBM::getWeights()
const{
675 return weightsMatrix;
682 bool BernoulliRBM::setNumHiddenUnits(
const UINT numHiddenUnits){
683 this->numHiddenUnits = numHiddenUnits;
688 bool BernoulliRBM::setMomentum(
const Float momentum){
689 this->momentum = momentum;
693 bool BernoulliRBM::setLearningRateUpdate(
const Float learningRateUpdate){
694 this->learningRateUpdate = learningRateUpdate;
698 bool BernoulliRBM::setRandomizeWeightsForTraining(
const bool randomizeWeightsForTraining){
699 this->randomizeWeightsForTraining = randomizeWeightsForTraining;
703 bool BernoulliRBM::setBatchSize(
const UINT batchSize){
704 this->batchSize = batchSize;
708 bool BernoulliRBM::setBatchStepSize(
const UINT batchStepSize){
709 this->batchStepSize = batchStepSize;
716 UINT numGibbsSteps = 0;
719 errorLog <<
"loadModelFromFile(fstream &file) - Failed to load base settings to file!" << std::endl;
725 if( word !=
"NumVisibleUnits:" ){
726 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumVisibleUnits header!" << std::endl;
729 file >> numVisibleUnits;
733 if( word !=
"NumHiddenUnits:" ){
734 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumHiddenUnits header!" << std::endl;
737 file >> numHiddenUnits;
741 if( word !=
"NumTrainingEpochs:" ){
742 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumTrainingEpochs header!" << std::endl;
745 file >> maxNumEpochs;
749 if( word !=
"NumGibbsSteps:" ){
750 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read NumGibbsSteps header!" << std::endl;
753 file >> numGibbsSteps;
757 if( word !=
"LearningRate:" ){
758 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read LearningRate header!" << std::endl;
761 file >> learningRate;
765 if( word !=
"LearningRateUpdate:" ){
766 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read LearningRateUpdate header!" << std::endl;
769 file >> learningRateUpdate;
773 if( word !=
"Momentum:" ){
774 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read Momentum header!" << std::endl;
781 if( word !=
"RandomizeWeightsForTraining:" ){
782 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read RandomizeWeightsForTraining header!" << std::endl;
785 file >> randomizeWeightsForTraining;
789 if( word !=
"Ranges:" ){
790 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read Ranges header!" << std::endl;
793 ranges.
resize(numInputDimensions);
794 for(UINT n=0; n<ranges.size(); n++){
795 file >> ranges[n].minValue;
796 file >> ranges[n].maxValue;
804 if( word !=
"WeightsMatrix:" ){
805 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read WeightsMatrix header!" << std::endl;
808 weightsMatrix.
resize(numHiddenUnits, numVisibleUnits);
810 for(UINT i=0; i<weightsMatrix.
getNumRows(); i++){
811 for(UINT j=0; j<weightsMatrix.
getNumCols(); j++){
812 file >> weightsMatrix[i][j];
818 if( word !=
"VisibleLayerBias:" ){
819 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read VisibleLayerBias header!" << std::endl;
822 visibleLayerBias.
resize(numVisibleUnits);
824 for(
unsigned int i=0; i<visibleLayerBias.
getSize(); i++){
825 file >> visibleLayerBias[i];
830 if( word !=
"HiddenLayerBias:" ){
831 errorLog <<
"loadModelFromFile(fstream &file) - Failed to read HiddenLayerBias header!" << std::endl;
834 hiddenLayerBias.
resize(numHiddenUnits);
836 for(
unsigned int i=0; i<hiddenLayerBias.
getSize(); i++){
837 file >> hiddenLayerBias[i];
bool saveBaseSettingsToFile(std::fstream &file) const
virtual bool loadModelFromFile(std::fstream &file)
bool predict_(VectorFloat &inputData)
virtual bool resize(const unsigned int size)
This class implements a Bernoulli Restricted Boltzmann machine.
signed long getMilliSeconds()
unsigned int getSize() const
bool setAllValues(const T &value)
bool add(const MatrixFloat &b)
bool subtract(const MatrixFloat &b)
unsigned int getNumRows() const
bool loadLegacyModelFromFile(std::fstream &file)
unsigned int getNumCols() const
bool loadBaseSettingsFromFile(std::fstream &file)
T ** getDataPointer() const
virtual bool print() const
Vector< MinMax > getRanges() const
Float getRandomNumberUniform(Float minRange=0.0, Float maxRange=1.0)
virtual bool saveModelToFile(std::fstream &file) const
virtual bool train_(MatrixFloat &data)
virtual bool resize(const unsigned int r, const unsigned int c)
MatrixFloat multiple(const Float value) const