finalized code + cleanup
parent
ef7be8ac54
commit
176ed663c1
|
@ -1,5 +1,3 @@
|
||||||
from typing import Tuple
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
@ -11,23 +9,34 @@ def load_data():
|
||||||
|
|
||||||
return df_digits.to_numpy()
|
return df_digits.to_numpy()
|
||||||
|
|
||||||
|
|
||||||
mnist = load_data()
|
mnist = load_data()
|
||||||
|
|
||||||
|
|
||||||
def sigmoid(x):
|
def sigmoid(x):
|
||||||
return 1.0 / (1.0 + np.exp(-x)) # Sigmoidfunktion
|
return 1.0 / (1.0 + np.exp(-x)) # Sigmoidfunktion
|
||||||
|
|
||||||
|
|
||||||
class RBM:
|
class RBM:
|
||||||
|
|
||||||
def __init__(self, visible_size: int, hidden_size: int, learnrate: float=0.1) -> None:
|
def __init__(self, visible_size: int, hidden_size: int, learnrate: float = 0.1, epochs=20):
|
||||||
|
"""__init__ Initializes a newly created Ristricted Bolzmann Machine.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
visible_size (int): amount of neurons inside the visible layer
|
||||||
|
hidden_size (int): amount of neurons inside the hidden layer
|
||||||
|
learnrate (float, optional): learnrate eta in [0;1]. Defaults to 0.1.
|
||||||
|
epochs (int, optional): training epochs. Defaults to 20.
|
||||||
|
"""
|
||||||
self.learnrate = learnrate
|
self.learnrate = learnrate
|
||||||
self.visible_size = visible_size
|
self.visible_size = visible_size
|
||||||
self.hidden_size = hidden_size
|
self.hidden_size = hidden_size
|
||||||
self.k = 2
|
self.epochs = epochs
|
||||||
self.epochs = 10
|
|
||||||
|
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
def reset(self) -> None:
|
def reset(self):
|
||||||
|
# initialize/reset learnable attributes
|
||||||
self.weights = np.random.randn(self.visible_size, self.hidden_size)
|
self.weights = np.random.randn(self.visible_size, self.hidden_size)
|
||||||
self.visible_bias = np.zeros(self.visible_size) * 0.1
|
self.visible_bias = np.zeros(self.visible_size) * 0.1
|
||||||
self.hidden_bias = np.zeros(self.hidden_size) * 0.1
|
self.hidden_bias = np.zeros(self.hidden_size) * 0.1
|
||||||
|
@ -39,63 +48,66 @@ class RBM:
|
||||||
return sigmoid(np.matmul(self.weights, h0.T) + self.visible_bias)
|
return sigmoid(np.matmul(self.weights, h0.T) + self.visible_bias)
|
||||||
|
|
||||||
def contrastive_divergence(self, v0, h0, v1, h1):
|
def contrastive_divergence(self, v0, h0, v1, h1):
|
||||||
|
# calculate gradients
|
||||||
postive_gradient = np.outer(v0, h0)
|
postive_gradient = np.outer(v0, h0)
|
||||||
negative_gradient = np.outer(v1, h0)
|
negative_gradient = np.outer(v1, h0)
|
||||||
|
|
||||||
|
# Adjust weights by delta
|
||||||
self.weights += self.learnrate * (postive_gradient - negative_gradient)
|
self.weights += self.learnrate * (postive_gradient - negative_gradient)
|
||||||
|
|
||||||
return self.weights
|
# Adjust biases by delta
|
||||||
|
|
||||||
def train(self, v0):
|
|
||||||
for _ in range(self.epochs):
|
|
||||||
h0 = self.activate(v0) # Aktivieren versteckter Schicht
|
|
||||||
v1 = self.reactivate(h0) # Reaktivieren sichtbarer Schicht
|
|
||||||
h1 = self.activate(v1)
|
|
||||||
|
|
||||||
self.contrastive_divergence(v0, h0, v1, h1)
|
|
||||||
|
|
||||||
self.visible_bias += self.learnrate * (v0 - v1)
|
self.visible_bias += self.learnrate * (v0 - v1)
|
||||||
self.hidden_bias += self.learnrate * (h0 - h1)
|
self.hidden_bias += self.learnrate * (h0 - h1)
|
||||||
|
|
||||||
|
def train(self, v0):
|
||||||
|
for _ in range(self.epochs):
|
||||||
|
# activate hidden layer
|
||||||
|
h0 = self.activate(v0)
|
||||||
|
|
||||||
return h0, v1
|
# reactivate visible layer
|
||||||
|
v1 = self.reactivate(h0)
|
||||||
|
|
||||||
def run(self, v0 : np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
|
#activate next hidden layer
|
||||||
"""run Runs the Restricted Boltzmann machine on some input vector v0.
|
h1 = self.activate(v1)
|
||||||
|
|
||||||
Args:
|
# Adjust weights
|
||||||
v0 (np.ndarray): 1-dimensional Input vector
|
self.contrastive_divergence(v0, h0, v1, h1)
|
||||||
|
|
||||||
Returns:
|
def run(self, v0):
|
||||||
Tuple[np.ndarray, np.ndarray]: (hidden activation, visible reactivation)
|
# activate hidden layer
|
||||||
"""
|
|
||||||
h0 = self.activate(v0)
|
h0 = self.activate(v0)
|
||||||
v1 = self.reactivate(h0)
|
v1 = self.reactivate(h0)
|
||||||
|
|
||||||
return h0, v1
|
return h0, v1
|
||||||
|
|
||||||
|
rbm = RBM(28**2, 256, 0.1, epochs=3)
|
||||||
|
|
||||||
def validate(idx):
|
def validate(idx):
|
||||||
|
#flatten and normalize mnist data
|
||||||
test = mnist[idx].flatten()/255
|
test = mnist[idx].flatten()/255
|
||||||
|
|
||||||
|
# train bolzmann machine and run
|
||||||
rbm.train(test)
|
rbm.train(test)
|
||||||
(hid, out) = rbm.run(test)
|
(hid, out) = rbm.run(test)
|
||||||
|
|
||||||
return (hid.reshape((5, 5)), out.reshape((28,28)))
|
return (hid.reshape((16, 16)), out.reshape((28, 28)))
|
||||||
|
|
||||||
|
# plot results
|
||||||
rbm = RBM(28**2, 25, 0.1)
|
rows, columns = (4, 6)
|
||||||
|
|
||||||
rows, columns = (4,4)
|
|
||||||
fig = plt.figure(figsize=(10, 7))
|
fig = plt.figure(figsize=(10, 7))
|
||||||
|
|
||||||
for i in range((rows * columns)):
|
for i in range((rows * columns)):
|
||||||
if i % 2 == 0:
|
if i % 2 == 0:
|
||||||
(hid, out) = validate(i)
|
(hid, out) = validate(i)
|
||||||
|
|
||||||
|
# hidden layer
|
||||||
fig.add_subplot(rows, columns, i+1)
|
fig.add_subplot(rows, columns, i+1)
|
||||||
plt.imshow(hid, cmap='gray')
|
plt.imshow(hid, cmap='gray')
|
||||||
|
plt.axis('off')
|
||||||
|
|
||||||
|
# visible layer
|
||||||
fig.add_subplot(rows, columns, i+2)
|
fig.add_subplot(rows, columns, i+2)
|
||||||
plt.imshow(out, cmap='gray')
|
plt.imshow(out, cmap='gray')
|
||||||
plt.axis('off')
|
plt.axis('off')
|
||||||
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue