from __future__ import print_function
import numpy as np
class RBM:
def __init__(self, num_visible, num_hidden, learning_rate = 0.1):
self.num_hidden = num_hidden
self.num_visible = num_visible
self.learning_rate = learning_rate
self.weights = 0.1 * np.random.randn(self.num_visible, self.num_hidden)
self.weights = np.insert(self.weights, 0, 0, axis = 0)
self.weights = np.insert(self.weights, 0, 0, axis = 1)
def train(self, data, max_epochs = 1000):
"""
Train the machine.
Parameters
----------
data: A matrix where each row is a training example consisting of the states of visible units.
"""
num_examples = data.shape[0]
data = np.insert(data, 0, 1, axis = 1)
for epoch in range(max_epochs):
pos_hidden_activations = np.dot(data, self.weights)
pos_hidden_probs = self._logistic(pos_hidden_activations)
pos_hidden_states = pos_hidden_probs > np.random.rand(num_examples, self.num_hidden + 1)
pos_associations = np.dot(data.T, pos_hidden_probs)
neg_visible_activations = np.dot(pos_hidden_states, self.weights.T)
neg_visible_probs = self._logistic(neg_visible_activations)
neg_visible_probs[:,0] = 1
neg_hidden_activations = np.dot(neg_visible_probs, self.weights)
neg_hidden_probs = self._logistic(neg_hidden_activations)
neg_associations = np.dot(neg_visible_probs.T, neg_hidden_probs)
self.weights += self.learning_rate * ((pos_associations - neg_associations) / num_examples)
error = np.sum((data - neg_visible_probs) ** 2)
print("Epoch %s: error is %s" % (epoch, error))
def run_visible(self, data):
"""
Assuming the RBM has been trained (so that weights for the network have been learned),
run the network on a set of visible units, to get a sample of the hidden units.
Parameters
----------
data: A matrix where each row consists of the states of the visible units.
Returns
-------
hidden_states: A matrix where each row consists of the hidden units activated from the visible
units in the data matrix passed in.
"""
num_examples = data.shape[0]
hidden_states = np.ones((num_examples, self.num_hidden + 1))
data = np.insert(data, 0, 1, axis = 1)
hidden_activations = np.dot(data, self.weights)
hidden_probs = self._logistic(hidden_activations)
hidden_states[:,:] = hidden_probs > np.random.rand(num_examples, self.num_hidden + 1)
hidden_states = hidden_states[:,1:]
return hidden_states
def run_hidden(self, data):
"""
Assuming the RBM has been trained (so that weights for the network have been learned),
run the network on a set of hidden units, to get a sample of the visible units.
Parameters
----------
data: A matrix where each row consists of the states of the hidden units.
Returns
-------
visible_states: A matrix where each row consists of the visible units activated from the hidden
units in the data matrix passed in.
"""
num_examples = data.shape[0]
visible_states = np.ones((num_examples, self.num_visible + 1))
data = np.insert(data, 0, 1, axis = 1)
visible_activations = np.dot(data, self.weights.T)
visible_probs = self._logistic(visible_activations)
visible_states[:,:] = visible_probs > np.random.rand(num_examples, self.num_visible + 1)
visible_states = visible_states[:,1:]
return visible_states
def daydream(self, num_samples):
"""
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.
"""
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:]
def _logistic(self, x):
return 1.0 / (1 + np.exp(-x))
if __name__ == '__main__':
r = RBM(num_visible = 6, num_hidden = 2)
training_data = np.array([[1,1,1,0,0,0],[1,0,1,0,0,0],[1,1,1,0,0,0],[0,0,1,1,1,0], [0,0,1,1,0,0],[0,0,1,1,1,0]])
r.train(training_data, max_epochs = 5000)
print(r.weights)
user = np.array([[0,0,0,1,1,0]])
print(r.run_visible(user))