【问题标题】:Backpropagation outputs tend towards same value反向传播输出趋向于相同的值
【发布时间】:2016-02-16 01:31:40
【问题描述】:

我正在尝试创建一个多层前馈反向传播神经网络来识别手写数字,但我遇到了一个问题,即我的输出层中的激活都趋向于相同的值。

我正在使用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

无论我为我的学习率、隐藏节点数或隐藏层数选择什么,一切似乎都趋于 1。这让我想知道我是否正确地处理和设置了问题,64输入到 10 个输出,或者我是否正确选择/实现了我的 sigmoid 函数,或者失败是否在我的反向传播算法的实现中。我已经用同样的结果重新创建了上述程序两到三遍,这让我相信我从根本上误解了这个问题并且没有正确地表达它。

【问题讨论】:

  • 能否告诉我训练数据格式示例。
  • 哎呀,我在我的 OP 中调用了训练数据测试数据。它看起来像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。我正在使用的测试和训练数据可以在archive.ics.uci.edu/ml/machine-learning-databases/optdigitsoptdigits.traoptsdigits.tes 中找到。

标签: python algorithm backpropagation training-data


【解决方案1】:

我想我已经回答了我的问题。

我认为问题在于我如何计算输出层中的错误。我一直将其计算为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% 的准确度。希望这对其他人有帮助。

【讨论】:

    猜你喜欢
    • 2013-08-05
    • 2015-01-13
    • 2011-12-11
    • 2014-06-22
    • 1970-01-01
    • 2013-02-05
    • 2018-10-24
    • 2020-07-27
    • 1970-01-01
    相关资源
    最近更新 更多