python – XOR神经网络收敛到0.5
作者:互联网
我已经实现了以下神经网络来解决Python中的XOR问题.我的神经网络由2个神经元的输入层,2个神经元的隐藏层和1个神经元的输出层组成.我使用Sigmoid函数作为隐藏层的激活函数,使用线性(标识)函数作为输出层的激活函数:
import numpy as np
def sigmoid(z):
return 1/(1+np.exp(-z))
def s_prime(z):
return np.multiply(sigmoid(z), sigmoid(1.0-z))
def init_weights(layers, epsilon):
weights = []
for i in range(len(layers)-1):
w = np.random.rand(layers[i+1], layers[i]+1)
w = w * 2*epsilon - epsilon
weights.append(np.mat(w))
return weights
def fit(X, Y, w, predict=False, x=None):
w_grad = ([np.mat(np.zeros(np.shape(w[i])))
for i in range(len(w))])
for i in range(len(X)):
x = x if predict else X[0]
y = Y[0,i]
# forward propagate
a = x
a_s = []
for j in range(len(w)):
a = np.mat(np.append(1, a)).T
a_s.append(a)
z = w[j] * a
a = sigmoid(z)
if predict: return a
# backpropagate
delta = a - y.T
w_grad[-1] += delta * a_s[-1].T
for j in reversed(range(1, len(w))):
delta = np.multiply(w[j].T*delta, s_prime(a_s[j]))
w_grad[j-1] += (delta[1:] * a_s[j-1].T)
return [w_grad[i]/len(X) for i in range(len(w))]
def predict(x):
return fit(X, Y, w, True, x)
####
X = np.mat([[0,0],
[0,1],
[1,0],
[1,1]])
Y = np.mat([0,1,1,0])
layers = [2,2,1]
epochs = 10000
alpha = 0.5
w = init_weights(layers, 1)
for i in range(epochs):
w_grad = fit(X, Y, w)
print w_grad
for j in range(len(w)):
w[j] -= alpha * w_grad[j]
for i in range(len(X)):
x = X[i]
guess = predict(x)
print x, ":", guess
反向传播似乎都是正确的;我想到的唯一问题是我实施偏差单元的一些问题.无论哪种方式,每次运行代码时,每个输入的所有预测都会收敛到大约0.5.我仔细检查了代码,似乎无法找到错误.任何人都可以指出我的实施有什么问题吗?我感谢任何反馈.
如果由于任何原因它可能有所帮助,这是我得到的那种输出:
[[0 0]] : [[ 0.5]]
[[0 1]] : [[ 0.49483673]]
[[1 0]] : [[ 0.52006739]]
[[1 1]] : [[ 0.51610963]]
解决方法:
您的前向和后向传播的实现或多或少都是正确的.但是,你出错的地方很简单.第一个小错误是查看你的fit函数 – 特别是for循环中的第一个语句:
x = x if predict else X[0]
你要说的是,如果你没有预测(即进行训练),那么在随机梯度下降的每次迭代期间选择的输入例子必须始终是第一个例子,即[0 0](即X [0]).这就是为什么你为所有预测得到0.5的原因,因为你只使用第一个输入进行训练.您需要更改它,以便它读取正确的示例,这是示例i:
x = x if predict else X[i]
您需要做的最后一项更改是您的s_prime函数. sigmoid函数的衍生物确实就是你所拥有的:
def s_prime(z):
return np.multiply(sigmoid(z), sigmoid(1.0-z))
当你计算前向传播时,你已经计算了a_s中每个神经元的输出激活,所以当你计算这些神经元的局部导数时,你直接将输出激活提供给s_prime,所以你不需要计算sigmoid这些再一次.
因此:
def s_prime(z):
return np.multiply(z, 1.0-z)
一旦我做了这两个更改,我们现在得到这个输出:
[[0 0]] : [[ 0.00239857]]
[[0 1]] : [[ 0.99816778]]
[[1 0]] : [[ 0.99816596]]
[[1 1]] : [[ 0.0021052]]
您可以看到,这或多或少与XOR门的预期输出一致.我可以推荐的最后一件事是,根据您当前的代码结构,10000次迭代计算得太长.我注意到,通过上述修正,我们能够以更少的迭代次数达到预期的输出.我已经将迭代次数减少到1000次,并且我将学习率alpha提高到了0.75.改变我们现在得到的这两件事:
[[0 0]] : [[ 0.03029435]]
[[0 1]] : [[ 0.95397528]]
[[1 0]] : [[ 0.95371525]]
[[1 1]] : [[ 0.04796917]]
标签:python,machine-learning,neural-network,backpropagation 来源: https://codeday.me/bug/20190628/1312040.html