Advertisement
Guest User

Untitled

a guest
Jun 13th, 2019
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.56 KB | None | 0 0
  1. from scipy.special import erf
  2. import numpy as np
  3.  
  4. def logistic(x):
  5.     return 0.5 * (1 + erf(x))
  6.  
  7. # Computes gradient (possibly, the Jacobian) of y with respect to xs
  8. def grad(y, xs):
  9.     dx = 0.0001
  10.     return np.stack(
  11.         (y(xs + dxs) - y(xs - dxs)) / (2 * dx)
  12.         for dxs in dx * np.eye(len(xs.T))
  13.     ).T
  14.  
  15. def forward_pure(weights, inputs):
  16.     return logistic(weights @ inputs)
  17.  
  18. class Layer:
  19.     def __init__(self, input_size, output_size, learning_rate=1):
  20.         # weights column 0 is bias
  21.         self.weights = np.random.normal(size=(output_size, input_size + 1))
  22.         self.learning_rate = learning_rate
  23.  
  24.     def forward(self, inputs):
  25.         self.inputs = np.array([1, *inputs])
  26.         self.outputs = forward_pure(self.weights, self.inputs)
  27.         return self.outputs
  28.  
  29.     def backward(self, error_grad):
  30.         # Derivative of output w.r.t. weights
  31.         self.dout_dw = grad(lambda w: forward_pure(w, self.inputs), self.weights)
  32.         # Derivative of output w.r.t. inputs
  33.         # (input 0 is constant, so differentiating wrt. it is useless)
  34.         self.dout_din = grad(lambda i: forward_pure(self.weights, i), self.inputs)[:, 1:]
  35.  
  36.         # Adjust weights
  37.         # We note that according to the chain rule:
  38.         # d[Error]/d[weights] = d[Error]/d[outputs] @ d[outputs]/d[weights]
  39.         # self.derror_dw = error_grad @ self.dout_dw
  40.         self.derror_dw = error_grad @ self.dout_dw
  41.         self.weights -= self.learning_rate * self.derror_dw
  42.  
  43.         # Return gradient propagated backwards
  44.         return self.dout_din
  45.  
  46. def loss(actual, predicted):
  47.     return np.sum((predicted - actual) ** 2)
  48.  
  49. # Gradient of loss w.r.t. predictions
  50. def loss_grad(actual, predicted):
  51.     return grad(lambda xs: loss(actual, xs), predicted)
  52.  
  53. class NN:
  54.     def __init__(self, layers):
  55.         self.layers = layers
  56.  
  57.     def forward(self, inputs):
  58.         for layer in self.layers:
  59.             inputs = layer.forward(inputs)
  60.  
  61.         self.outputs = inputs
  62.         return inputs
  63.  
  64.     def backward(self, actual):
  65.         # derivative of error w.r.t. output
  66.         de_do = loss_grad(actual, self.outputs)
  67.  
  68.         for layer in reversed(self.layers):
  69.             de_do = layer.backward(de_do)
  70.  
  71.         return de_do
  72.  
  73. def train(nn, num_epochs, Xs, ys):
  74.     for i in range(num_epochs):
  75.         samples = list(zip(Xs, ys))
  76.         np.random.shuffle(samples)
  77.  
  78.         for X, y in samples:
  79.             pred = nn.forward(X)
  80.             err = nn.backward(y)
  81.  
  82.     for X, y in zip(Xs, ys):
  83.         pred = nn.forward(X)
  84.         print(X, y, np.round(pred, 3))
  85.  
  86. print("Learning logical AND")
  87. train(
  88.     nn = NN(layers=[
  89.         Layer(input_size=2, output_size=1),
  90.     ]),
  91.     num_epochs=10000,
  92.     Xs = np.array([
  93.         [0, 0],
  94.         [0, 1],
  95.         [1, 0],
  96.         [1, 1],
  97.     ]),
  98.     ys = np.array([
  99.         [0],
  100.         [0],
  101.         [0],
  102.         [1],
  103.     ])
  104. )
  105. print("Learning logical OR")
  106. train(
  107.     nn = NN(layers=[
  108.         Layer(input_size=2, output_size=1),
  109.     ]),
  110.     num_epochs=10000,
  111.     Xs = np.array([
  112.         [0, 0],
  113.         [0, 1],
  114.         [1, 0],
  115.         [1, 1],
  116.     ]),
  117.     ys = np.array([
  118.         [0],
  119.         [1],
  120.         [1],
  121.         [1],
  122.     ])
  123. )
  124. print("Learning both at the same time")
  125. train(
  126.     nn = NN(layers=[
  127.         Layer(input_size=2, output_size=2),
  128.     ]),
  129.     num_epochs=10000,
  130.     Xs = np.array([
  131.         [0, 0],
  132.         [0, 1],
  133.         [1, 0],
  134.         [1, 1],
  135.     ]),
  136.     ys = np.array([
  137.         [0, 0],
  138.         [0, 1],
  139.         [0, 1],
  140.         [1, 1],
  141.     ])
  142. )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement