Approximation to the reconstruction error Note that this function requires the pre-sigmoid activation as input. To understand why this is so you need to understand a bit about how Theano works. Whenever you compile a Theano function, the computational graph that you
(self, updates, pre_sigmoid_nv)
| 320 | return cost |
| 321 | |
| 322 | def get_reconstruction_cost(self, updates, pre_sigmoid_nv): |
| 323 | """Approximation to the reconstruction error |
| 324 | |
| 325 | Note that this function requires the pre-sigmoid activation as |
| 326 | input. To understand why this is so you need to understand a |
| 327 | bit about how Theano works. Whenever you compile a Theano |
| 328 | function, the computational graph that you pass as input gets |
| 329 | optimized for speed and stability. This is done by changing |
| 330 | several parts of the subgraphs with others. One such |
| 331 | optimization expresses terms of the form log(sigmoid(x)) in |
| 332 | terms of softplus. We need this optimization for the |
| 333 | cross-entropy since sigmoid of numbers larger than 30. (or |
| 334 | even less then that) turn to 1. and numbers smaller than |
| 335 | -30. turn to 0 which in terms will force theano to compute |
| 336 | log(0) and therefore we will get either -inf or NaN as |
| 337 | cost. If the value is expressed in terms of softplus we do not |
| 338 | get this undesirable behaviour. This optimization usually |
| 339 | works fine, but here we have a special case. The sigmoid is |
| 340 | applied inside the scan op, while the log is |
| 341 | outside. Therefore Theano will only see log(scan(..)) instead |
| 342 | of log(sigmoid(..)) and will not apply the wanted |
| 343 | optimization. We can not go and replace the sigmoid in scan |
| 344 | with something else also, because this only needs to be done |
| 345 | on the last step. Therefore the easiest and more efficient way |
| 346 | is to get also the pre-sigmoid activation as an output of |
| 347 | scan, and apply both the log and sigmoid outside scan such |
| 348 | that Theano can catch and optimize the expression. |
| 349 | |
| 350 | """ |
| 351 | |
| 352 | cross_entropy = T.mean( |
| 353 | T.sum( |
| 354 | self.input * T.log(T.nnet.sigmoid(pre_sigmoid_nv)) + |
| 355 | (1 - self.input) * T.log(1 - T.nnet.sigmoid(pre_sigmoid_nv)), |
| 356 | axis=1 |
| 357 | ) |
| 358 | ) |
| 359 | |
| 360 | return cross_entropy |
| 361 | |
| 362 | |
| 363 | def test_rbm(learning_rate=0.1, training_epochs=15, |