iris_improvment.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import numpy as np
  2. from sklearn import datasets
  3. import random
  4. iris = datasets.load_iris()
  5. dataset = [(iris.data[i][None, ...], iris.target[i]) for i in range(len(iris.target))]
  6. ''' Данная нейросеть работает с batch-ами
  7. batch это группа образцов для обучения
  8. ошибка вычисляется суммарной ошибкой для группы образцов '''
  9. INPUT_DIM = 4 # входные параметры
  10. OUTPUT_DIM = 3 # ответы нейронной сети
  11. H_DIM = 10 # Количество нейронов в слое
  12. # функции
  13. def relu(x): # функция активации 1 скрытого слоя
  14. return np.maximum(0, x)
  15. def softmax(x): # функция активации выходного слоя
  16. out = np.exp(x)
  17. return out / np.sum(out)
  18. def softmax_batch(x):
  19. out = np.exp(x)
  20. return out / np.sum(out, axis=1, keepdims=True)
  21. def sparse_cross_entropy_batch(a, b):
  22. return -np.log(np.array([a[j, b[j]] for j in range(len(b))]))
  23. def to_full_batch(a, num_class):
  24. y_full = np.zeros((len(a), num_class))
  25. for j, yj in enumerate(a):
  26. y_full[j, yj] = 1
  27. return y_full
  28. def relu_deriv(t): # производная от функция ReLU
  29. return (t >= 0).astype(float)
  30. # два полносвязных слоя
  31. # объявление весов и bias
  32. W1 = np.random.rand(INPUT_DIM, H_DIM) # размерность (INPUT_DIM, H_DIM)
  33. b1 = np.random.rand(1, H_DIM)
  34. W2 = np.random.rand(H_DIM, OUTPUT_DIM)
  35. b2 = np.random.rand(1, OUTPUT_DIM)
  36. W1 = (W1 - 0.5) * 2 * np.sqrt(1 / INPUT_DIM)
  37. b1 = (b1 - 0.5) * 2 * np.sqrt(1 / INPUT_DIM)
  38. W2 = (W2 - 0.5) * 2 * np.sqrt(1 / H_DIM)
  39. b2 = (b2 - 0.5) * 2 * np.sqrt(1 / H_DIM)
  40. ALPHA = 0.001 # скорость обучения
  41. EPOCH = 400 # количество эпох
  42. BATCH = 50
  43. loss_arr = []
  44. for epoh in range(EPOCH):
  45. random.shuffle(dataset) # Перемешивает dataset случайным образом.
  46. for i in range(len(dataset) // BATCH): # итерации происходят не по конкретному batch, а итерируемся по batch-ам
  47. # * - распаковка в аргументы функции
  48. batch_x, batch_y = zip(*dataset[i * BATCH: i * BATCH + BATCH])
  49. x = np.concatenate(batch_x, axis=0) # создаем массив из массивов batch-ов
  50. y = np.array(batch_y)
  51. # Forward
  52. ''' в качестве промежутчных значений мы будем получать не векторы, а матрицы
  53. т.е по сути параллельное вычисление каждого вектора из batch независимо '''
  54. t1 = x @ W1 + b1 # вычисление 1 скрытого слоя
  55. h1 = relu(t1) # функция активации промежу точного выходного слоя
  56. t2 = h1 @ W2 + b2 # вычисление 2 скрытого слоя
  57. z = softmax_batch(t2) # функция активации выходного слоя
  58. E = np.sum(sparse_cross_entropy_batch(z, y)) # ошибка
  59. # Backward
  60. y_full = to_full_batch(y, OUTPUT_DIM) # правильный ответ записываем в ветор той же размерности что и output_dim
  61. ''' вычисление градиентов
  62. dE/dt1 <- dE/dh1 <- dE/dt2 <- E
  63. из dE/dt2 можем получить dE/dW2 и dE/db2
  64. из dE/dt1 можем получить dE/dW1 и dE/db1 '''
  65. dE_dt2 = z - y_full
  66. dE_dW2 = h1.T @ dE_dt2
  67. dE_b2 = np.sum(dE_dt2, axis=0, keepdims=True)
  68. dE_h1 = dE_dt2 @ W2.T
  69. dE_dt1 = dE_h1 * relu_deriv(t1)
  70. dE_dW1 = x.T @ dE_dt1
  71. dE_db1 = np.sum(dE_dt1, axis=0, keepdims=True)
  72. # Update
  73. W1 -= ALPHA * dE_dW1
  74. b1 -= ALPHA * dE_db1
  75. W2 -= ALPHA * dE_dW2
  76. b2 -= ALPHA * dE_b2
  77. loss_arr.append(E)
  78. def predict(x):
  79. t1 = x @ W1 + b1 # @ - матричное умножение
  80. h1 = relu(t1)
  81. t2 = h1 @ W2 + b2
  82. z = softmax(t2)
  83. return z
  84. def calc_accuracy():
  85. correct = 0
  86. for x, y in dataset:
  87. z = predict(x)
  88. y_pred = np.argmax(z)
  89. if y_pred == y:
  90. correct += 1
  91. acc = correct / len(dataset)
  92. return acc
  93. accuracy = calc_accuracy()
  94. print("Accuracy: ", accuracy)
  95. import matplotlib.pyplot as plt
  96. plt.plot(loss_arr)
  97. plt.show()