# Pastebin hiuZXY8l class NormalSampler { public: template static void Fn(const InputVecType& x, OutputVecType& y) { for (std::size_t i = 0; i < y.n_elem; i++) y[i] = math::RandNormal(x[2 * i], x[2 * i + 1); } }; class BinomialSampler { public: template static void Fn(const InputVecType& x, OutputVecType& y) { // this should be similar to core/math/random std::random_device rd; std::mt19937 gen(rd()); for (std::size_t i = 0; i < y.n_elem; i++) { std::binomial_distribution dist(1, x[i]); y[i] = dist(gen); } } }; /* * You can use the BaseLayer class if you define ActivationFunction::Deriv */ template < class ActivationFunction = NormalSampler, typename InputDataType = arma::mat, typename OutputDataType = arma::mat > class BaseProbabilisticLayer { template void Forward(const InputType&& input, OutputType&& output) { ActivationFunction::Fn(input, output); } }; template < class ActivationFunction = BinomialSampler, typename InputDataType = arma::mat, typename OutputDataType = arma::mat > using BinomialLayer = BaseProbabilisticLayer< ActivationFunction, InputDataType, OutputDataType>; /* * In such a way Gibbs sampling (for a binary RBM) is just a cyclic forward propogation over the network * VisibleLayer -> Linear -> SigmoidLayer -> BinomialSampler -> HiddenLayer -> Linear -> SigmoidLayer -> BinomialSampler * * Of course the implementation of the ssRBM in this manner is a little tricky but this is possible. * * Actually BinomialSampler is similar to your ConditionalDistribution and BinomialLayer is similar to the Try class. * But I think it is better to use the LayerType notation for that. */