我正在尝试让我的程序通过神经网络和梯度下降算法学习OR逻辑门。我增加了一个输入神经元为-1,这样我可以稍后调整神经元的激活阈值。目前阈值简单地设为0。以下是我尝试实现的代码
#!/usr/bin/env pythonfrom numpy import *def pcntrain(inp, tar, wei, eta): for data in range(nData): activation = dot(inp,wei) wei += eta*(dot(transpose(inp), target-activation)) print "ITERATION " + str(data) print wei print "TESTING LEARNED ALGO" # Sample input activation = dot(array([[0,0,-1],[1,0,-1],[1,1,-1],[0,0,-1]]),wei) print activationnIn = 2nOut = 1nData = 4inputs = array([[0,0],[0,1],[1,0],[1,1]])target = array([[0],[1],[1],[1]])inputs = concatenate((inputs,-ones((nData,1))),axis=1) #add bias input = -1weights = random.rand(nIn +1,nOut)*0.1-0.05 #random weight if __name__ == '__main__': pcntrain(inputs, target, weights, 0.25)
这段代码似乎生成的输出并不像OR门。请问有什么问题吗?
回答:
如果您修正测试数据为
activation = dot(array([[0,0,-1],[1,0,-1],[1,1,-1],[0,1,-1]]),wei)
(您的代码中0,0出现了两次,而0,1一次都没有),它会产生
[[ 0.30021868] [ 0.67476151] [ 1.0276208 ] [ 0.65307797]]
经过round函数处理后会得到
[[ 0.] [ 1.] [ 1.] [ 1.]]
这正是我们想要的结果。
然而,您确实存在一些小错误:
- 您运行了4次梯度下降(主循环),这是因为您使用输入的数量来指定迭代次数 – 这是不正确的,合理的迭代次数与数据点的数量之间没有关系。如果您运行100次迭代,最终会得到更接近的分数
。
[[ 0.25000001] [ 0.75 ] [ 1.24999999] [ 0.75 ]]
- 您的模型是线性的,输出也是线性的,因此您不能期望它精确地输出0和1,上述结果(0.25, 0.75和1.25)实际上是这种模型的最优解。如果您希望它收敛到漂亮的0/1,您需要在输出中使用sigmoid函数,并相应地使用不同的损失函数和导数(这在机器学习意义上仍然是一个线性模型,您只是在输出上加了一个压缩函数,使其在正确的空间中工作)。
- 您在函数中没有使用”tar”参数,而是引用了全局变量”target”(虽然它们的值相同,但这显然是一个错误)