我正在尝试用Python实现一个带有一个隐藏层的基本XOR神经网络。我特别不理解反向传播算法,所以我卡在了计算delta2和更新权重上…能帮帮我吗?
import numpy as np
def sigmoid(x):
return 1.0 / (1.0 + np.exp(-x))
vec_sigmoid = np.vectorize(sigmoid)
theta1 = np.matrix(np.random.rand(3,3))
theta2 = np.matrix(np.random.rand(3,1))
def fit(x, y, theta1, theta2, learn_rate=.001):
# 前向传播
layer1 = np.matrix(x, dtype='f')
layer1 = np.c_[np.ones(1), layer1]
layer2 = vec_sigmoid(layer1*theta1)
layer3 = sigmoid(layer2*theta2)
# 反向传播
delta3 = y - layer3
delta2 = (theta2*delta3) * np.multiply(layer2, 1 - layer2) #??
# 更新权重
theta2 += learn_rate * delta3 #??
theta1 += learn_rate * delta2 #??
def train(X, Y):
for _ in range(10000):
for i in range(4):
x = X[i]
y = Y[i]
fit(x, y, theta1, theta2)
X = [(0,0), (1,0), (0,1), (1,1)]
Y = [0, 1, 1, 0]
train(X, Y)
回答:
好的,首先,这里是修改后的代码,让你的代码能够工作。
#! /usr/bin/python
import numpy as np
def sigmoid(x):
return 1.0 / (1.0 + np.exp(-x))
vec_sigmoid = np.vectorize(sigmoid)
# Binesh - 只是清理一下代码,这样你可以轻松更改隐藏层的数量。
# 同时,使用Yoshua Bengio的启发式初始化。
# 在很多地方,你混用了矩阵乘法和逐元素乘法... 你不能这样做..(所以我明确地将所有内容改为点积和乘法,以便更清晰。)
input_sz = 2;hidden_sz = 3;output_sz = 1;
theta1 = np.matrix(0.5 * np.sqrt(6.0 / (input_sz+hidden_sz)) * (np.random.rand(1+input_sz,hidden_sz)-0.5))
theta2 = np.matrix(0.5 * np.sqrt(6.0 / (hidden_sz+output_sz)) * (np.random.rand(1+hidden_sz,output_sz)-0.5))
def fit(x, y, theta1, theta2, learn_rate=.1):
# 前向传播
layer1 = np.matrix(x, dtype='f')
layer1 = np.c_[np.ones(1), layer1]
# Binesh - 对于layer2,我们需要添加一个偏置项。
layer2 = np.c_[np.ones(1), vec_sigmoid(layer1.dot(theta1))]
layer3 = sigmoid(layer2.dot(theta2))
# 反向传播
delta3 = y - layer3
# Binesh - 实际上,这是交叉熵函数对最终sigmoid函数输入的_负_导数。
delta2 = np.multiply(delta3.dot(theta2.T), np.multiply(layer2, (1-layer2)))
# Binesh - 我们实际上不使用偏置项的delta。(这有什么意义呢?
# 它没有输入。因此下面这行代码。
delta2 = delta2[:,1:]
# 但,delta只是sigmoid输入的导数。
# 我们不会直接将这些加到theta上。我们必须将这些乘以
# 前一层以获得theta2d和theta1d
theta2d = np.dot(layer2.T, delta3)
theta1d = np.dot(layer1.T, delta2)
# 更新权重
# Binesh - 这里你使用了delta3和delta2... 这些不是
# theta的导数,它们是sigmoid输入的导数..(如上所述)
theta2 += learn_rate * theta2d #??
theta1 += learn_rate * theta1d #??
def train(X, Y):
for _ in range(10000):
for i in range(4):
x = X[i]
y = Y[i]
fit(x, y, theta1, theta2)
# Binesh - 这里是一个小测试函数,用来查看它是否真的工作
def test(X):
for i in range(4):
layer1 = np.matrix(X[i],dtype='f')
layer1 = np.c_[np.ones(1), layer1]
layer2 = np.c_[np.ones(1), vec_sigmoid(layer1.dot(theta1))]
layer3 = sigmoid(layer2.dot(theta2))
print "%d xor %d = %.7f" % (layer1[0,1], layer1[0,2], layer3[0,0])
X = [(0,0), (1,0), (0,1), (1,1)]
Y = [0, 1, 1, 0]
train(X, Y)
# Binesh - 好吧,让我们看看!
test(X)