Я прошел главы 1 и 2 этой книги и попытался написать свой собственный трехслойный NN со ссылками на код, который я получил, когда у меня возникли проблемы.
Вы можно увидеть код ниже для NN. Когда я запускаю его, я получаю неправильную ошибку измерения для точечного произведения в строке:
dw[-1] = np.dot(np.asmatrix(db[-1]), np.asmatrix(self.a[-2]).transpose()).
Это третье последнее уравнение в нижней части вопроса.
ValueError : формы (1,10) и (16,1) не выровнены: 10 (тусклый 1)! = 16 (тусклый 0).
Я не вижу, где я ошибся в Реализация
Из структуры сети я могу заранее определить, какие размеры матриц следует ожидать для параметров, используемых для расчетов. т.е. количество нейронов в слоях 1, 2 и 3: n = 784, 16, 10
. Весовые матрицы в слоях 2 и 3: w = [16, 784], [10, 16]
. Векторы смещения для слоев 2 и 3: b = [16, 1], [10, 1]
. Взвешенные итоговые входные данные для слоев 2 и 3: z = [16, 1], [10, 1]
. Векторы градиента для весов: dw = [16, 784], [10, 16]
и векторы градиента для смещений: db = [16, 1], [10, 1]
. Размеры для выходных массивов активации для слоев 1, 2 и 3 будут: a = [784, 1], [16, 1], [10, 1]
Чтобы продолжить, если перечисленные выше размеры матрицы верны, а уравнения, которые я использую, представленные внизу, верны, я Должен быть в состоянии обучить сеть, если уравнения реализованы правильно.
Если у меня возникли проблемы с работой точечного продукта выше из-за несоответствия размеров, я уверен, что в программе больше ошибок. Если кто-то может просто просмотреть код и уравнения, чтобы указать на ошибки, я был бы очень благодарен.
import random
import numpy as np
class NeuralNetwork:
def __init__(self, inputs, targets, hidden, n_outputs, learning_rate, epochs, batch_size):
# training and testing data
self.training_inputs = inputs # network inputs
self.targets = targets # target outputs for the training data
self.n_data = len(self.training_inputs) # number of training data
# network structure
self.n_inputs = len(self.training_inputs[0]) # number of input nodes
self.hidden_layers = hidden # list containing the number of neurons in each hidden layer. Layer number is the index.
self.n_outputs = n_outputs # number of outputs in the final layer
n_nuerons = [[self.n_inputs], self.hidden_layers, [self.n_outputs]]
self.layers = [x for s in n_nuerons for x in s] # list of the number of neurons in each layer. Layer number is the index
self.n_layers = len(self.layers) # number of layers in the network
# hyperparameters
self.learning_rate = learning_rate
self.epochs = epochs
self.batch_size = batch_size # batching is not implemented yet.. using online learning
# initialise matrices
self.b, self.z = [], []
for neurons in self.layers[1:]: # loop through all layers except the input network layer
self.b.append(np.random.randn(neurons)) # biases
self.z.append(np.zeros(neurons)) # layer weighted sum inputs
self.a = [np.zeros(n) for n in self.layers] # activation outputs - including inputs to network as activation outputs for layer 0
self.w = [np.random.rand(self.layers[i + 1], self.layers[i]) - 0.5 for i in range(self.n_layers - 1)] # weights
self.train()
def train(self):
for epoch in range(self.epochs):
random.shuffle(self.training_inputs)
sum_error = 0
for index in range(self.n_data):
# forward pass
x = self.training_inputs[index]
self.a[0] = x
outputs = self.feedforward(x)
sum_error += sum(self.cost(outputs, index))
# backward pass
dw, db = self.backpropagation(index)
self.update_weights(dw, db)
print('>epoch=%d, error=%.3f' % (epoch, sum_error))
def feedforward(self, output):
for layer in range(self.n_layers - 1):
self.z[layer] = np.dot(self.w[layer], self.a[layer]) + self.b[layer] # layer inputs
self.a[layer + 1] = self.sigmoid(self.z[layer]) # output activations
return self.a[-1]
def backpropagation(self, index):
# initialise gradient matrices
dw = [np.zeros(w.shape) for w in self.w]
db = [np.zeros(n) for n in self.layers[1:]]
# loop backwards through network layers
for i in reversed(range(1, self.n_layers)):
if i == self.n_layers - 1:
# output layer
db[-1] = (self.a[-1] - self.targets[index]) * self.sp(self.z[-1])
dw[-1] = np.dot(np.asmatrix(db[-1]), np.asmatrix(self.a[-2]).transpose())
else:
# all other layers
# NOTE: to compute the weight gradient vector for hidden layer 1 the inputs to the network are used as activation outputs
db[i - 1] = np.multiply(np.dot(np.transpose(self.w[i]), db[i]), self.sp(self.z[i - 1]))
dw[i - 1] = np.dot(np.asmatrix(db[i - 1]), np.asmatrix(self.a[i - 2]).transpose())
return dw, db
def update_weights(self, dw, db):
self.w = np.array([w - self.learning_rate * nw for w, nw in zip(self.w, dw)])
self.b = np.array([b - self.learning_rate * nb for b, nb in zip(self.b, db)])
def cost(self, outputs, index):
return (self.targets[index] - outputs) ** 2
@staticmethod
def sigmoid(z):
return 1 / (1 + np.exp(-z))
@staticmethod
def sp(z):
return z * (1.0 - z)
# Program driver
if __name__ == '__main__':
data = np.load('mnist.npz')
(training_images, test_images) = data['x_train'], data['x_test']
(training_labels, test_labels) = data['y_train'], data['y_test']
n_outputs = 10
training_inputs = np.array([data.flatten() / 255 for data in training_images])
training_targets = []
for i in range(len(training_labels)):
training_targets.append([1 if training_labels[i] == x else 0 for x in range(n_outputs)])
nn = nn.NeuralNetwork(training_inputs, np.array(training_targets), [16], n_outputs, learning_rate=0.1, epochs=10, batch_size=100)
Код включен github с включенным мнистом для всех, кому это может понадобиться. Любые комментарии, исправления, критика, все и вся приветствуются с целью изучения .. Спасибо!