further development
git-svn-id: http://moon:8086/svn/software/trunk/projects/RBM@17 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
+67
-209
@@ -8,161 +8,63 @@
|
||||
#ifndef RBM_HPP_
|
||||
#define RBM_HPP_
|
||||
|
||||
#include "Layer.hpp"
|
||||
#include "VisibleLayer.hpp"
|
||||
#include "HiddenLayer.hpp"
|
||||
#include "Weights.hpp"
|
||||
#include <cmath>
|
||||
|
||||
class VisibleLayer : public Layer
|
||||
{
|
||||
public:
|
||||
VisibleLayer(uint32_t numUnits = 0)
|
||||
: Layer(numUnits)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~VisibleLayer()
|
||||
{
|
||||
}
|
||||
|
||||
double getEnergy(const Weights &weights)
|
||||
{
|
||||
uint32_t i;
|
||||
double energy = 0;
|
||||
|
||||
for (i=0; i < getNumUnits(); i++)
|
||||
{
|
||||
energy -= weights.getBiasVisible()[i] * getStates()[i];
|
||||
}
|
||||
return energy;
|
||||
}
|
||||
|
||||
private:
|
||||
double accum(const Layer &layer, const Weights &weights, uint32_t index) const
|
||||
{
|
||||
uint32_t i;
|
||||
double sum = weights.getBiasVisible()[index];
|
||||
const double *pStates = layer.getStates();
|
||||
|
||||
for (i=0; i < layer.getNumUnits(); i++)
|
||||
{
|
||||
sum += pStates[i] * weights.getWeights()[i][index];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
class HiddenLayer : public Layer
|
||||
{
|
||||
public:
|
||||
HiddenLayer(uint32_t numUnits = 0)
|
||||
: Layer(numUnits)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~HiddenLayer()
|
||||
{
|
||||
}
|
||||
|
||||
double getEnergy(const Weights &weights)
|
||||
{
|
||||
uint32_t i;
|
||||
double energy = 0;
|
||||
|
||||
for (i=0; i < getNumUnits(); i++)
|
||||
{
|
||||
energy -= weights.getBiasHidden()[i] * getStates()[i];
|
||||
}
|
||||
return energy;
|
||||
}
|
||||
|
||||
private:
|
||||
double accum(const Layer &layer, const Weights &weights, uint32_t index) const
|
||||
{
|
||||
uint32_t i;
|
||||
double sum = weights.getBiasVisible()[index];
|
||||
const double *pStates = layer.getStates();
|
||||
|
||||
for (i=0; i < layer.getNumUnits(); i++)
|
||||
{
|
||||
sum += pStates[i] * weights.getWeights()[index][i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
void mylog(const char* format, ...);
|
||||
#define printf mylog
|
||||
|
||||
class Rbm
|
||||
{
|
||||
public:
|
||||
Rbm(uint32_t numVisible, uint32_t numHidden)
|
||||
: m_w(numVisible, numHidden)
|
||||
, tv(numVisible)
|
||||
, th(numHidden)
|
||||
, m_numVisible(numVisible)
|
||||
, m_numHidden(numHidden)
|
||||
, m_numTrainingPatterns(0)
|
||||
, m_pVisibleTraining(nullptr)
|
||||
Rbm(Weights &weights)
|
||||
: m_w(weights)
|
||||
, m_tv(weights.getNumVisible())
|
||||
, m_th(weights.getNumHidden())
|
||||
{
|
||||
Noise_Init(&m_noise, 0x32727155);
|
||||
}
|
||||
|
||||
~Rbm()
|
||||
{
|
||||
freeTrainingPatterns();
|
||||
Noise_Free(&m_noise);
|
||||
}
|
||||
|
||||
void setTrainingInput(uint32_t index, const double *pValues)
|
||||
{
|
||||
if (!m_pVisibleTraining)
|
||||
return;
|
||||
|
||||
if (index >= m_numTrainingPatterns)
|
||||
return;
|
||||
|
||||
m_pVisibleTraining[index].setInput(pValues);
|
||||
m_pVisibleTraining[index].statesAssignfromInput();
|
||||
}
|
||||
|
||||
void setNumTrainingPatterns(uint32_t numTrainingPatterns)
|
||||
{
|
||||
m_numTrainingPatterns = numTrainingPatterns;
|
||||
allocTrainingPatterns();
|
||||
}
|
||||
|
||||
void weightsUpdate(VisibleLayer &v, VisibleLayer &vr, HiddenLayer &h, HiddenLayer &hr, double mu)
|
||||
{
|
||||
uint32_t i, j;
|
||||
double dw;
|
||||
|
||||
// Update weights
|
||||
for (i=0; i < m_numHidden; i++)
|
||||
for (i=0; i < m_w.getNumHidden(); i++)
|
||||
{
|
||||
dw = 0;
|
||||
for (j=0; j < m_numVisible; j++)
|
||||
for (j=0; j < m_w.getNumVisible(); j++)
|
||||
{
|
||||
dw = v.getStates()[j] * h.getStates()[i];
|
||||
m_w.getWeights()[i][j] += mu*dw;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i < m_numHidden; i++)
|
||||
for (i=0; i < m_w.getNumHidden(); i++)
|
||||
{
|
||||
dw = 0;
|
||||
for (j=0; j < m_numVisible; j++)
|
||||
for (j=0; j < m_w.getNumVisible(); j++)
|
||||
{
|
||||
dw = vr.getStates()[j] * hr.getStates()[i];
|
||||
m_w.getWeights()[i][j] -= mu*dw;
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
for (i=0; i < m_numVisible; i++)
|
||||
for (i=0; i < m_w.getNumVisible(); i++)
|
||||
{
|
||||
dw = v.getStates()[i] - vr.getStates()[i];
|
||||
m_w.getBiasVisible()[i] += mu*dw;
|
||||
}
|
||||
|
||||
for (i=0; i < m_numHidden; i++)
|
||||
for (i=0; i < m_w.getNumHidden(); i++)
|
||||
{
|
||||
dw = h.getStates()[i] - hr.getStates()[i];
|
||||
m_w.getBiasHidden()[i] += mu*dw;
|
||||
@@ -170,37 +72,36 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
void train(uint32_t numEpochs, double mu)
|
||||
void train(VisibleLayerArray &vts, uint32_t numEpochs, double mu)
|
||||
{
|
||||
uint32_t epoch;
|
||||
uint32_t trainingPatternIndex;
|
||||
VisibleLayer *pV;
|
||||
VisibleLayer vr(m_numVisible);
|
||||
HiddenLayer h(m_numHidden);
|
||||
HiddenLayer hr(m_numHidden);
|
||||
VisibleLayer vr(m_w.getNumVisible());
|
||||
HiddenLayer h(m_w.getNumHidden());
|
||||
HiddenLayer hr(m_w.getNumHidden());
|
||||
const uint32_t monitorInterval = 100; // epochs
|
||||
uint32_t monitorCount = monitorInterval; // epochs
|
||||
|
||||
for (epoch=0; epoch < numEpochs; epoch++)
|
||||
{
|
||||
trainingPatternIndex = (uint32_t)((m_numTrainingPatterns)*Noise_Uniform(&m_noise, 0.5));
|
||||
trainingPatternIndex = (uint32_t)((vts.getSize())*Noise_Uniform(&m_noise, 0.5));
|
||||
|
||||
if (trainingPatternIndex == m_numTrainingPatterns)
|
||||
if (trainingPatternIndex == vts.getSize())
|
||||
continue;
|
||||
|
||||
// Assign training data
|
||||
pV = &m_pVisibleTraining[trainingPatternIndex];
|
||||
VisibleLayer &vt = vts.getAt(trainingPatternIndex);
|
||||
|
||||
// Create hidden layer base on training data
|
||||
h.probsUpdate(*pV, m_w);
|
||||
h.probsUpdate(vt, m_w);
|
||||
// h.statesAssignfromProbs();
|
||||
h.statesUpdateStochastic();
|
||||
|
||||
// Create visible reconstruction (a fantasy...)
|
||||
vr = *pV;
|
||||
vr = vt;
|
||||
vr.probsUpdate(h, m_w);
|
||||
vr.statesAssignfromProbs();
|
||||
// vr.statesUpdateStochastic();
|
||||
// vr.statesAssignfromProbs();
|
||||
vr.statesUpdateStochastic();
|
||||
|
||||
// Create hidden reconstruction
|
||||
hr.probsUpdate(vr, m_w);
|
||||
@@ -208,7 +109,7 @@ public:
|
||||
hr.statesUpdateStochastic();
|
||||
|
||||
// Update weights
|
||||
weightsUpdate(*pV, vr, h, hr, mu);
|
||||
weightsUpdate(vt, vr, h, hr, mu);
|
||||
|
||||
if (!monitorCount)
|
||||
{
|
||||
@@ -237,27 +138,27 @@ public:
|
||||
return energy;
|
||||
}
|
||||
|
||||
void prob()
|
||||
void prob(VisibleLayerArray &vts)
|
||||
{
|
||||
uint32_t i, j;
|
||||
double z;
|
||||
double p;
|
||||
|
||||
HiddenLayer *h = new HiddenLayer[m_numTrainingPatterns];
|
||||
HiddenLayer *h = new HiddenLayer[vts.getSize()];
|
||||
|
||||
// Create hidden layer activations based on training data
|
||||
for (j=0; j < m_numTrainingPatterns; j++)
|
||||
for (j=0; j < vts.getSize(); j++)
|
||||
{
|
||||
h[j].setNumUnits(m_numHidden);
|
||||
h[j].probsUpdate(m_pVisibleTraining[j], m_w);
|
||||
h[j].setNumUnits(m_w.getNumHidden());
|
||||
h[j].probsUpdate(vts.getAt(j), m_w);
|
||||
// h[j].statesAssignfromProbs();
|
||||
h[j].statesUpdateStochastic();
|
||||
}
|
||||
|
||||
printf("pi(t) = (pi^, v>)\n");
|
||||
for (i=0; i < m_numHidden; i++)
|
||||
for (i=0; i < m_w.getNumHidden(); i++)
|
||||
{
|
||||
for (j=0; j < m_numTrainingPatterns; j++)
|
||||
for (j=0; j < vts.getSize(); j++)
|
||||
{
|
||||
p = h[j].getProbs()[i];
|
||||
printf("%3.6f ", p);
|
||||
@@ -267,9 +168,9 @@ public:
|
||||
printf("\n");
|
||||
|
||||
printf("si(t) = (si^, v>)\n");
|
||||
for (i=0; i < m_numHidden; i++)
|
||||
for (i=0; i < m_w.getNumHidden(); i++)
|
||||
{
|
||||
for (j=0; j < m_numTrainingPatterns; j++)
|
||||
for (j=0; j < vts.getSize(); j++)
|
||||
{
|
||||
p = h[j].getStates()[i];
|
||||
printf("%3.6f ", p);
|
||||
@@ -279,16 +180,16 @@ public:
|
||||
printf("\n");
|
||||
|
||||
printf("p(v) = (t^, v>)\n");
|
||||
for (i=0; i < m_numTrainingPatterns; i++)
|
||||
for (i=0; i < vts.getSize(); i++)
|
||||
{
|
||||
z = 0;
|
||||
for (j=0; j < m_numTrainingPatterns; j++)
|
||||
for (j=0; j < vts.getSize(); j++)
|
||||
{
|
||||
z += exp(-getEnergy(m_pVisibleTraining[j], h[i]));
|
||||
z += exp(-getEnergy(vts.getAt(j), h[i]));
|
||||
}
|
||||
for (j=0; j < m_numTrainingPatterns; j++)
|
||||
for (j=0; j < vts.getSize(); j++)
|
||||
{
|
||||
p = exp(-getEnergy(m_pVisibleTraining[j], h[i]))/z;
|
||||
p = exp(-getEnergy(vts.getAt(j), h[i]))/z;
|
||||
printf("%3.6f ", p);
|
||||
}
|
||||
printf("\n");
|
||||
@@ -296,17 +197,17 @@ public:
|
||||
printf("\n");
|
||||
|
||||
// Reconstruct
|
||||
for (i=0; i < m_numTrainingPatterns; i++)
|
||||
for (i=0; i < vts.getSize(); i++)
|
||||
{
|
||||
m_pVisibleTraining[i].probsUpdate(h[i], m_w);
|
||||
vts.getAt(i).probsUpdate(h[i], m_w);
|
||||
}
|
||||
|
||||
printf("A fantasy... (v^, t>)\n");
|
||||
for (i=0; i < m_numVisible; i++)
|
||||
for (i=0; i < m_w.getNumVisible(); i++)
|
||||
{
|
||||
for (j=0; j < m_numTrainingPatterns; j++)
|
||||
for (j=0; j < vts.getSize(); j++)
|
||||
{
|
||||
p = m_pVisibleTraining[j].getProbs()[i];
|
||||
p = vts.getAt(j).getProbs()[i];
|
||||
printf("%3.6f ", p);
|
||||
}
|
||||
printf("\n");
|
||||
@@ -320,19 +221,22 @@ public:
|
||||
double p;
|
||||
uint32_t i;
|
||||
|
||||
tv.setInput(pVisible);
|
||||
tv.statesAssignfromInput();
|
||||
VisibleLayer tv(m_w.getNumVisible(), pVisible);
|
||||
|
||||
th.probsUpdate(tv, m_w);
|
||||
m_th.probsUpdate(tv, m_w);
|
||||
m_th.statesAssignfromProbs();
|
||||
// m_th.statesUpdateStochastic();
|
||||
|
||||
#if 0
|
||||
printf("pi(t) = (pi^, v>)\n");
|
||||
for (i=0; i < m_numHidden; i++)
|
||||
for (i=0; i < m_w.getNumHidden(); i++)
|
||||
{
|
||||
p = th.getProbs()[i];
|
||||
p = m_th.getProbs()[i];
|
||||
printf("%3.6f\n", p);
|
||||
}
|
||||
printf("\n");
|
||||
return th.getProbs();
|
||||
#endif
|
||||
return m_th.getStates();
|
||||
}
|
||||
|
||||
const double* toVisible(const double *pHidden)
|
||||
@@ -340,76 +244,30 @@ public:
|
||||
double p;
|
||||
uint32_t i;
|
||||
|
||||
th.setInput(pHidden);
|
||||
th.statesAssignfromInput();
|
||||
HiddenLayer th(m_w.getNumHidden(), pHidden);
|
||||
|
||||
tv.probsUpdate(th, m_w);
|
||||
m_tv.probsUpdate(th, m_w);
|
||||
m_tv.statesAssignfromProbs();
|
||||
// m_tv.statesUpdateStochastic();
|
||||
|
||||
#if 0
|
||||
printf("pi(t) = (pi^, v>)\n");
|
||||
for (i=0; i < m_numVisible; i++)
|
||||
for (i=0; i < m_w.getNumVisible(); i++)
|
||||
{
|
||||
p = tv.getProbs()[i];
|
||||
p = m_tv.getProbs()[i];
|
||||
printf("%3.6f\n", p);
|
||||
}
|
||||
printf("\n");
|
||||
return tv.getProbs();
|
||||
#endif
|
||||
return m_tv.getStates();
|
||||
}
|
||||
|
||||
void weightsPrint()
|
||||
{
|
||||
m_w.print();
|
||||
}
|
||||
|
||||
void weightsShuffle(double stdDev)
|
||||
{
|
||||
m_w.shuffle(stdDev);
|
||||
}
|
||||
|
||||
double **getWeights()
|
||||
{
|
||||
return m_w.getWeights();
|
||||
}
|
||||
private:
|
||||
|
||||
Weights m_w;
|
||||
VisibleLayer tv;
|
||||
HiddenLayer th;
|
||||
uint32_t m_numVisible;
|
||||
uint32_t m_numHidden;
|
||||
uint32_t m_numTrainingPatterns;
|
||||
VisibleLayer *m_pVisibleTraining;
|
||||
Weights &m_w;
|
||||
VisibleLayer m_tv;
|
||||
HiddenLayer m_th;
|
||||
noise_gen_t m_noise;
|
||||
|
||||
void allocTrainingPatterns()
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (m_pVisibleTraining)
|
||||
{
|
||||
freeTrainingPatterns();
|
||||
allocTrainingPatterns();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pVisibleTraining = new VisibleLayer[m_numTrainingPatterns];
|
||||
for (i=0; i < m_numTrainingPatterns; i++)
|
||||
{
|
||||
m_pVisibleTraining[i].setNumUnits(m_numVisible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void freeTrainingPatterns()
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (m_pVisibleTraining)
|
||||
{
|
||||
delete [] m_pVisibleTraining;
|
||||
m_pVisibleTraining = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user