/* * Rbm.hpp * * Created on: 21.09.2014 * Author: jens */ #ifndef RBM_HPP_ #define RBM_HPP_ #include "VisibleLayer.hpp" #include "HiddenLayer.hpp" #include "Weights.hpp" #include void mylog(const char* format, ...); #define printf mylog class Rbm { public: Rbm(Weights &weights) : m_w(weights) , m_tv(weights.getNumVisible()) , m_th(weights.getNumHidden()) { Noise_Init(&m_noise, 0x32727155); } ~Rbm() { Noise_Free(&m_noise); } 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_w.getNumHidden(); i++) { dw = 0; 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_w.getNumHidden(); i++) { dw = 0; 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_w.getNumVisible(); i++) { dw = v.getStates()[i] - vr.getStates()[i]; m_w.getBiasVisible()[i] += mu*dw; } for (i=0; i < m_w.getNumHidden(); i++) { dw = h.getStates()[i] - hr.getStates()[i]; m_w.getBiasHidden()[i] += mu*dw; } #endif } void train(VisibleLayerArray &vts, uint32_t numEpochs, double mu) { uint32_t epoch; uint32_t trainingPatternIndex; 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)((vts.getSize())*Noise_Uniform(&m_noise, 0.5)); if (trainingPatternIndex == vts.getSize()) continue; // Assign training data VisibleLayer &vt = vts.getAt(trainingPatternIndex); // Create hidden layer base on training data h.probsUpdate(vt, m_w); // h.statesAssignfromProbs(); h.statesUpdateStochastic(); // Create visible reconstruction (a fantasy...) vr = vt; vr.probsUpdate(h, m_w); // vr.statesAssignfromProbs(); vr.statesUpdateStochastic(); // Create hidden reconstruction hr.probsUpdate(vr, m_w); // hr.statesAssignfromProbs(); hr.statesUpdateStochastic(); // Update weights weightsUpdate(vt, vr, h, hr, mu); if (!monitorCount) { monitorCount = monitorInterval; // printf("Epoch #%d\n", epoch); // prob(); } monitorCount--; } } double getEnergy(VisibleLayer &v, HiddenLayer &h) { uint32_t i, j; double energy; energy = -v.getEnergy(m_w) - h.getEnergy(m_w); for (i=0; i < h.getNumUnits(); i++) { for (j=0; j < v.getNumUnits(); j++) { energy -= v.getStates()[j] * h.getStates()[i] * m_w.getWeights()[i][j]; } } return energy; } void prob(VisibleLayerArray &vts) { uint32_t i, j; double z; double p; HiddenLayer *h = new HiddenLayer[vts.getSize()]; // Create hidden layer activations based on training data for (j=0; j < vts.getSize(); j++) { 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_w.getNumHidden(); i++) { for (j=0; j < vts.getSize(); j++) { p = h[j].getProbs()[i]; printf("%3.6f ", p); } printf("\n"); } printf("\n"); printf("si(t) = (si^, v>)\n"); for (i=0; i < m_w.getNumHidden(); i++) { for (j=0; j < vts.getSize(); j++) { p = h[j].getStates()[i]; printf("%3.6f ", p); } printf("\n"); } printf("\n"); printf("p(v) = (t^, v>)\n"); for (i=0; i < vts.getSize(); i++) { z = 0; for (j=0; j < vts.getSize(); j++) { z += exp(-getEnergy(vts.getAt(j), h[i])); } for (j=0; j < vts.getSize(); j++) { p = exp(-getEnergy(vts.getAt(j), h[i]))/z; printf("%3.6f ", p); } printf("\n"); } printf("\n"); // Reconstruct for (i=0; i < vts.getSize(); i++) { vts.getAt(i).probsUpdate(h[i], m_w); } printf("A fantasy... (v^, t>)\n"); for (i=0; i < m_w.getNumVisible(); i++) { for (j=0; j < vts.getSize(); j++) { p = vts.getAt(j).getProbs()[i]; printf("%3.6f ", p); } printf("\n"); } delete [] h; } const double* toHidden(const double *pVisible) { double p; uint32_t i; VisibleLayer tv(m_w.getNumVisible(), pVisible); 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_w.getNumHidden(); i++) { p = m_th.getProbs()[i]; printf("%3.6f\n", p); } printf("\n"); #endif return m_th.getStates(); } const double* toVisible(const double *pHidden) { double p; uint32_t i; HiddenLayer th(m_w.getNumHidden(), pHidden); 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_w.getNumVisible(); i++) { p = m_tv.getProbs()[i]; printf("%3.6f\n", p); } printf("\n"); #endif return m_tv.getStates(); } private: Weights &m_w; VisibleLayer m_tv; HiddenLayer m_th; noise_gen_t m_noise; }; #endif /* RBM_HPP_ */