Advertisement
Guest User

Untitled

a guest
Nov 14th, 2019
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.32 KB | None | 0 0
  1. import numpy as np
  2. import pickle
  3. from mlxtend.data import loadlocal_mnist
  4. import math as m
  5. from scipy import signal
  6. import matplotlib.pyplot as plt
  7. import time
  8.  
  9. np.random.seed(1)                   # заставим numpy выдавать одинаковые набор случайных чисел для каждого запуска программы
  10. np.set_printoptions(suppress=True)  # выводить числа в формате 0.123 а не 1.23e-1
  11.  
  12. # В `X` находятся изображения для обучения, а в `y` значения соответственно
  13. # `X.shape` == (60000, 784)   # изображения имеют размер 28x28 pix => 28*28=784
  14. # `y.shape` == (60000,)       # каждое значение это число от 0 до 9 то что изображено на соответствующем изображении
  15. X, y = loadlocal_mnist(
  16.         images_path="F:/python/n1/train-images.idx3-ubyte",
  17.         labels_path="F:/python/n1/train-labels.idx1-ubyte")
  18.  
  19. # В `Xt` находятся изображения для тестирования, а в `yt` значения соответственно
  20. # `Xt.shape` == (10000, 784)   # изображения имеют размер 28x28 pix => 28*28=784
  21. # `yt.shape` == (10000,)       # каждое значение это число от 0 до 9 то что изображено на соответствующем изображении
  22. Xt, yt = loadlocal_mnist(
  23.         images_path="F:/python/n1/t10k-images.idx3-ubyte",
  24.         labels_path="F:/python/n1/t10k-labels.idx1-ubyte")
  25.  
  26. def sigmoid(x, deriv=False):
  27.     if deriv:
  28.         return x * (1 - x)
  29.  
  30.     return 1.0 / (1.0 + np.exp(-x))
  31.  
  32. def convert(y):
  33.     y_d = np.zeros((len(y), 10))
  34.  
  35.     for idx, val in enumerate(y):
  36.         y_d[idx, val] = 1.0
  37.  
  38.     return y_d
  39.  
  40. X = X * (1 / 255)
  41. Xt = Xt * (1 / 255)
  42.  
  43. # Параметры:
  44.  
  45. lr = 1       # значени на которое будет домножаться дельта на каждом шаге
  46. batch = 60   # кол-во изображений использованное для обучения на каждом шаге
  47. epochs = 100  # кол-во эпох. Если видно что прогресс есть, но нужно больше итераций
  48.  
  49. class MnistConvModel:
  50.     def __init__(self, lr=0.1, batch=60):
  51.         self.lr = lr
  52.         self.batch = batch
  53.         self.filters = 8
  54.  
  55.         self.W_conv = np.random.uniform(-0.05, 0.05, (self.filters, 3, 3))
  56.         self.W_linear = np.random.uniform(-0.05, 0.05, (self.filters * 26 * 26, 10))
  57.  
  58.     def load(self, conv, linear):
  59.         with open(conv, 'rb') as f:
  60.             self.W_conv = np.array(pickle.load(f)).reshape((self.filters, 3, 3))
  61.  
  62.         with open(linear, 'rb') as f:
  63.             self.W_linear = np.array(pickle.load(f)).reshape((self.filters * 26 * 26, -1))
  64.  
  65.     # Linear Layer
  66.  
  67.     def linear_forward(self, X):
  68.         return np.dot(X, self.W_linear)
  69.  
  70.     def linear_backward(self, e):
  71.         return np.dot(e, self.W_linear.T)
  72.  
  73.     # Sigmoid Layer
  74.  
  75.     def sigmoid_forward(self, X):
  76.         return sigmoid(X)
  77.  
  78.     def sigmoid_backward(self, e):
  79.         return e * sigmoid(self.o_sigmoid, True)
  80.  
  81.     # ReLU Layer
  82.  
  83.     def relu_forward(self, X):
  84.         X_o = X.copy()
  85.         X_o[X < 0] = 0
  86.  
  87.         return X_o
  88.    
  89.     def relu_backward(self, s):
  90.         res = s.copy()
  91.         res[res > 0] = 1.0
  92.  
  93.         return res
  94.  
  95.     # Convolution Layer
  96.     def convolution_backward(self, e):
  97.         res = np.zeros((len(e), len(e[0]), len(e[0][0]) + len(self.W_conv[0]) - 1, len(e[0][0]) + len(self.W_conv[0]) - 1))
  98.        
  99.         # res = np.zeros((len(e), 1, len(e[0][0]) + len(self.W_conv[0]) - 1, len(e[0][0]) + len(self.W_conv[0]) - 1))
  100.         # print(e.shape, self.W_conv.shape)
  101.         for b in np.arange(len(e)):
  102.             for ch in np.arange(len(e[b])):
  103.                 # print(signal.correlate2d(e[b][ch], self.W_conv[ch], mode="full").shape)
  104.                 res[b][ch] += signal.correlate2d(e[b][ch], self.W_conv[ch], mode="full")
  105.                 # res[b][0] += signal.correlate2d(e[b][ch], self.W_conv[ch], mode="full")
  106.         # print(np.max(e))
  107.         res /= len(e)
  108.         return res # TODO
  109.  
  110.     def convolution_forward(self, X):
  111.         (filter_channels, filter_height, filter_width) = self.W_conv.shape
  112.         (batch_size, in_channels, in_rows, in_cols) = X.shape
  113.         (out_channels, out_rows, out_cols) = (filter_channels, in_rows - 2, in_cols - 2)
  114.  
  115.         res = np.zeros((batch_size, out_channels, out_rows, out_cols))
  116.  
  117.         for batch in range(0, batch_size):
  118.             for och in range(0, out_channels):
  119.                 for ich in range(0, in_channels):
  120.                     res[batch][och] += signal.convolve2d(X[batch][ich], self.W_conv[och], mode='valid')
  121.  
  122.         return res
  123.  
  124.  
  125.  
  126.     def forward(self, X):
  127.         self.X = X
  128.         # print("f", self.X.shape)
  129.        
  130.         self.o_conv = self.convolution_forward(X)
  131.        
  132.         # print("f", self.o_conv.shape)
  133.         self.o_relu = self.relu_forward(self.o_conv).reshape(len(X), -1)
  134.         # print("f", self.o_relu.shape)
  135.         self.o_linear = self.linear_forward(self.o_relu)
  136.        
  137.         self.o_sigmoid = self.sigmoid_forward(self.o_linear)
  138.        
  139.         return self.o_sigmoid
  140.  
  141.  
  142.     def backward(self, e):
  143.         self.e_sigmoid = self.sigmoid_backward(e)
  144.  
  145.         self.e_linear = self.linear_backward(self.e_sigmoid)
  146.  
  147.         self.e_relu = self.relu_backward(self.e_linear.reshape((-1, self.filters, 26, 26)))
  148.        
  149.         self.e_conv = self.convolution_backward(self.e_relu)
  150.  
  151.     def calc_gradients(self):
  152.         scaler = 1 / len(self.X)
  153.         # print(self.W_conv.shape, self.e_conv.shape, self.o_conv.shape)
  154.         # asd
  155.         self.dW_linear = np.dot(self.o_relu.T, self.e_sigmoid) * scaler
  156.         temp = np.zeros(self.W_conv.shape)
  157.         # print(temp.shape)
  158.         for b in np.arange(len(self.e_conv)):
  159.             for ch in np.arange(len(self.W_conv)):
  160.                 # print(self.o_conv.shape, self.e_conv[b][ch].shape, self.o_conv[ch].shape)
  161.                 # print(self.e_conv.shape)
  162.                 temp[ch] += signal.correlate2d(self.e_conv[b][ch], self.e_relu[b][ch], mode="valid")
  163.             temp *= scaler
  164.         # print(np.max(temp))
  165.         self.dW_conv = temp
  166.        
  167.         # (self.X.reshape(100, 28, 28).T.dot(self.e_conv.reshape(len(self.X), -1)) * scaler)
  168.         # print(self.dW_conv.shape)
  169.         # asd
  170.  
  171.     def update(self):
  172.         self.W_linear -= self.dW_linear * self.lr
  173.         self.W_conv -= self.dW_conv * self.lr
  174.  
  175. def mse(o, y):
  176.     return np.sum(np.square(o - y))
  177.  
  178. def mse_prime(o, y):
  179.     return 2 * (o - y)
  180.  
  181. def validate(model, X, y):
  182.     tp = model.forward(X)
  183.  
  184.     return np.sum(y == np.argmax(tp, axis=1)) / len(y)
  185.  
  186. def train(model, X, y, epochs=100, batch_size=100, validation=None):
  187.     batch_count = m.ceil(len(y) / batch_size)
  188.     loss = np.zeros((epochs * 6))
  189.     t = np.zeros((len(y), 10))
  190.     np.put_along_axis(t, y.reshape((-1, 1)), 1.0, axis=1)
  191.  
  192.     lind = 0
  193.     for epoch in range(0, epochs):
  194.         st_time = time.time()
  195.         print("Epoch ", epoch + 1)
  196.         for index, (bX, bt) in enumerate(zip(np.split(X, batch_count), np.split(t, batch_count))):
  197.             res = model.forward(bX)
  198.             error = mse_prime(res, bt)
  199.  
  200.             model.backward(error)
  201.             model.calc_gradients()
  202.             model.update()
  203.  
  204.             if index % 100 == 0:
  205.                 loss[lind] = mse(res, bt)
  206.                 print("  Loss: ", loss[lind])
  207.                 lind += 1
  208.         if validation is not None:
  209.             end_time = time.time()
  210.             (model, val_X, val_y) = validation
  211.             print("  Accuracy: ", validate(model, val_X, val_y), " Time: ", end_time - st_time)
  212.            
  213.     plt.title("Loss функция")  # заголовок
  214.     plt.xlabel("эпоха")  # ось абсцисс
  215.     plt.ylabel("loss")  # ось ординат
  216.     plt.grid()      # включение отображение сетки
  217.     # print('h')
  218.     plt.plot(np.arange(epochs * 6), loss)
  219.     plt.show()
  220.  
  221. if __name__ == "__main__":
  222.     model = MnistConvModel()
  223.     X = X.reshape((-1, 1, 28, 28))
  224.     Xt = Xt.reshape((-1, 1, 28, 28))
  225.  
  226.     train(model, X, y, epochs=10, validation=(model, Xt, yt))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement