反向传播输出趋向于相同的值
Backpropagation outputs tend towards same value
我正在尝试创建一个多层前馈反向传播神经网络来识别手写数字,但我 运行 遇到了一个问题,我的输出层中的激活都趋向于相同的值。
我正在使用 Optical Recognition of Handwritten Digits Data Set,训练数据看起来像
0,1,6,15,12,1,0,0,0,7,16,6,6,10,0,0,0,8,16,2,0,11,2,0,0,5,16,3,0,5,7,0,0,7,13,3,0,8,7,0,0,4,12,0,1,13,5,0,0,0,14,9,15,9,0,0,0,0,6,14,7,1,0,0,0
表示一个8x8矩阵,其中64个整数中的每一个都对应于sub-4x4矩阵中暗像素的数量,最后一个整数是分类。
我在输入层中使用 64 个节点对应 64 个整数,在一定数量的隐藏层中使用一些隐藏节点,在输出层中使用 10 个节点对应 0-9。
这里初始化了我的权重,并为输入层和隐藏层添加了偏差
self.weights = []
for i in xrange(1, len(layers) - 1):
self.weights.append(
np.random.uniform(low=-0.2,
high=0.2,
size=(layers[i-1] + 1, layers[i] + 1)))
# Output weights
self.weights.append(
np.random.uniform(low=-0.2,
high=0.2,
size=(layers[-2] + 1, layers[-1])))
其中list
包含每一层的节点数,例如
layers=[64, 30, 10]
我使用逻辑函数作为我的激活函数
def logistic(self, z):
return sp.expit(z)
及其导数
def derivative(self, z):
return sp.expit(z) * (1 - sp.expit(z))
我的反向传播算法大量借鉴了here;我之前的尝试失败了,所以我想尝试另一条路线。
def back_prop_learning(self, X, y):
# add biases to inputs with value of 1
biases = np.atleast_2d(np.ones(X.shape[0]))
X = np.concatenate((biases.T, X), axis=1)
# Iterate over training set
for epoch in xrange(self.epochs):
# for each weight w[i][j] in network assign random tiny values
# handled in __init__
''' PROPAGATE THE INPUTS FORWARD TO COMPUTE THE OUTPUTS '''
for example in zip(X, y):
# for each node i in the input layer
# set input layer outputs equal to input vector outputs
activations = [example[0]]
# for layer = 1 (first hidden) to output layer
for layer in xrange(len(self.weights)):
# for each node j in layer
weighted_sum = np.dot(activations[layer], self.weights[layer])
# assert number of outputs == number of weights in each layer
assert(len(activations[layer]) == len(self.weights[layer]))
# compute activation of weighted sum of node j
activation = self.logistic(weighted_sum)
# append vector of activations
activations.append(activation)
''' PROPAGATE DELTAS BACKWARDS FROM OUTPUT LAYER TO INPUT LAYER '''
# for each node j in the output layer
# compute error of target - output
errors = example[1] - activations[-1]
# multiply by derivative
deltas = [errors * self.derivative(activations[-1])]
# for layer = last hidden layer down to first hidden layer
for layer in xrange(len(activations)-2, 0, -1):
deltas.append(deltas[-1].dot(self.weights[layer].T) * self.derivative(activations[layer]))
''' UPDATE EVERY WEIGHT IN NETWORK USING DELTAS '''
deltas.reverse()
# for each weight w[i][j] in network
for i in xrange(len(self.weights)):
layer = np.atleast_2d(activations[i])
delta = np.atleast_2d(deltas[i])
self.weights[i] += self.alpha * layer.T.dot(delta)
我在 运行 测试数据后的输出都类似于
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 9.0
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 4.0
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 6.0
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 6.0
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 7.0
无论我 select 的学习率、隐藏节点数或隐藏层数如何,一切似乎都趋向于 1。这让我想知道我是否正在接近并设置问题是否正确,64 个输入到 10 个输出,或者我是否 selected/implemented 我的 sigmoid 函数正确,或者我的反向传播算法的实现是否失败。我重新创建了上述程序两三次,结果相同,这让我相信我从根本上误解了这个问题,没有正确地表达它。
我想我已经回答了我的问题。
我认为问题在于我如何计算输出层中的错误。我一直在计算它作为 errors = example[1] - activations[-1]
,它创建了一个错误数组,这是从目标值中减去我的输出层激活而产生的。
我对此进行了更改,以便我的目标值是零向量 0-9,因此我的目标值的索引是 1.0。
y = int(example[1])
errors_v = np.zeros(shape=(10,), dtype=float)
errors_v[y] = 1.0
errors = errors_v - activations[-1]
我还将我的激活函数更改为 tanh 函数。
这显着增加了我输出层中激活的方差,到目前为止,我在有限的测试中已经能够达到 50% - 75% 的准确率。希望这对其他人有帮助。
我正在尝试创建一个多层前馈反向传播神经网络来识别手写数字,但我 运行 遇到了一个问题,我的输出层中的激活都趋向于相同的值。
我正在使用 Optical Recognition of Handwritten Digits Data Set,训练数据看起来像
0,1,6,15,12,1,0,0,0,7,16,6,6,10,0,0,0,8,16,2,0,11,2,0,0,5,16,3,0,5,7,0,0,7,13,3,0,8,7,0,0,4,12,0,1,13,5,0,0,0,14,9,15,9,0,0,0,0,6,14,7,1,0,0,0
表示一个8x8矩阵,其中64个整数中的每一个都对应于sub-4x4矩阵中暗像素的数量,最后一个整数是分类。
我在输入层中使用 64 个节点对应 64 个整数,在一定数量的隐藏层中使用一些隐藏节点,在输出层中使用 10 个节点对应 0-9。
这里初始化了我的权重,并为输入层和隐藏层添加了偏差
self.weights = []
for i in xrange(1, len(layers) - 1):
self.weights.append(
np.random.uniform(low=-0.2,
high=0.2,
size=(layers[i-1] + 1, layers[i] + 1)))
# Output weights
self.weights.append(
np.random.uniform(low=-0.2,
high=0.2,
size=(layers[-2] + 1, layers[-1])))
其中list
包含每一层的节点数,例如
layers=[64, 30, 10]
我使用逻辑函数作为我的激活函数
def logistic(self, z):
return sp.expit(z)
及其导数
def derivative(self, z):
return sp.expit(z) * (1 - sp.expit(z))
我的反向传播算法大量借鉴了here;我之前的尝试失败了,所以我想尝试另一条路线。
def back_prop_learning(self, X, y):
# add biases to inputs with value of 1
biases = np.atleast_2d(np.ones(X.shape[0]))
X = np.concatenate((biases.T, X), axis=1)
# Iterate over training set
for epoch in xrange(self.epochs):
# for each weight w[i][j] in network assign random tiny values
# handled in __init__
''' PROPAGATE THE INPUTS FORWARD TO COMPUTE THE OUTPUTS '''
for example in zip(X, y):
# for each node i in the input layer
# set input layer outputs equal to input vector outputs
activations = [example[0]]
# for layer = 1 (first hidden) to output layer
for layer in xrange(len(self.weights)):
# for each node j in layer
weighted_sum = np.dot(activations[layer], self.weights[layer])
# assert number of outputs == number of weights in each layer
assert(len(activations[layer]) == len(self.weights[layer]))
# compute activation of weighted sum of node j
activation = self.logistic(weighted_sum)
# append vector of activations
activations.append(activation)
''' PROPAGATE DELTAS BACKWARDS FROM OUTPUT LAYER TO INPUT LAYER '''
# for each node j in the output layer
# compute error of target - output
errors = example[1] - activations[-1]
# multiply by derivative
deltas = [errors * self.derivative(activations[-1])]
# for layer = last hidden layer down to first hidden layer
for layer in xrange(len(activations)-2, 0, -1):
deltas.append(deltas[-1].dot(self.weights[layer].T) * self.derivative(activations[layer]))
''' UPDATE EVERY WEIGHT IN NETWORK USING DELTAS '''
deltas.reverse()
# for each weight w[i][j] in network
for i in xrange(len(self.weights)):
layer = np.atleast_2d(activations[i])
delta = np.atleast_2d(deltas[i])
self.weights[i] += self.alpha * layer.T.dot(delta)
我在 运行 测试数据后的输出都类似于
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 9.0
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 4.0
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 6.0
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 6.0
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 7.0
无论我 select 的学习率、隐藏节点数或隐藏层数如何,一切似乎都趋向于 1。这让我想知道我是否正在接近并设置问题是否正确,64 个输入到 10 个输出,或者我是否 selected/implemented 我的 sigmoid 函数正确,或者我的反向传播算法的实现是否失败。我重新创建了上述程序两三次,结果相同,这让我相信我从根本上误解了这个问题,没有正确地表达它。
我想我已经回答了我的问题。
我认为问题在于我如何计算输出层中的错误。我一直在计算它作为 errors = example[1] - activations[-1]
,它创建了一个错误数组,这是从目标值中减去我的输出层激活而产生的。
我对此进行了更改,以便我的目标值是零向量 0-9,因此我的目标值的索引是 1.0。
y = int(example[1])
errors_v = np.zeros(shape=(10,), dtype=float)
errors_v[y] = 1.0
errors = errors_v - activations[-1]
我还将我的激活函数更改为 tanh 函数。
这显着增加了我输出层中激活的方差,到目前为止,我在有限的测试中已经能够达到 50% - 75% 的准确率。希望这对其他人有帮助。