Guest User

Untitled

a guest
Aug 19th, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.22 KB | None | 0 0
  1. # Numpy for matrix math and matplotlib for plotting loss
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4. # Abstract Base Class
  5. from abc import ABC, abstractmethod
  6.  
  7. MOMENTUM = 0.9
  8.  
  9.  
  10. def l2_loss(y, yhat):
  11. loss_matrix = np.square(yhat - y)
  12. loss_gradient = 2 * (yhat - y)
  13. return loss_matrix, loss_gradient
  14.  
  15.  
  16. def apply_linear_momentum(prev_momentum, grad_parameter, momentum):
  17. # Calculate momentum update by linear momentum method
  18. assert momentum <= 1 and momentum >= 0
  19.  
  20. return prev_momentum * momentum + grad_parameter * (1 - momentum)
  21.  
  22.  
  23. class Layer(ABC):
  24. @abstractmethod
  25. def __init__(self, **args):
  26. pass
  27.  
  28. @abstractmethod
  29. def forward(self, x):
  30. # Forward propagate. Remember params needed for backprop
  31. pass
  32.  
  33. @abstractmethod
  34. def backward(self, x):
  35. # Return gradient to input, gradient to parameters
  36. pass
  37.  
  38. def step(self, learning_rate):
  39. pass
  40.  
  41.  
  42. class Lrelu(Layer):
  43. def __init__(self, input_layer=None, in_size=None):
  44. self.out_size = input_layer if input_layer is not None else in_size
  45.  
  46. def forward(self, x):
  47. return np.maximum(x, x * .1)
  48.  
  49. def backward(self, out_grad):
  50. grad_back = np.where(out_grad > 0, out_grad, out_grad * .1)
  51. return grad_back
  52.  
  53.  
  54. class Linear(Layer):
  55. def __init__(self, input_layer=None, in_size=None, out_size=None):
  56. self.in_size = input_layer if input_layer is not None else in_size
  57. self.out_size = out_size
  58. self.w = np.random.randn(in_size, out_size)
  59. self.vel = np.zeros((in_size, out_size))
  60.  
  61. def forward(self, x):
  62. self.prev_input = x
  63. return np.matmul(x, self.w)
  64.  
  65. def backward(self, out_grad):
  66. # in_size, BS * BS, out_size = in_size, out_size
  67. raw_grad_w = np.matmul(self.prev_input.T, out_grad)
  68. self.grad_w = np.clip(raw_grad_w, -1, 1)
  69.  
  70. # BS, out_size * out_size, in_size = BS, in_size
  71. return np.matmul(out_grad, self.w.T)
  72.  
  73. def step(self, learning_rate):
  74. self.vel = apply_linear_momentum(self.vel, self.grad_w, MOMENTUM)
  75. self.w = self.w - self.vel * learning_rate
  76.  
  77.  
  78. class MultiLayerPerceptron():
  79. def __init__(self, layers, loss_fcn):
  80. self.layers = layers
  81. self.loss_fcn = loss_fcn
  82.  
  83. def forward(self, x):
  84. for layer in self.layers:
  85. x = layer.forward(x)
  86. yhat = x
  87. return yhat
  88.  
  89. def backward(self, loss_gradient):
  90. for layer in self.layers[::-1]:
  91. loss_gradient = layer.backward(loss_gradient)
  92.  
  93. def loss(self, y, yhat):
  94. loss_matrix, loss_gradient = self.loss_fcn(y, yhat)
  95. return loss_matrix, loss_gradient
  96.  
  97. def step(self, learning_rate):
  98. for layer in self.layers:
  99. layer.step(learning_rate)
  100.  
  101.  
  102. class Trainer():
  103. def __init__(self, model):
  104. self.model = model
  105. self.losses = []
  106. self.steps = 0
  107.  
  108. def optimize(self, x, y, learning_rate):
  109. model = self.model
  110. yhat = model.forward(x)
  111. loss_matrix, loss_gradient = model.loss(y, yhat)
  112. model.backward(loss_gradient)
  113. model.step(learning_rate)
  114. loss_rms = np.sqrt(np.square(loss_matrix).sum(1)).mean()
  115. self.losses.append(loss_rms)
  116.  
  117. def train_n_steps(self, n, x, y):
  118. for _ in range(n):
  119. self.steps += 1
  120. self.optimize(x, y, learning_rate=1 / (self.steps + 100))
  121.  
  122. def visualize(self, skip_first=0):
  123. plt.plot(self.losses[skip_first:])
  124. plt.title('Loss for model with momentum, clean software\napproaches ' +
  125. str(self.losses[-1])[:5])
  126. plt.savefig('model_5.jpg')
  127. plt.show()
  128.  
  129.  
  130. if __name__ == "__main__":
  131. # N is batch size; D_in is input dimension;
  132. # H is hidden dimension; D_out is output dimension.
  133. N, D_in, H, D_out = 64, 1000, 100, 10
  134.  
  135. # Create random input and output data
  136. x = np.random.randn(N, D_in)
  137. y = np.random.randn(N, D_out)
  138.  
  139. sizes = [D_in, H, D_out]
  140.  
  141. layers = []
  142. layers.append(Linear(in_size=D_in, out_size=H))
  143. layers.append(Lrelu(in_size=H))
  144. layers.append(Linear(in_size=H, out_size=D_out))
  145.  
  146. model = MultiLayerPerceptron(layers, loss_fcn=l2_loss)
  147.  
  148. trainer = Trainer(model)
  149. trainer.train_n_steps(n=500, x=x, y=y)
  150. trainer.visualize(skip_first=300)
Add Comment
Please, Sign In to add comment