GPUMLib  0.2.2
GPU Machine Learning Library
RBM.h
1 /*
2  Noel Lopes is an Assistant Professor at the Polytechnic Institute of Guarda, Portugal
3  Copyright (C) 2009, 2010, 2011, 2012 Noel de Jesus Mendonša Lopes
4 
5  This file is part of GPUMLib.
6 
7  GPUMLib is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #ifndef GPUMLib_RBM_h
22 #define GPUMLib_RBM_h
23 
24 #include "RBMconfig.h"
25 
26 #include "../memory/DeviceAccessibleVariable.h"
27 #include "../common/CudaStreams.h"
28 #include "../common/Utilities.h"
29 #include "../memory/CudaArray.h"
30 #include "../memory/CudaMatrix.h"
31 #include "../reduction/reduction.h"
32 
33 #include <iostream>
34 #include <ostream>
35 
36 using namespace std;
37 
38 namespace GPUMLib {
39 
42 
44 class RBM {
45  friend class DBN;
46 
47  private:
48  class ConnectionsInfo {
49  public:
50  DeviceArray<cudafloat> a; // bias of the visible layer
51  DeviceArray<cudafloat> b; // bias of the hidden layer
52  DeviceMatrix<cudafloat> w; // weights
53 
54  bool Resize(int I, int J) {
55  if (w.ResizeWithoutPreservingData(J, I) != J * I) return false;
56  if (a.ResizeWithoutPreservingData(I) != I) return false;
57  if (b.ResizeWithoutPreservingData(J) != J) return false;
58 
59  return true;
60  }
61 
62  void Dispose() {
63  a.Dispose();
64  b.Dispose();
65  w.Dispose();
66  }
67  };
68 
69  int I; // number of visible units
70  int J; // number of hidden units
71  int samples;
72  int miniBatchSize;
73 
74  DeviceMatrix<cudafloat> v; // visible units inputs
75 
76  CudaArray<cudafloat> a; // bias of the visible layer
77  CudaArray<cudafloat> b; // bias of the hidden layer
78  CudaMatrix<cudafloat> w; // weights
79 
80  ConnectionsInfo lastDelta;
81  ConnectionsInfo learningRate;
82  ConnectionsInfo lastDeltaWithoutLearningMomentum;
83 
84  cudafloat stdWeights;
85  cudafloat initialLearningRate;
86  cudafloat momentum;
87 
88  bool useBinaryValuesVisibleReconstruction;
89 
93 
94  DeviceArray<float> randomValues;
95 
96  int epoch;
97 
98  dim3 dimIJ;
99  dim3 dimJI;
100 
101  int inputsBlockSize;
102  int hiddenUnitsBlockSize;
103  int samplesBlockSize;
104 
105  DeviceArray<cudafloat> errors;
106 
107  RBM * previousLayer;
108 
111  CudaStream streamMSE;
112 
113  void _Init(int I, int J, int samples, cudafloat stdWeights, cudafloat initialLearningRate, cudafloat momentum, bool useBinaryValuesVisibleReconstruction, int proportionRandomValuesGenerated, RBM * previousLayer) {
114  this->I = I;
115  this->J = J;
116  this->samples = samples;
117 
118  this->stdWeights = stdWeights;
119  this->initialLearningRate = initialLearningRate;
120  this->momentum = momentum;
121 
122  this->useBinaryValuesVisibleReconstruction = useBinaryValuesVisibleReconstruction;
123 
124  dimIJ.x = I;
125  dimIJ.y = J;
126 
127  dimJI.x = J;
128  dimJI.y = I;
129 
130  inputsBlockSize = NumberThreadsPerBlockThatBestFit(I);
131  hiddenUnitsBlockSize = NumberThreadsPerBlockThatBestFit(J);
132  samplesBlockSize = NumberThreadsPerBlockThatBestFit(samples);
133 
134  this->previousLayer = previousLayer;
135 
136  d_mse.ResizeWithoutPreservingData(1);
137 
138  *(mse.Pointer()) = CUDA_VALUE(1.0);
139  }
140 
141  // Used by DBNs
142  RBM(RBM * previousLayer, int hiddenUnits, cudafloat initialLearningRate, cudafloat momentum, bool useBinaryValuesVisibleReconstruction, cudafloat stdWeights, int proportionRandomValuesGenerated = 1) : mse(CUDA_VALUE(1.0)) {
143  _Init(previousLayer->J, hiddenUnits, previousLayer->samples, stdWeights, initialLearningRate, momentum, useBinaryValuesVisibleReconstruction, proportionRandomValuesGenerated, previousLayer);
144  }
145 
146  void ComputeStatusUnits(cudafloat * v, cudafloat * h, cudafloat * v_reconstructed, int samples, float * rnd);
147 
148  public:
152  bool Init(int miniBatchSize, int cd) {
153  this->miniBatchSize = miniBatchSize;
154  int numberWeights = I * J;
155 
156  if (previousLayer != nullptr) {
157  previousLayer->ComputeStatusUnits(previousLayer->v.Pointer(), previousLayer->h_data.Pointer(), nullptr, samples, nullptr);
158  v.TransferOwnerShipFrom(previousLayer->h_data);
159  previousLayer->DisposeDeviceInformation();
160  }
161 
162  if (w.ResizeWithoutPreservingData(J, I) != numberWeights) return false;
163  if (a.ResizeWithoutPreservingData(I) != I) return false;
164  if (b.ResizeWithoutPreservingData(J) != J) return false;
165 
166  if (!lastDelta.Resize(I, J)) return false;
167 
168  if (!learningRate.Resize(I, J)) return false;
169  if (!lastDeltaWithoutLearningMomentum.Resize(I, J)) return false;
170 
171  if (h_data.ResizeWithoutPreservingData(samples, J) != samples * J) return false;
172  if (h_recon.ResizeWithoutPreservingData(samples, J) != h_data.Elements()) return false;
173  if (v_recon.ResizeWithoutPreservingData(samples, I) != samples * I) return false;
174 
175  int randomValuesNeededPerEpoch = J;
176  if (useBinaryValuesVisibleReconstruction) randomValuesNeededPerEpoch += I;
177  randomValuesNeededPerEpoch *= samples;
178 
179  int numberRandomValues = randomValuesNeededPerEpoch * cd;
180 
181  if (randomValues.ResizeWithoutPreservingData(numberRandomValues) != numberRandomValues) return false;
182 
183  RandomizeWeights();
184 
185  if (errors.ResizeWithoutPreservingData(I) != I) return false;
186 
187  return true;
188  }
189 
195  v.Dispose();
196 
197  a.DisposeDevice();
198  b.DisposeDevice();
199  w.DisposeDevice();
200 
201  lastDelta.Dispose();
202 
203  learningRate.Dispose();
204  lastDeltaWithoutLearningMomentum.Dispose();
205 
206  h_data.Dispose();
207  h_recon.Dispose();
208  v_recon.Dispose();
209 
210  randomValues.Dispose();
211  errors.Dispose();
212  }
213 
224  RBM(int visibleUnits, int hiddenUnits, HostMatrix<cudafloat> & inputs, cudafloat initialLearningRate, cudafloat momentum = DEFAULT_MOMENTUM, bool useBinaryValuesVisibleReconstruction = false, cudafloat stdWeights = STD_WEIGHTS, int proportionRandomValuesGenerated = 1 /*, curandGenerator_t randomGenerator = nullptr*/) : mse(CUDA_VALUE(1.0)) {
225  assert(visibleUnits == inputs.Columns() && inputs.IsRowMajor());
226  assert(proportionRandomValuesGenerated > 0);
227 
228  v = inputs;
229 
230  _Init(visibleUnits, hiddenUnits, inputs.Rows(), stdWeights, initialLearningRate, momentum, useBinaryValuesVisibleReconstruction, proportionRandomValuesGenerated, nullptr);
231  }
232 
234  void RandomizeWeights();
235 
238  void RandomizeWeights(cudafloat stdWeights) {
239  this->stdWeights = stdWeights;
240  RandomizeWeights();
241  }
242 
246  void RandomizeWeights(cudafloat stdWeights, cudafloat initialLearningRate) {
247  this->initialLearningRate = initialLearningRate;
248  RandomizeWeights(stdWeights);
249  }
250 
253  void ContrastiveDivergence(int n);
254 
259  if (mse.Value() >= CUDA_VALUE(1.0)) return GetMSE();
260 
261  if (cudaStreamQuery(streamMSE) == cudaSuccess) {
262  Reduction::Sum(errors, d_mse, 1.0f, streamMSE);
263  mse.UpdateValueAsync(d_mse.Pointer(), streamMSE);
264  }
265 
266  return mse.Value() / ((cudafloat) I * samples);
267  }
268 
275  if (errors.Length() > 0) {
276  Reduction::Sum(errors, d_mse);
277  mse.UpdateValue(d_mse.Pointer());
278  }
279 
280  return mse.Value() / ((cudafloat) I * samples);
281  }
282 
285  int Epoch() const {
286  return epoch;
287  }
288 
292  if (w.DevicePointer() != nullptr) w.UpdateHost();
293  return HostMatrix<cudafloat>(w.GetHostMatrix());
294  }
295 
299  if (a.DevicePointer() != nullptr) a.UpdateHost();
300  return HostArray<cudafloat>(a.GetHostArray());
301  }
302 
306  if (b.DevicePointer() != nullptr) b.UpdateHost();
307  return HostArray<cudafloat>(b.GetHostArray());
308  }
309 
312  int GetNumberInputs() const {
313  return I;
314  }
315 
318  int GetNumberOutputs() const {
319  return J;
320  }
321 };
322 
324 
325 }
326 
327 #endif
int Epoch() const
Definition: RBM.h:285
void Dispose()
Disposes the matrix.
Definition: DeviceMatrix.h:63
void DisposeDeviceInformation()
Definition: RBM.h:194
int NumberThreadsPerBlockThatBestFit(int threads, int maxThreadsPerBlock=MAX_THREADS_PER_BLOCK)
Definition: Utilities.h:37
cudafloat GetMSE()
Definition: RBM.h:274
HostMatrix< cudafloat > GetWeights()
Definition: RBM.h:291
cudafloat GetMSEestimate()
Definition: RBM.h:258
int GetNumberOutputs() const
Definition: RBM.h:318
Represents a CUDA stream.
Definition: CudaStreams.h:32
HostArray< cudafloat > GetVisibleBias()
Definition: RBM.h:298
int GetNumberInputs() const
Definition: RBM.h:312
void RandomizeWeights(cudafloat stdWeights)
Definition: RBM.h:238
Type * Pointer() const
Definition: BaseMatrix.h:88
void RandomizeWeights(cudafloat stdWeights, cudafloat initialLearningRate)
Definition: RBM.h:246
int Columns() const
Definition: BaseMatrix.h:80
RBM(int visibleUnits, int hiddenUnits, HostMatrix< cudafloat > &inputs, cudafloat initialLearningRate, cudafloat momentum=DEFAULT_MOMENTUM, bool useBinaryValuesVisibleReconstruction=false, cudafloat stdWeights=STD_WEIGHTS, int proportionRandomValuesGenerated=1)
Definition: RBM.h:224
Represents a Deep Belief Network (Device - GPU).
Definition: DBN.h:33
bool IsRowMajor() const
Definition: BaseMatrix.h:100
int Rows() const
Definition: BaseMatrix.h:74
#define CUDA_VALUE(X)
Represents a Restricted Boltzman Machine (GPU).
Definition: RBM.h:44
HostArray< cudafloat > GetHiddenBias()
Definition: RBM.h:305
float cudafloat
bool Init(int miniBatchSize, int cd)
Definition: RBM.h:152