0
$\begingroup$

As the title says, i made an RBM from scratch:

class RBM:
  def __init__(self, data, n_v, n_h, k, epochs, mini_batch_size, alpha, momentum, weight_decay):
    self.number_features = 10
    self.n_v = n_v
    self.n_h = self.number_features
    self.k = k
    self.alpha = alpha
    self.momentum = momentum
    self.weight_decay = weight_decay
    self.mini_batch_size = mini_batch_size
    self.epochs = epochs
    self.data = data

  def sigmoid(self, x):
    x = np.clip(x, -25, 25)
    return 1 / (1 + np.exp(-x))

  def fit(self):
    np.random.seed(100)
    self.data = self.data / 255.0
    self.n_v = len(self.data[0])
    self.n_h = self.number_features

    self.w = np.random.randn(self.n_v, self.n_h) * 0.1 # initialization of weights, a matrix of shape (v1, h0)
    self.a = np.ones(self.n_v) * 0.5 # initialization of the biases in the forward step, matrix of size v1
    self.b = np.ones(self.n_h) # initialization of the biases in the reconstruction step, matrix of size h1 (which is equal to h0)

    self.w_moment = np.zeros((self.n_v, self.n_h))
    self.a_moment = np.zeros((self.n_v))
    self.b_moment = np.zeros((self.n_h))

    self.train()

  def train(self):
    for epoch_no in range(self.epochs): # iterates through epochs
      if epoch_no == 100: self.momentum = 0.9
      ep_error = 0 # initialization of the error for each epoch

      for i in range(0, len(self.data), self.mini_batch_size): # data is splitted into batches
        mini_batch = self.data[i:i+self.mini_batch_size]
        ep_error += self.contrastive_divergence(mini_batch) # contrastive divergence is added to error of epoch ep

      print("Epoch Number: ", epoch_no, "Error: ", ep_error.item())

  def contrastive_divergence(self, v):
    p_h_0 = self.sample_hidden(v) 
    h_0 = (p_h_0 >= np.random.rand(self.n_h)) 
    g_0 = np.dot(v.T, h_0) 

    wv_a = h_0

    for step in range(self.k):
      p_v_h = self.sample_visible(wv_a)
      p_h_v = self.sample_hidden(p_v_h) 
      wv_a = (p_h_v >= np.random.rand(self.n_h))

    p_v_k = p_v_h
    p_h_k = p_h_v

    g_k = np.dot(p_v_k.T, p_h_k)

    self.update_parameters(g_0, g_k, v, p_v_k, p_h_0, p_h_k)
    error = np.sum((v - p_v_k) ** 2) / len(p_v_k)

    return error

  def sample_hidden(self, p_v_h):
    wv = np.dot(p_v_h, self.w)
    wv_a = wv + self.b
    p_h_v = self.sigmoid(wv_a)

    return p_h_v

  def sample_visible(self, p_h_v):
    wh = np.dot(p_h_v, self.w.T)

    wh_b = wh + self.a
    p_v_h = self.sigmoid(wh_b)

    return p_v_h

  def update_parameters(self, g_0, g_k, v, p_v_k, p_h_0, p_h_k):
    self.w_moment *= self.momentum
    del_w = (g_0 - g_k) + self.w_moment

    self.a_moment *= self.momentum
    del_a = np.sum(v - p_v_k, axis=0) + self.a_moment

    self.b_moment *= self.momentum
    del_b = np.sum(p_h_0 - p_h_k, axis=0) + self.b_moment

    batch_size = v.shape[0]

    self.w += (del_w * self.alpha / batch_size) - self.w * self.weight_decay
    self.a += del_a * self.alpha / batch_size
    self.b += del_b * self.alpha / batch_size

    self.w_moment = del_w
    self.a_moment = del_a
    self.b_moment = del_b

  def predict(self, x_test):
    return self.sample_hidden(x_test)

And then i fit my model on MNIST:

from keras.datasets import mnist

(xt, yt), (xtt, ytt) = mnist.load_data()
xt = np.array([i.flatten() for i in xt])

rbm = RBM(xt[:2500], 0, 0, 2, 500, 64, 0.15, 0.5, 0.0001)
rbm.fit()

The error drops up to converge (not to a value next to 0), and when i try to predict an image this is one of the outputs:

Can someone tell me how to fix this? it may be in hyperparameters as well as in code

$\endgroup$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.