我想实现一个多层感知器(mlp)来解决异或问题。因为我不是一个伟大的科学家,所以很长一段时间以来,我一直在为这个项目绞尽脑汁,我希望能够理解这个项目的每一行。
我将从以下问题开始:
有没有调试神经网络的具体方法?(例如导致预期解决方案的预定义已知权重)
下面的反向传播算法(伪代码)正确吗?
这种算法应该有偏差吗?如果不是,那么偏倚是解决异或问题所必需的吗?如果是的话,偏差应该是每个神经元1个,每层1个还是每个网络1个?
我的python实现正确吗如果不是,是关于反向传播,正向传播,没有偏倚还是其他的?
每一个回应都是非常受欢迎的。这不是“家庭作业”,但如果你很害怕,我会很高兴只有好的提示我仍然没有正确地使用numpy,因为我是一个开发人员,而不是一个科学家,有时会遇到矩阵方程的问题(我目前正在研究)因此,我很难很好地理解我发现的不同实现。
编辑:算法现在运行良好,我将重点介绍伪代码/python实现中存在的不同问题:
理论:
在重量调整时伪代码是错误的(我编辑了代码,用fix标记错误的行)。我在应该使用输入值的地方使用了输出层输出
无偏压、只有一个隐含层的异或问题可以有效地解决。有趣的是,它只对4个或更多的神经元起作用,而对3个神经元不起作用但是,在基准测试之后,添加偏差可以大大加快最佳收敛的时间(5倍或更多)
python实现:
权重是在0和1之间随机初始化的,而不是在-1和1之间,它不能这样工作。
最后,this resource对理解“神经元魔法”有很大帮助。它没有帮助我调试反向传播,但它现在证明,如果没有更多的理论知识,我永远无法使它工作如果,作为我,你更像一个开发人员而不是一个科学家,我强烈建议你去看看。
根据维吉尼·马蒂维特的《开发人员的人工智能》一书,这里是反向传播算法的伪代码(这是一本法国书,对不起,坏的交易):
While stop criteria is not achieved:
Initialize d(i)
For each example:
Compute output value s(i) #1
For each output neuron weight: #2
d(i) = s(i) * (1 - s(i)) * (y(i) - s(i))
EndFor
For each hidden neuron weight:
sum = 0
For each link towards output neuron k:
sum += d(k) * w(i->k)
EndFor
d(i) = o(i) * (1 - o(i)) * sum
EndFor
For each weight of the network:
If link towards output neuron:
w(i) += rate * d(i) * o(i)
Else
w(i) += rate * d(i) * s(i) # WRONG: s(i) should be input(i)
EndIf
EndFor
EndFor
EndWhile
在上面,
d(x)
是delta,o(x)
是隐藏层输出,s(x)
是输出层输出,y(x)
是预期输出,w(x)
是网络权重。我知道第1行是正向传播,第2行(包括)之后的行是反向传播因此,正确的算法可以写成:
While stop criteria is not achieved:
Initialize d(i)
For each example:
output = Forward propagation with example inputs #1
Backpropagation of the error between output and expected output #2
EndFor
EndWhile
我的问题是,该算法似乎与反向传播算法成圆圈,并且权重发生变化,例如,下面是隐藏层的输出:
[Epoch 0, inputs (1.0, 1.0)]: hidden outputs: None
[Epoch 0, inputs (0.0, 0.0)]: hidden outputs: [ 0.7755638 0.64556638 0.68163599]
[Epoch 0, inputs (1.0, 0.0)]: hidden outputs: [ 0.5 0.5 0.5]
[Epoch 0, inputs (0.0, 1.0)]: hidden outputs: [ 0.60747218 0.58975313 0.55246625]
[Epoch 1, inputs (1.0, 1.0)]: hidden outputs: [ 0.68911554 0.55079694 0.62718831]
[Epoch 1, inputs (1.0, 0.0)]: hidden outputs: [ 0.77449528 0.64107552 0.67770194]
[Epoch 1, inputs (0.0, 0.0)]: hidden outputs: [ 0.60728756 0.58957687 0.55230354]
[Epoch 1, inputs (0.0, 1.0)]: hidden outputs: [ 0.5 0.5 0.5]
[Epoch 2, inputs (0.0, 0.0)]: hidden outputs: [ 0.68877278 0.54872848 0.6254074 ]
[Epoch 2, inputs (1.0, 0.0)]: hidden outputs: [ 0.5 0.5 0.5]
[Epoch 2, inputs (1.0, 1.0)]: hidden outputs: [ 0.60700878 0.58812487 0.5509695 ]
[Epoch 2, inputs (0.0, 1.0)]: hidden outputs: [ 0.77344667 0.63591436 0.67311723]
[Epoch 3, inputs (0.0, 0.0)]: hidden outputs: [ 0.68856723 0.54708942 0.62400827]
[Epoch 3, inputs (1.0, 0.0)]: hidden outputs: [ 0.5 0.5 0.5]
按随机顺序排列示例不会改变任何内容。此外,我尝试了所有的学习率(0.05到0.95),结果都是一样的,所以我认为这并不是因为收敛性差以下是我的python实现:
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def dsigmoid(y):
return y * (1.0 - y)
class NeuralNetwork:
def __init__(self, nb_inputs, nb_hidden, nb_outputs, learning_rate):
self.nb_inputs = nb_inputs
self.nb_hidden = nb_hidden
self.nb_outputs = nb_outputs
self.learning_rate = learning_rate
self.output_deltas = None
self.output_weights = np.random.random((nb_outputs, nb_hidden)) # WRONG: should be between -1 and 1, not 0 and 1
self.outputs = None
self.hidden_deltas = None
self.hidden_weights = np.random.random((nb_hidden, nb_inputs)) # WRONG: should be between -1 and 1, not 0 and 1
self.hidden_outputs = None
def forward_propagation(self, inputs):
self.hidden_outputs = np.zeros((self.nb_hidden,))
self.outputs = np.zeros((self.nb_outputs,))
# get outputs for hidden layer
for i in range(self.nb_hidden):
aggregated = sum([inputs[j] * self.hidden_weights[i][j] for j in range(self.nb_inputs)])
self.hidden_outputs[i] = sigmoid(aggregated)
# get inputs for output layer
for i in range(self.nb_outputs):
aggregated = sum([self.hidden_outputs[j] * self.output_weights[i][j] for j in range(self.nb_hidden)])
self.outputs[i] = sigmoid(aggregated)
def backpropagation(self, expected_outputs):
# find deltas for output layer
for i in range(self.nb_outputs):
for j in range(self.nb_hidden):
self.output_deltas[i][j] = dsigmoid(self.outputs[i]) * (expected_outputs[i] - self.outputs[i])
# find deltas for hidden layer
for i in range(self.nb_hidden):
for j in range(self.nb_inputs):
total = 0.0
for k in range(self.nb_outputs):
total += self.output_deltas[k][i] * self.output_weights[k][i]
self.hidden_deltas[i][j] = dsigmoid(self.hidden_outputs[i]) * total
# change weights for output layer
for i in range(self.nb_outputs):
for j in range(self.nb_hidden):
self.output_weights[i][j] += self.learning_rate * self.output_deltas[i][j] * self.outputs[i] # WRONG: should be self.hidden_outputs[j]
# change weights for inputs layer
for i in range(self.nb_hidden):
for j in range(self.nb_inputs):
self.hidden_weights[i][j] += self.learning_rate * self.hidden_deltas[i][j] * self.hidden_outputs[i] # WRONG: should be inputs[j]
def train(self, data, nb_iterations):
for i in range(nb_iterations):
# Init deltas
self.output_deltas = np.zeros((self.nb_outputs, self.nb_hidden), dtype=np.float64)
self.hidden_deltas = np.zeros((self.nb_hidden, self.nb_inputs), dtype=np.float64)
# Train on examples with different orders
for inputs, expected_output in sorted(data.items(), key=lambda x: random.random()):
expected_outputs = np.array([expected_output])
self.forward_propagation(inputs)
self.backpropagation(expected_outputs) # WRONG: need inputs: backpropagation(inputs, expected_outputs)
def predict(self, inputs):
self.forward_propagation(inputs)
return self.outputs
最佳答案
很长一段时间以来,我一直在为它伤脑筋,因为我不是一个伟大的人
科学家,我想知道
程序。
你得到我的答案了。继续这样下去,你会发疯的!
免责声明:部分回答我可能会随着时间的推移而改进。
有没有调试神经网络的具体方法?(例如
导致预期解决方案的预定义已知权重)
一般情况下是不可能的。由于权重的数量,在大多数实际情况下几乎是不可能的。您仍然可以尝试监视神经元活动(代码中的aggregated
变量),例如连续两次发送类似的网络输入,看它是否学习,即它越来越接近正确的值。
下面的反向传播算法(伪代码)正确吗?
会去查的。是你的吗?
这种算法应该有偏差吗?如果没有,是否有必要
解决异或问题如果是,偏差应该是
神经元,每层一个还是每个网络一个?
通常每个神经元有一个biais。如果你忽略了它就没问题了。
我的python实现正确吗如果不是,是关于
反向传播、正向传播、无偏压或
其他事?
会检查的没有偏见是可以的。
作为一个脚注,我推荐这本在线“书”:http://neuralnetworksanddeeplearning.com/chap1.html有相当多的数学,不要把时间花在数学上,试着得到概念。我觉得这很有教益。
希望有帮助pltrdy
关于python - 反向传播算法卡在了多层感知器中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42394761/