【发布时间】:2021-11-13 07:42:11
【问题描述】:
我正在从头开始开发神经网络。问题似乎与我的 relu 反向传播有关。当我训练模型时,它有时会输出 -0,有时会输出良好的预测(相对而言)。有人可以告诉我我的反向传播是否不正确,或者我的 relu 预测为 -0 是否有原因?
-- [编辑]
修复了预测 -0 的问题,但现在它只是为 XOR 的所有输入预测 0。有人可以查看我的反向传播吗?
import numpy as np
# Each layer in our neural network
class NeuralLayer:
def __init__(self, input_neurons, output_neurons):
self.weights = np.random.randn(input_neurons, output_neurons)* np.sqrt(2. / input_neurons)
self.bias = np.ones((1,output_neurons)) * 0.5
# Two different activations, sigmoid by default
def sigmoid(self, neurons):
self.act = 1.0/(1.0 + np.exp(-neurons))
return self.act
def sigmoidBackward(self, grad):
return grad * self.act * (1 - self.act)
def relu(self, neurons):
self.act = (neurons > 0)
return neurons * self.act
def reluBackward(self, grad):
return grad * self.act
# Forward pass for this layer
def forward(self, input, activation):
self.input = np.atleast_2d(input)
if activation == 'sigmoid':
return self.sigmoid(input @ self.weights + self.bias)
else:
return self.relu(input @ self.weights + self.bias)
# backward pass for this layer
def backward(self, grad, activation):
if activation == 'sigmoid':
grad = self.sigmoidBackward(np.atleast_2d(grad))
else:
grad = self.reluBackward(np.atleast_2d(grad))
self.grad_weights = np.matmul(self.input.T, grad)
self.grad_bias = grad.sum()
return grad @ self.weights.T
def step(self, step_size):
self.weights -= step_size*self.grad_weights
self.bias -= step_size*self.grad_bias
# Our neural net
class NeuralNetwork:
# Dynamically create all layers
def __init__(self, input_neurons, hidden_neurons, layer_count, activation, output_neurons = 1):
self.activation = activation
# Used to ensure input neurons match inputted data
self.neuron_safety = input_neurons
assert layer_count >= 2 and output_neurons >= 1
# Input layer
self.layers = [NeuralLayer(input_neurons, hidden_neurons)]
# Hidden Layers
for i in range(layer_count - 2):
self.layers.append(NeuralLayer(hidden_neurons, hidden_neurons))
# Output layer
self.layers.append(NeuralLayer(hidden_neurons, output_neurons))
# Forward pass for each layer
def forward(self, inp):
assert inp.shape[0] == self.neuron_safety
for layer in self.layers:
inp = layer.forward(inp, self.activation)
return inp
def backward(self, grad):
for layer in reversed(self.layers):
grad = layer.backward(grad, self.activation)
def step(self, step_size = 0.01):
for layer in self.layers:
layer.step(step_size)
# loss function - only 1 output neuron
def meanSquaredError(self, preds, labels):
self.labels = labels
self.preds = preds
return (self.preds - self.labels)**2
def meanSquaredErrorGrad(self):
return 2 * (self.preds - self.labels)
# Create a neural network with 2 inputs, 2 hidden neurons in each layer, and 2 layers
net = NeuralNetwork(2,16,4, 'relu')
epochs = 5000
# Input data (A,B) for XOR
X = np.array([[0,0],[1,1], [1,0],[0,1]])
# Expected output data
Y = np.array([[0],[0],[1],[1]])
for i in range(epochs):
preds = []
for idx, x in enumerate(X):
predictions = net.forward(x)
preds.append(predictions)
loss = net.meanSquaredError(predictions, Y[idx])
loss_grad = net.meanSquaredErrorGrad()
net.backward(loss_grad)
net.step()
print("Model predicted: {}\nactual values: {} ".format(preds, Y.T))
输出:
Model predicted: [array([[-0.]]), array([[-0.]]), array([[1.]]), array([[-0.]])]
实际值:[[0 0 1 1]]
有时预测是完美的,但大多数时候至少有一个预测是-0
【问题讨论】:
-
从relu函数中,将最后一行
return neurons * self.act改为return np.maximum(neurons, 0)。这可以消除负面影响。 -
这摆脱了 -0 预测,但它仍然没有做出很好的预测。例如,在更改之后,我得到: 模型预测:[array([[0.]]), array([[0.]]), array([[0.]]), array([[0.] ])] 实际值:[[0 0 1 1]] - 因为它只有 4 个点,它不应该大幅过度拟合并预测几乎完美吗?
-
我不知道。我只是快速浏览代码。你没有得到完美的预测可能是因为模型中的随机性。模型陷入局部最小值或其他问题。
-
嗯,感谢您的关注。我不明白,因为使用 sigmoid 我得到了很好的预测,但 relu 没有那么多.. relu 只预测所有结果的 0,但 sigmoid 将非常接近完美。有没有办法调整模型的随机性?
-
我还发现了您的代码使用均方误差的问题,这是回归的损失函数。但是你的目标是 0 和 1,这是二进制的。
标签: python numpy machine-learning neural-network