为什么梯度下降不能正常工作?
Why is gradient descent not working properly?
这是我第一次尝试在Python中编码多层神经网络(代码附在下面)。
我很难尝试使用梯度下降偏导数,因为似乎权重没有正确更新。
当我试图预测一个新样本的输出时,我总是得到错误的答案(应该有两个输出值和一个与它们相关的概率;例如:如果一个新样本属于 class 1,它的概率应该大于 0.5 (prob_class1),因此 class 2 有 (1-prob_class1),但代码只产生 [1,1] 或 [-1,-1]对于任何样品)。
我仔细检查了所有的行,我几乎可以肯定这是由于使用梯度下降的一些问题造成的。
有人可以帮我吗?
提前谢谢你。
import numpy as np
import sklearn
from sklearn.linear_model import LogisticRegressionCV
from sklearn.datasets import make_moons
import matplotlib.pyplot as plt
np.random.seed(0)
x, y = sklearn.datasets.make_moons(200, noise=0.20)
plt.scatter(x[:,0], x[:,1], s=40, c=y, cmap=plt.cm.Spectral)
y = y.reshape(-1,1)
N = x.shape[0]
n_input = min(x.shape)
n_output = 2
n_hidden = max(n_input,n_output) + 20 # 20 is arbitrary
n_it = 10000
alpha = 0.01
def predict(model,xn):
W1, b1, W2, b2, W3, b3 = model['W1'], model['b1'], model['W2'], model['b2'],model['W3'], model['b3']
z1 = W1.dot(xn) + b1
a1 = np.tanh(z1)
z2 = a1.dot(W2) + b2
a2 = np.tanh(z2)
z3 = a2.dot(W3) + b3
a3 = np.tanh(z3)
return a3
model = {}
W1 = np.random.randn(n_input,n_input)
b1 = np.random.randn(1,n_input)
W2 = np.random.randn(n_input,n_hidden)
b2 = np.random.randn(1,n_hidden)
W3 = np.random.randn(n_hidden,n_output)
b3 = np.random.randn(1,n_output)
for i in range(n_it):
# Feedforward:
z1 = x.dot(W1) + b1
a1 = np.tanh(z1)
z2 = a1.dot(W2) + b2
a2 = np.tanh(z2)
z3 = a2.dot(W3) + b3
a3 = np.tanh(z3)
# Loss function:
# f(w,b) = (y - (w*x + b)^2)
# df/dw = -2*(1/N)*x*(y - (w*x + b))
# df/db = -2*(1/N)*(y - (w*x + b))
# Backpropagation:
dW3 = -2*(1/N)*(a2.T).dot(y-a3)
db3 = -2*(1/N)*sum(y-a3)
db3 = db3.reshape(-1,1)
db3 = db3.T
dW2 = -2*(1/N)*a1.T.dot(a2)
db2 = -2*(1/N)*sum(a2)
db2 = db2.reshape(-1,1)
db2 = db2.T
dW1 = -2*(1/N)*(x.T).dot(a1)
db1 = -2*(1/N)*sum(dW1)
db1 = db1.reshape(-1,1)
db1 = db1.T
# Updating weights
W3 += alpha*dW3
b3 += alpha*db3
W2 += alpha*dW2
b2 += alpha*db2
W1 += alpha*dW1
b1 += alpha*db1
model = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2, 'W3':W3, 'b3':b3}
test = np.array([2,0])
prediction = predict(model,test)
看着你的代码,我想到了一些事情:
首先,您没有使用链式法则来计算反向传播。如果您想对此有一些直观的了解,可以观看 Andrej Karpathy https://www.youtube.com/watch?v=i94OvYb6noo 的精彩 class,但也有大量在线资源。也许从 1 个隐藏层开始(这里有 2 个),因为它使事情变得容易得多。
其次,你还应该在反向传播中使用你的 tanh 的导数(你在前向传播中这样做,所以也应该反过来做)。
最后,为什么要有两个输出节点?在我看来,在这种情况下 output_1 = 1 - output_2 。或者,如果您希望两个输出分别计算,则需要在最后对它们进行归一化以获得属于 class 1 或 2.
的概率
这是我第一次尝试在Python中编码多层神经网络(代码附在下面)。 我很难尝试使用梯度下降偏导数,因为似乎权重没有正确更新。 当我试图预测一个新样本的输出时,我总是得到错误的答案(应该有两个输出值和一个与它们相关的概率;例如:如果一个新样本属于 class 1,它的概率应该大于 0.5 (prob_class1),因此 class 2 有 (1-prob_class1),但代码只产生 [1,1] 或 [-1,-1]对于任何样品)。 我仔细检查了所有的行,我几乎可以肯定这是由于使用梯度下降的一些问题造成的。 有人可以帮我吗? 提前谢谢你。
import numpy as np
import sklearn
from sklearn.linear_model import LogisticRegressionCV
from sklearn.datasets import make_moons
import matplotlib.pyplot as plt
np.random.seed(0)
x, y = sklearn.datasets.make_moons(200, noise=0.20)
plt.scatter(x[:,0], x[:,1], s=40, c=y, cmap=plt.cm.Spectral)
y = y.reshape(-1,1)
N = x.shape[0]
n_input = min(x.shape)
n_output = 2
n_hidden = max(n_input,n_output) + 20 # 20 is arbitrary
n_it = 10000
alpha = 0.01
def predict(model,xn):
W1, b1, W2, b2, W3, b3 = model['W1'], model['b1'], model['W2'], model['b2'],model['W3'], model['b3']
z1 = W1.dot(xn) + b1
a1 = np.tanh(z1)
z2 = a1.dot(W2) + b2
a2 = np.tanh(z2)
z3 = a2.dot(W3) + b3
a3 = np.tanh(z3)
return a3
model = {}
W1 = np.random.randn(n_input,n_input)
b1 = np.random.randn(1,n_input)
W2 = np.random.randn(n_input,n_hidden)
b2 = np.random.randn(1,n_hidden)
W3 = np.random.randn(n_hidden,n_output)
b3 = np.random.randn(1,n_output)
for i in range(n_it):
# Feedforward:
z1 = x.dot(W1) + b1
a1 = np.tanh(z1)
z2 = a1.dot(W2) + b2
a2 = np.tanh(z2)
z3 = a2.dot(W3) + b3
a3 = np.tanh(z3)
# Loss function:
# f(w,b) = (y - (w*x + b)^2)
# df/dw = -2*(1/N)*x*(y - (w*x + b))
# df/db = -2*(1/N)*(y - (w*x + b))
# Backpropagation:
dW3 = -2*(1/N)*(a2.T).dot(y-a3)
db3 = -2*(1/N)*sum(y-a3)
db3 = db3.reshape(-1,1)
db3 = db3.T
dW2 = -2*(1/N)*a1.T.dot(a2)
db2 = -2*(1/N)*sum(a2)
db2 = db2.reshape(-1,1)
db2 = db2.T
dW1 = -2*(1/N)*(x.T).dot(a1)
db1 = -2*(1/N)*sum(dW1)
db1 = db1.reshape(-1,1)
db1 = db1.T
# Updating weights
W3 += alpha*dW3
b3 += alpha*db3
W2 += alpha*dW2
b2 += alpha*db2
W1 += alpha*dW1
b1 += alpha*db1
model = { 'W1': W1, 'b1': b1, 'W2': W2, 'b2': b2, 'W3':W3, 'b3':b3}
test = np.array([2,0])
prediction = predict(model,test)
看着你的代码,我想到了一些事情:
首先,您没有使用链式法则来计算反向传播。如果您想对此有一些直观的了解,可以观看 Andrej Karpathy https://www.youtube.com/watch?v=i94OvYb6noo 的精彩 class,但也有大量在线资源。也许从 1 个隐藏层开始(这里有 2 个),因为它使事情变得容易得多。
其次,你还应该在反向传播中使用你的 tanh 的导数(你在前向传播中这样做,所以也应该反过来做)。
最后,为什么要有两个输出节点?在我看来,在这种情况下 output_1 = 1 - output_2 。或者,如果您希望两个输出分别计算,则需要在最后对它们进行归一化以获得属于 class 1 或 2.
的概率