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  * <http://shark-ml.org/>
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 
39 namespace 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)$
47 template<class RBMType>
48 double 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
78 template<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
101 template<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 
117 };
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_rows(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;
141  case AcceptanceRatioMean:
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_rows(energyDiffUp),sum_rows(energyDiffDown));
148  }
149 
150  return deltaF;
151 }
152 
153 template<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 
170 template<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_rows(energyDiffTempering))-std::log(double(samples));
179 }
180 
181 template<class RBMType>
183  RBMType& rbm, Data<RealVector> const& initDataset,
184  std::size_t chains, std::size_t samples,
185  PartitionEstimationAlgorithm algorithm = AIS,
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 
195 template<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