【发布时间】:2018-10-29 23:42:00
【问题描述】:
我正在构建我的第一个单层感知器网络,并且我正在对其进行训练以模仿具有两个输入的最简单逻辑门(AND 和 OR)的行为。
网络由两个输入节点和一个偏差组成。采用单层感知器的delta-rule学习算法,激活函数为tanh函数。
在 AND 数据集上进行训练时,当给定输入 (1, 1) 时,网络应给出接近 1 的答案,而对于任何其他输入(例如 (0, 1)、(1, 0) 或 (1, 1))给出的答案应为 0。在 OR 数据集上进行训练时,如果给定除 (0, 0) 之外的任何输入,它应该返回接近 1 的答案。
但是它表现出我无法理解的行为。当我在 OR 数据集上训练它时,它收敛得很好(即错误率非常低 - 0.01 或更低):
$ python nn.py
[0 0]: (actual result = [[0.00051257]]). (expected result from training set=0, error rate=[[-0.00051257]])
[0 1]: (actual result = [[0.98865851]]). (expected result from training set=1, error rate=[[0.01134149]])
[1 0]: (actual result = [[0.98865222]]). (expected result from training set=1, error rate=[[0.01134778]])
[1 1]: (actual result = [[0.99993485]]). (expected result from training set=1, error rate=[[6.51512784e-05]])
但是,它在 AND 数据集上不能很好地收敛:
$ python nn.py
[0 0]: (actual result = [[-0.28911014]]). (expected result from training set=0, error rate=[[0.28911014]])
[0 1]: (actual result = [[0.23984154]]). (expected result from training set=0, error rate=[[-0.23984154]])
[1 0]: (actual result = [[0.28911014]]). (expected result from training set=0, error rate=[[-0.28911014]])
[1 1]: (actual result = [[0.68570095]]). (expected result from training set=1, error rate=[[0.31429905]])
我尝试将epoch 调整为500-10000 之间的各种数字,但没有效果。和eta 到0.1 到1.0 之间的任何地方。
查看下面的收敛图,您会看到 OR 数据集的神经网络如何比 AND 数据集收敛得更好,如不断“变薄”的橙色图所示。
我认为 OR 和 AND 门是彼此相反的,如果网络在其中一个上工作,那么它肯定应该在另一个上工作。我在这里错过了什么?
这里附上nn.py的源码。
注意:当您查看时,您会发现我已将权重矩阵初始化为 1,而不是一些随机值。这仅仅是因为我想要一些确定性来帮助我进行故障排除。据我了解,它不应该影响算法的正确性(尽管它可能会使其收敛速度变慢)。
现在,按照@Dennis Soemers 的建议,权重已正确初始化为一些随机值。问题依然存在。
import numpy as np
def tanh(x):
return (1.0 - np.exp(-2*x))/(1.0 + np.exp(-2*x))
def tanh_derivative(x):
return (1 + tanh(x))*(1 - tanh(x))
# AND dataset
training_set = [
(np.array([0, 0]), 0),
(np.array([0, 1]), 0),
(np.array([1, 0]), 0),
(np.array([1, 1]), 1)
]
# # OR dataset
# training_set = [
# (np.array([0, 0]), 0),
# (np.array([0, 1]), 1),
# (np.array([1, 0]), 1),
# (np.array([1, 1]), 1)
# ]
weight = np.random.rand(3, 1)
# fit
eta = 0.2
epoch = 5000
for i in range(0, len(training_set)*epoch):
input_, expected_output = training_set[np.random.randint(0, len(training_set))]
input_with_bias = np.concatenate((input_, np.ones(1))).reshape(3, 1)
sum_weights_of_input = np.dot(input_with_bias.T, weight)
actual_output = tanh(sum_weights_of_input)
error = expected_output - actual_output
delta = np.multiply(eta, np.multiply(error, np.multiply(input_with_bias, tanh_derivative(sum_weights_of_input))))
weight = weight + delta
# print
for input_, expected_output in training_set:
input_with_bias = np.concatenate((input_, np.ones(1))).reshape(3, 1)
actual_output = tanh(np.dot(input_with_bias.T, weight))
error = expected_output - actual_output
print("{}: (actual result = {}). (expected result from training set={}, error rate={})".format(input_, actual_output, expected_output, error))
【问题讨论】:
-
一项改进是在循环结束时更新您的 eta(递减)。另外,这是一个非常简单的例子,所以当你最终得到正确的算法时,你可能不需要 5000 个 epoch,应该最多收敛 20 个 epoch 左右
标签: python machine-learning neural-network perceptron