向量的反向传播和形状不适合
Backpropagation and shapes of vectors not fitting
这可能是一个愚蠢的问题,但我有点卡住了。我正在尝试在 Python 中编写一个简单的前馈神经网络。我的输入层、权重层和输出层声明如下:
self.inp = np.zeros(21)
self.weights1 = np.random.rand(self.inp.shape[0],15)
self.weights2 = np.random.rand(15, 15)
self.layer1 = self.sigmoid(np.dot(self.inp, self.weights1))
self.output = self.sigmoid(np.dot(self.layer1, self.weights2))
现在我正在尝试反向传播,但我的向量大小不合适。这是我的反向传播函数:
def backpropagate(self, dice, board):
y = argmax(dice, self.moves)
d_weights2 = np.dot(self.layer1.T, (2*(y - self.output) * self.sigmoidDerivative(self.output)))
d_weights1 = np.dot(self.inp.T, (np.dot(2*(y - self.output) * self.sigmoidDerivative(self.output), self.weights2.T) * self.sigmoidDerivative(self.layer1)))
self.weights1 += d_weights1
self.weights2 += d_weights2
计算 d_weights1 时出现错误。错误是
ValueError: shapes (21,) and (15,) not aligned: 21 (dim 0) != 15 (dim 0)
如何使我的向量适合?
提前致谢!
编辑:
根据要求,这里是完整的 class:
import numpy as np
from TestValues import argmax, testfunctions, zero
class AI:
def __init__(self):
self.moves = []
self.inp = np.zeros(21)
self.weights1 = np.random.rand(self.inp.shape[0],21)
self.weights2 = np.random.rand(21, 15)
self.output = np.zeros(15)
def getPlacement(self, dice, board):
self.feedforward(dice, board)
self.backpropagate(dice, board)
result = self.output
for x in self.moves:
result[x] = -1.
move = np.argmax(result)
self.moves.append(move)
return move
def feedforward(self, dice, board):
i = 0
for x in dice:
self.inp[i] = x
i += 1
for x in board:
self.inp[i] = x
i += 1
self.layer1 = self.sigmoid(np.dot(self.inp, self.weights1))
self.output = self.sigmoid(np.dot(self.layer1, self.weights2))
def backpropagate(self, dice, board):
y = argmax(dice, self.moves)
d_weights2 = np.dot(self.layer1.T, np.dot(2*(y - self.output), self.sigmoidDerivative(self.output)))
d_weights1 = np.dot(self.inp.T, (np.dot(2*(y - self.output) * self.sigmoidDerivative(self.output), self.weights2.T) * self.sigmoidDerivative(self.layer1)))
print(self.weights2.shape)
self.weights1 += d_weights1
self.weights2 += d_weights2
def sigmoid(self, x):
return 1 / (1 + np.exp(-x))
def sigmoidDerivative(self, x):
return self.sigmoid(x) * (1 - self.sigmoid(x))
问题似乎出在您初始化输入的方式上。您正在生成一个形状为 (21,)
的数组,而不是 (1, 21)
。如果您计划一次反向传播许多训练样本,这在某些时候可能会变得很明显。此外,尝试调试这些结果矩阵的形状通常是有益的。例如,我的 d_weights2
是单个标量。如果您不熟悉矩阵代数,它对理解点积以及应该得出的结果非常有帮助。
所以,简单地说,就像这样初始化:
inp = np.zeros((1, 21))
这为我生成了合理的形状。
此外,即使不是 CodeReview,我也不得不对您的代码说几句。不要重复自己。反向传播时,您可以先计算一层的误差,然后在两次更新中使用它。 error = 2*(output - y) * d_logistic(output)
如果您计划将网络扩展到任意大小,而不仅仅是两层,这也会稍微简化一些事情。
还有一件事,你的函数 sigmoid
和 sigmoidDerivative
在 class 中没有用处。考虑让它们成为纯函数,而不是 class 方法。
这可能是一个愚蠢的问题,但我有点卡住了。我正在尝试在 Python 中编写一个简单的前馈神经网络。我的输入层、权重层和输出层声明如下:
self.inp = np.zeros(21)
self.weights1 = np.random.rand(self.inp.shape[0],15)
self.weights2 = np.random.rand(15, 15)
self.layer1 = self.sigmoid(np.dot(self.inp, self.weights1))
self.output = self.sigmoid(np.dot(self.layer1, self.weights2))
现在我正在尝试反向传播,但我的向量大小不合适。这是我的反向传播函数:
def backpropagate(self, dice, board):
y = argmax(dice, self.moves)
d_weights2 = np.dot(self.layer1.T, (2*(y - self.output) * self.sigmoidDerivative(self.output)))
d_weights1 = np.dot(self.inp.T, (np.dot(2*(y - self.output) * self.sigmoidDerivative(self.output), self.weights2.T) * self.sigmoidDerivative(self.layer1)))
self.weights1 += d_weights1
self.weights2 += d_weights2
计算 d_weights1 时出现错误。错误是
ValueError: shapes (21,) and (15,) not aligned: 21 (dim 0) != 15 (dim 0)
如何使我的向量适合?
提前致谢!
编辑:
根据要求,这里是完整的 class:
import numpy as np
from TestValues import argmax, testfunctions, zero
class AI:
def __init__(self):
self.moves = []
self.inp = np.zeros(21)
self.weights1 = np.random.rand(self.inp.shape[0],21)
self.weights2 = np.random.rand(21, 15)
self.output = np.zeros(15)
def getPlacement(self, dice, board):
self.feedforward(dice, board)
self.backpropagate(dice, board)
result = self.output
for x in self.moves:
result[x] = -1.
move = np.argmax(result)
self.moves.append(move)
return move
def feedforward(self, dice, board):
i = 0
for x in dice:
self.inp[i] = x
i += 1
for x in board:
self.inp[i] = x
i += 1
self.layer1 = self.sigmoid(np.dot(self.inp, self.weights1))
self.output = self.sigmoid(np.dot(self.layer1, self.weights2))
def backpropagate(self, dice, board):
y = argmax(dice, self.moves)
d_weights2 = np.dot(self.layer1.T, np.dot(2*(y - self.output), self.sigmoidDerivative(self.output)))
d_weights1 = np.dot(self.inp.T, (np.dot(2*(y - self.output) * self.sigmoidDerivative(self.output), self.weights2.T) * self.sigmoidDerivative(self.layer1)))
print(self.weights2.shape)
self.weights1 += d_weights1
self.weights2 += d_weights2
def sigmoid(self, x):
return 1 / (1 + np.exp(-x))
def sigmoidDerivative(self, x):
return self.sigmoid(x) * (1 - self.sigmoid(x))
问题似乎出在您初始化输入的方式上。您正在生成一个形状为 (21,)
的数组,而不是 (1, 21)
。如果您计划一次反向传播许多训练样本,这在某些时候可能会变得很明显。此外,尝试调试这些结果矩阵的形状通常是有益的。例如,我的 d_weights2
是单个标量。如果您不熟悉矩阵代数,它对理解点积以及应该得出的结果非常有帮助。
所以,简单地说,就像这样初始化:
inp = np.zeros((1, 21))
这为我生成了合理的形状。
此外,即使不是 CodeReview,我也不得不对您的代码说几句。不要重复自己。反向传播时,您可以先计算一层的误差,然后在两次更新中使用它。 error = 2*(output - y) * d_logistic(output)
如果您计划将网络扩展到任意大小,而不仅仅是两层,这也会稍微简化一些事情。
还有一件事,你的函数 sigmoid
和 sigmoidDerivative
在 class 中没有用处。考虑让它们成为纯函数,而不是 class 方法。