/* ============================================================================== Layer.hpp Created: 21 Sep 2014 1:55:15pm Author: jens ============================================================================== */ #ifndef LAYER_HPP #define LAYER_HPP #include "noise.h" class Weights { public: Weights(uint32_t numVisible, uint32_t numHidden) : m_ppW(nullptr) , m_pBiasVisible(nullptr) , m_pBiasHidden(nullptr) , m_numVisible(numVisible) , m_numHidden(numHidden) { alloc(); Noise_Init(&m_noise, 0x32727155); shuffle(0); } ~Weights() { Noise_Free(&m_noise); free(); } void shuffle(double stdDev) { uint32_t i, j; double kdev = stdDev*sqrt(12.0); for (j=0; j < m_numVisible; j++) { m_pBiasVisible[j] = kdev*Noise_Uniform(&m_noise, 0.5); } for (i=0; i < m_numHidden; i++) { m_pBiasHidden[i] = kdev*Noise_Uniform(&m_noise, 0.5); } for (i=0; i < m_numHidden; i++) { for (j=0; j < m_numVisible; j++) { m_ppW[i][j] = kdev*Noise_Uniform(&m_noise, 0.5); } } } double **getWeights() const { return m_ppW; } double *getBiasVisible() const { return m_pBiasVisible; } double *getBiasHidden() const { return m_pBiasHidden; } void print() { uint32_t i, j; double w; printf("\n"); printf("w(v,h) = (v^, h>)\n"); for (i=0; i < m_numVisible; i++) { for (j=0; j < m_numHidden; j++) { w = m_ppW[j][i]; printf("%3.6f ", w); } printf("\n"); } printf("\n"); printf("bv = \n"); for (i=0; i < m_numVisible; i++) { w = m_pBiasVisible[i]; printf("%3.6f\n", w); } printf("\n"); printf("bh = \n"); for (i=0; i < m_numHidden; i++) { w = m_pBiasHidden[i]; printf("%3.6f\n", w); } printf("\n"); } private: double **m_ppW; double *m_pBiasVisible; double *m_pBiasHidden; uint32_t m_numVisible; uint32_t m_numHidden; noise_gen_t m_noise; void alloc() { uint32_t i; if (m_ppW) { free(); alloc(); } else { m_ppW = new double*[m_numHidden]; for (i=0; i < m_numHidden; i++) { m_ppW[i] = new double[m_numVisible]; } m_pBiasVisible = new double[m_numVisible]; m_pBiasHidden = new double[m_numHidden]; } } void free() { uint32_t i; if (m_ppW) { for (i=0; i < m_numHidden; i++) { delete [] m_ppW[i]; } delete [] m_ppW; m_ppW = nullptr; } delete [] m_pBiasVisible; m_pBiasVisible = nullptr; delete [] m_pBiasHidden; m_pBiasHidden = nullptr; } }; class Layer { public: Layer(uint32_t numUnits = 0) : m_numUnits(numUnits) , m_pInput(nullptr) , m_pProbs(nullptr) , m_pStates(nullptr) { setNumUnits(numUnits); Noise_Init(&m_noise, 0x12345677); } virtual ~Layer() { setNumUnits(0); Noise_Free(&m_noise); } void setNumUnits(uint32_t numUnits) { if (m_numUnits) { delete [] m_pProbs; delete [] m_pStates; } m_numUnits = numUnits; if (m_numUnits) { uint32_t i; m_pProbs = new double[m_numUnits]; m_pStates = new double[m_numUnits]; for (i=0; i < m_numUnits; i++) { m_pProbs[i] = 0.0; } for (i=0; i < m_numUnits; i++) { m_pStates[i] = 0.0; } } } Layer& operator= (const Layer &rhs) { memcpy(m_pProbs, rhs.m_pProbs, m_numUnits*sizeof(double)); memcpy(m_pStates, rhs.m_pStates, m_numUnits*sizeof(double)); } void setInput(const double *pInput) { m_pInput = pInput; } void probsUpdate(const Layer &layer, const Weights &weights) const { uint32_t i; for (i=0; i < m_numUnits; i++) { m_pProbs[i] = logSigmoid(accum(layer, weights, i)); } } void statesAssignfromInput() { if (!m_pInput) return; memcpy(m_pStates, m_pInput, m_numUnits*sizeof(double)); } void statesAssignfromProbs() { memcpy(m_pStates, m_pProbs, m_numUnits*sizeof(double)); } void statesUpdateStochastic() { uint32_t i; double sample; for (i=0; i < m_numUnits; i++) { sample = Noise_Uniform(&m_noise, 0.5); m_pStates[i] = (double)(sample <= m_pProbs[i]); } } const double *getProbs() const { return m_pProbs; } const double *getStates() const { return m_pStates; } uint32_t getNumUnits() const { return m_numUnits; } virtual double getEnergy(const Weights &weights) = 0; private: uint32_t m_numUnits; const double *m_pInput; noise_gen_t m_noise; inline double logSigmoid(double x) const { return 1./(1 + exp(-x)); } protected: double *m_pProbs; double *m_pStates; virtual double accum(const Layer &layer, const Weights &weights, uint32_t index) const = 0; }; #endif // LAYER_HPP