Я пытаюсь создать библиотеку нейронных сетей с нуля (ie не использует Tensorflow), и у меня возникают некоторые проблемы из-за ошибки округления. Код для нейронной сети настроен так, чтобы я мог вводить глубину и высоту нейронной сети. Из-за этого для меня нецелесообразно находить аналитический c градиент для моей функции стоимости. Чтобы обойти это, я выполняю метод конечных разностей, чтобы вычислить частную производную моей функции стоимости по каждому весу и смещению. Тем не менее, большинство из этих производных оцениваются в ноль, что означает, что моя нейронная сеть действительно не меняется в процессе обучения (ну, это так, но не после нескольких сотен эпох или около того).
Мне интересно если есть способ гарантировать более высокую точность для этих типов вычислений, или если есть лучший способ вычислить эти градиенты, которые не приведут к такой низкой точности.
Кроме того, могут быть проблемы с числовыми точность в другом месте в коде (особенно в методе feed_forward), но сейчас я думаю, что мои главные проблемы в градиенте l ie в методе обучения.
Ниже приведены важные части моего кода:
# This is a general purpose neural network library. It will start simple, but features will be added over time.
import numpy as np
np.random.seed(42)
class NeuralNetwork:
def __init__(self, number_of_inputs, number_of_outputs, number_of_hidden_layers=0, height=5,
purpose="classification"):
self.number_of_inputs = number_of_inputs
self.number_of_outputs = number_of_outputs
self.number_of_hidden_layers = number_of_hidden_layers
self.height = height
self.purpose = purpose
# Weights will be entered as an array of matrices (np.arrays). The nth matrix will correspond to the nth layer
# (including the first layer). Thus, there will be number_of_hidden_layers + 1 matrices. The nth row of each
# matrix will correspond to the nth neuron of the next layer.
for i in range(0, number_of_hidden_layers + 1):
if i == 0 and number_of_hidden_layers != 0:
self.weights = [np.random.rand(number_of_inputs, height)]
elif i < number_of_hidden_layers:
self.weights.append(np.random.rand(height, height))
elif number_of_hidden_layers == 0:
self.weights = [np.random.rand(number_of_inputs, number_of_outputs)]
else:
self.weights.append(np.random.rand(height, number_of_outputs))
self.bias = np.random.rand(1, number_of_hidden_layers + 1)
def feed_forward(self, data, weights, bias):
output = self.sigmoid(np.dot(data, weights[0]) + bias[0][0])
for i in range(1, self.number_of_hidden_layers + 1):
output = self.sigmoid(np.dot(output, weights[i]) + bias[0][i])
return output
def train(self, inputs, outputs, epochs, training_rate, derivative_step_size=10**(-5):
new_bias = self.bias.copy()
new_weights = self.weights.copy()
for iteration in range(epochs):
for step in range(len(inputs)):
for entry in range(len(self.weights)):
for i in range(len(self.weights[entry])):
for j in range(len(self.weights[entry][i])):
temp_weights1 = self.weights.copy()
temp_weights2 = self.weights.copy()
temp_weights1[entry][i][j] = self.weights[entry][i][j] + derivative_step_size
temp_weights2[entry][i][j] = self.weights[entry][i][j] - derivative_step_size
derivative = ((self.error(np.array(inputs[step]), outputs, temp_weights1, self.bias) -
self.error(np.array(inputs[step]), outputs, temp_weights2,
self.bias)))/(2*derivative_step_size)
new_weights[entry][i][j] -= training_rate*derivative[step]
for entry in range(len(self.bias[0])):
temp_bias1 = self.bias.copy()
temp_bias2 = self.bias.copy()
temp_bias1[0][entry] = self.bias[0][entry] + derivative_step_size
temp_bias2[0][entry] = self.bias[0][entry] - derivative_step_size
derivative = ((self.error(np.array(inputs[step]), outputs, self.weights, temp_bias1) -
self.error(np.array(inputs[step]), outputs, self.weights, temp_bias2))
/ (2*derivative_step_size))
new_bias[0][entry] -= training_rate*derivative[step]
self.weights = new_weights.copy()
self.bias = new_bias.copy()
def error(self, inputs, outputs, weights, bias):
return (self.feed_forward(inputs, weights, bias) - outputs)**2
def sigmoid(self, x):
return 1/(1+np.exp(-x))
def relu(self, x):
temp = x
for i in range(len(x)):
if i > 0:
temp[i][0] = x[i][0]
else:
temp[i][0] = 0
return temp
example = NeuralNetwork(3, 1, 1)
# This is the training data
inputs = np.array([[0, 0, 1], [0, 0, 1], [1, 0, 0], [1, 1, 0], [1, 1, 1]])
outputs = np.array([[1], [0], [0], [1], [1]])
example.train(inputs, outputs, 1000, 0.05)
print(np.average(example.error(inputs, outputs, example.weights, example.bias)))