import numpy as np
from keras.datasets import mnist
import matplotlib.pyplot as plt
(train_X, train_y), (test_X, test_y) = mnist.load_data()
SIZE = train_X.shape[1] # высота картинки
# линеаризируем входные данные
train_X = train_X.reshape(-1, SIZE*SIZE)
test_X = test_X.reshape(-1, SIZE*SIZE)
# масштабируем данные, чтобы значения лежали между 0 и 1:
train_X = train_X / 255
test_X = test_X / 255
class Layer:
def __init__(self, neuron_number, weight_number):
self.neuronList = np.random.sample((neuron_number, weight_number))
self.b = np.random.sample(neuron_number)
def sigmoid(self, s, alpha=0.1):
return 1 / (1 + np.exp(-alpha*s))
def change_weight(self, subtracted_weight, neuron_number):
self.neuronList[neuron_number] -= subtracted_weight
def change_b(self, subtracted_b, b_number):
self.b[b_number] -= subtracted_b
def feedForward(self, input_data, neuron_number):
s = np.dot(self.neuronList[neuron_number], input_data) + self.b[neuron_number]
return self.sigmoid(s)
def layerOutPuts(self, data):
length = self.neuronList.shape[0]
self.outputs = np.zeros(length)
for i in range(length):
self.outputs[i] = self.feedForward(data, i)
class Network:
def __init__(self, network_data):
self.layerList = []
for i in range(1, len(network_data)):
neuron_number = network_data[i]
weight_number = network_data[i - 1]
self.layerList.append(Layer(neuron_number, weight_number))
def deriv_sigmoid(self, y):
return y * (1 - y)
def trueDataConvert(self, a):
y_true_convert = [
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
]
return y_true_convert[a]
def answer(self, input_datas, y_trues):
for input_data, y_true in zip(input_datas, y_trues):
for i in range(len(self.layerList)):
if i == 0:
self.layerList[i].layerOutPuts(input_data)
else:
self.layerList[i].layerOutPuts(self.layerList[i-1].outputs)
y_pred = self.layerList[len(self.layerList) - 1].outputs
print('Ответ: ', np.argmax(y_pred))
print('Правильный ответ: ',y_true)
#обучение
def fit(self, input_datas, y_trues):
learn_rate = 0.1
epochs = 3
for epoch in range(epochs):
loses = []
print()
for input_data, y_true in zip(input_datas, y_trues):
y_true = np.array(self.trueDataConvert(y_true))
#данные идут на вход
for i in range(len(self.layerList)):
#первый слой
if i == 0:
self.layerList[i].layerOutPuts(input_data)
#оcтальные слой
else:
self.layerList[i].layerOutPuts(self.layerList[i-1].outputs)
#выходы нейросети
y_pred = self.layerList[len(self.layerList) - 1].outputs
d_L_d_ypred = 2/10 * (y_pred - y_true)
#потери
loses = np.append(loses, ((y_true - y_pred) ** 2).mean())
d_th_list= [] #tetha скрытого слоя
#обратный проход
for i in range(len(self.layerList) - 1, -1, -1):
#последний слой
if i == len(self.layerList) - 1:
#проход по нейронам
for j in range(self.layerList[i].neuronList.shape[0]):
subtracted_weight = learn_rate * self.layerList[i - 1].outputs * d_L_d_ypred[j] * self.deriv_sigmoid(y_pred[j])
self.layerList[i].change_weight(subtracted_weight, j)
subtracted_b = learn_rate * d_L_d_ypred[j] * self.deriv_sigmoid(y_pred[j])
self.layerList[i].change_b(subtracted_b, j)
#скрытые слои
elif i != 0:
#проход по нейронам
for j in range(self.layerList[i].neuronList.shape[0]):
#веса следующего слоя
next_layer_weights = np.array(self.layerList[i+1].neuronList[:, j])
d_th_list.append(np.dot(d_L_d_ypred * self.deriv_sigmoid(y_pred), next_layer_weights) * self.deriv_sigmoid(self.layerList[i].outputs[j]))
subtracted_weight = learn_rate * self.layerList[i - 1].outputs * d_th_list[j]
self.layerList[i].change_weight(subtracted_weight, j)
subtracted_b = learn_rate * d_th_list[j]
self.layerList[i].change_b(subtracted_b, j)
#входной слой
else:
for j in range(self.layerList[i].neuronList.shape[0]):
#веса следующего слоя
next_layer_weights = np.array(self.layerList[i+1].neuronList[:, j])
subtracted_weight = learn_rate * input_data * np.dot(next_layer_weights, d_th_list) * self.deriv_sigmoid(self.layerList[i].outputs[j])
self.layerList[i].change_weight(subtracted_weight, j)
subtracted_b = learn_rate * np.dot(next_layer_weights, d_th_list) * self.deriv_sigmoid(self.layerList[i].outputs[j])
self.layerList[i].change_b(subtracted_b, j)
#построение графика потерь
x = range(100)
plt.grid(True)
plt.plot(x,
loses,
'bo-',
label='Train losses')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(loc='upper right')
#задаем нейросеть в 3 слоя
network_data = [784, 32, 16, 10]
nt = Network(network_data)
new_train_x = train_X[:100]
new_train_y = train_y[:100]
nt.fit(new_train_x, new_train_y)
#nt.answer(new_train_x, new_train_y)