'Randomly initialize the visible units once, and start running alternating Gibbs sampling steps
(where each step consists of updating all the hidden units, and then updating all of the visible units),
taking a sample of the visible units at each step.
Note that we only initialize the network *once*, so these samples are correlated.
Returns
samples: A matrix, where each row is a sample of the visible units produced while the network was
daydreaming.'

def daydream(self, num_samples):

    samples = np.ones((num_samples, (self.num_visible + 1)))
    samples[0, 1:] = np.random.rand(self.num_visible)
    for i in range(1, num_samples):
        visible = samples[(i - 1), :]
        hidden_activations = np.dot(visible, self.weights)
        hidden_probs = self._logistic(hidden_activations)
        hidden_states = (hidden_probs > np.random.rand((self.num_hidden + 1)))
        hidden_states[0] = 1
        visible_activations = np.dot(hidden_states, self.weights.T)
        visible_probs = self._logistic(visible_activations)
        visible_states = (visible_probs > np.random.rand((self.num_visible + 1)))
        samples[i, :] = visible_states
    return samples[:, 1:]
