analytics.h
Go to the documentation of this file.
1/*!
2 *
3 *
4 * \brief -
5 *
6 * \author O. Krause, A.Fischer
7 * \date 2012-2014
8 *
9 *
10 * \par Copyright 1995-2017 Shark Development Team
11 *
12 * <BR><HR>
13 * This file is part of Shark.
14 * <https://shark-ml.github.io/Shark/>
15 *
16 * Shark is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU Lesser General Public License as published
18 * by the Free Software Foundation, either version 3 of the License, or
19 * (at your option) any later version.
20 *
21 * Shark is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public License
27 * along with Shark. If not, see <http://www.gnu.org/licenses/>.
28 *
29 */
30#ifndef SHARK_UNSUPERVISED_RBM_ANALYTICS_H
31#define SHARK_UNSUPERVISED_RBM_ANALYTICS_H
32
33
34#include "Impl/analytics.h"
35
37#include <shark/Data/Dataset.h>
38
39namespace shark {
40///\brief Calculates the value of the partition function $Z$.
41///
42///Only useful for small input and theoretical analysis
43///
44///@param rbm the RBM for which to calculate the function
45///@param beta the inverse temperature of the RBM. default is 1
46///@return the value of the partition function $Z*e^(-constant)$
47template<class RBMType>
48double logPartitionFunction(RBMType const& rbm, double beta = 1.0) {
49
50 //special case: beta=0 is easy to compute and no explicit summation is needed
51 //as the RBM does not have any cross-terms anymore, the distribution is p(v,h)=p(v)*p(h)
52 //so we can simply assume v=0 and integrate all h in p(0,h) and then integrate over all v in p(v,0)
53 //and then multiply (or add the logarithms).
54 if(beta == 0.0){
55 RealVector zeroH(rbm.numberOfHN(),0.0);
56 RealVector zeroV(rbm.numberOfVN(),0.0);
57 double logPartition = rbm.visibleNeurons().logMarginalize(zeroV,0.0);
58 logPartition += rbm.hiddenNeurons().logMarginalize(zeroH,0.0);
59 return logPartition;
60 }
61 //choose correct version based on the enumeration tags
62 typedef typename RBMType::HiddenType::StateSpace::EnumerationTag HiddenTag;
63 typedef typename RBMType::VisibleType::StateSpace::EnumerationTag VisibleTag;
64
65 return detail::logPartitionFunction(rbm,VisibleTag(),HiddenTag(),beta);
66}
67
68
69///\brief Estimates the negative log-likelihood of a set of input vectors under the models distribution using the partition function
70///
71///Only useful for small input and theoretical analysis
72///
73///@param rbm the Restricted Boltzmann machine for which the negative log likelihood of the data is to be calculated
74///@param inputs the input vectors
75///@param logPartition the logarithmic value of the partition function of the RBM.
76///@param beta the inverse temperature of the RBM. default is 1
77///@return the log-likelihood
78template<class RBMType>
80 RBMType const&rbm,
81 UnlabeledData<RealVector> const& inputs,
82 double logPartition,
83 double beta = 1.0
84) {
85 double logP=0;
86 for(RealMatrix const& batch: inputs.batches()) {
87 logP += sum(rbm.energy().logUnnormalizedProbabilityVisible(batch, blas::repeat(beta,batch.size1())));
88 logP -= batch.size1()*logPartition;
89 }
90 return -logP;
91}
92
93///\brief Estimates the negative log-likelihood of a set of input vectors under the models distribution.
94///
95///Only useful for small input and theoretical analysis
96///
97///@param rbm the Restricted Boltzmann machine for which the negative log likelihood of the data is to be calculated
98///@param inputs the input vectors
99///@param beta the inverse temperature of the RBM. default is 1
100///@return the log-likelihood
101template<class RBMType>
103 RBMType const& rbm,
104 UnlabeledData<RealVector> const& inputs,
105 double beta = 1.0
106) {
107 double const logPartition = logPartitionFunction(rbm,beta);
108 return negativeLogLikelihoodFromLogPartition(rbm,inputs,logPartition,beta);
109}
110
118
120 RealMatrix const& energyDiffUp,
121 RealMatrix const& energyDiffDown,
123){
124 std::size_t chains = energyDiffUp.size1();
125 std::size_t samples = energyDiffUp.size2();
126 double deltaF = 0;
127 switch(algorithm){
128 case AIS:
129 deltaF = soft_max(-sum(as_columns(energyDiffUp)))-std::log(double(samples));
130 break;
131 case AISMean:
132 for(std::size_t i = chains-1; i != 0; --i){
133 deltaF += soft_max(-row(energyDiffUp,i))-std::log(double(samples));
134 }
135 break;
136 case TwoSidedAISMean:
137 for(std::size_t i = chains-1; i != 0; --i){
138 deltaF += detail::twoSidedAIS(row(energyDiffUp,i),row(energyDiffDown,i-1));
139 }
140 break;
142 for(std::size_t i = chains-1; i != 0; --i){
143 deltaF += detail::acceptanceRatio(row(energyDiffUp,i),row(energyDiffDown,i-1));
144 }
145 break;
146 case AcceptanceRatio:
147 deltaF = detail::acceptanceRatio(sum(as_columns(energyDiffUp)),sum(as_columns(energyDiffDown)));
148 }
149
150 return deltaF;
151}
152
153template<class RBMType>
155 RBMType& rbm, Data<RealVector> const& initDataset,
156 RealVector const& beta, std::size_t samples,
158 float burnInPercentage =0.1
159){
160 std::size_t chains = beta.size();
161 RealMatrix energyDiffUp(chains,samples);
162 RealMatrix energyDiffDown(chains,samples);
163 detail::sampleEnergies(rbm,initDataset,beta,energyDiffUp,energyDiffDown,burnInPercentage);
164
166 energyDiffUp,energyDiffDown,algorithm
167 );
168}
169
170template<class RBMType>
172 RBMType& rbm,RealVector const& beta, std::size_t samples
173){
174 std::size_t chains = beta.size();
175 RealMatrix energyDiffTempering(chains,samples,0.0);
176 detail::sampleEnergiesWithTempering(rbm,beta,energyDiffTempering);
177
178 return soft_max(-sum(as_columns(energyDiffTempering)))-std::log(double(samples));
179}
180
181template<class RBMType>
183 RBMType& rbm, Data<RealVector> const& initDataset,
184 std::size_t chains, std::size_t samples,
186 float burnInPercentage =0.1
187){
188 RealVector beta(chains);
189 for(std::size_t i = 0; i != chains; ++i){
190 beta(i) = 1.0-i/double(chains-1);
191 }
192 return estimateLogFreeEnergy(rbm,initDataset,beta,samples,algorithm,burnInPercentage);
193}
194
195template<class RBMType>
197 RBMType& rbm,std::size_t chains, std::size_t samples
198){
199 RealVector beta(chains);
200 for(std::size_t i = 0; i != chains; ++i){
201 beta(i) = 1.0-i/double(chains-1);
202 }
203 return annealedImportanceSampling(rbm,beta,samples);
204}
205
206}
207#endif