当前位置: 首页 > 知识库问答 >
问题:

反向传播输出趋向于相同的值

阎璞瑜
2023-03-14

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

我正在使用手写数字数据集的光学识别,训练数据看起来像

<代码>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,0,0,7,13,3,0,8,7,0,0,4,12,0,1,13,5,0,0,14,9,0,0,0,0,0,6,14,7,1,0,0,0

它表示一个8x8矩阵,其中64个整数中的每一个都对应于子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包含每层中的节点数,例如。

<代码>层=[64、30、10]

我使用逻辑函数作为激活函数

def logistic(self, z):
        return sp.expit(z)

及其衍生物

def derivative(self, z):
        return sp.expit(z) * (1 - sp.expit(z))

我的反向传播算法是从这里大量借用的;我之前的尝试失败了,所以我想尝试另一条路线。

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函数,或者我的反向传播算法的实现是否失败。我已经用同样的结果重复了两到三次以上的程序,这让我相信我从根本上误解了问题,没有正确地表达它。

共有1个答案

孔征
2023-03-14

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

我认为问题在于我是如何计算输出层中的错误的。我一直将其计算为示例[1]-激活[-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%的准确率。希望这能帮助其他人。

 类似资料:
  • 卷积神经网络其实是神经网络特征学习的一个典型例子。传统的机器学习算法其实需要人工的提取特征,比如很厉害的SVM。而卷积神经网络利用模板算子的参数也用以学习这个特点,把特征也学习出来了。其实不同的模板算子本质上就是抽象了图像的不同方面的特征。比如提取边缘,提取梯度的算子。用很多卷积核去提取,那就是 提取了很多的特征。一旦把参数w,b训练出来,意味着特征和目标之间的函数就被确定。今天分享下CNN的关键

  • 训练发散 理想的分类器应当是除了真实标签的概率为1,其余标签概率均为 0,这样计算得到其损失函数为 -ln(1) = 0 损失函数越大,说明该分类器在真实标签上分类概率越小,性能也就越差。一个非常差的分类器,可能在真实标签上的匪类概率接近于0,那么损失函数就接近于正无穷,我们成为训练发散,需要调小学习速率。 6.9 高原反应 在 ImageNet-1000 分类问题中,初始状态为均匀分布,每个类别

  • 1 正向传播(Forward propagation) 回忆一下,给出一个输入特征$x$的时候,我们定义了$a^{[0]}=x$。然后对于层(layer)$l=1,2,3,\dots,N$,其中的$N$是网络中的层数,则有: $z^{[l]}=W^{[l]}a^{[l-1]}+b^{[l]}$ $a^{[l]}=g^{[l]}(z^{[l]})$ 在讲义中都是假设了非线性特征$g^{[l]}$对除

  • 在使用relu激活功能时,我在实现backprop时遇到问题。我的模型有两个隐藏层,两个隐藏层中都有10个节点,输出层中有一个节点(因此有3个权重,3个偏差)。我的模型不适用于这个断开的backward\u prop函数。但是,该函数使用sigmoid激活函数(作为注释包含在函数中)与backprop一起工作。因此,我认为我把relu推导搞砸了。 谁能把我推向正确的方向?

  • 前面几节里我们使用了小批量随机梯度下降的优化算法来训练模型。在实现中,我们只提供了模型的正向传播(forward propagation)的计算,即对输入计算模型输出,然后通过autograd模块来调用系统自动生成的backward函数计算梯度。基于反向传播(back-propagation)算法的自动求梯度极大简化了深度学习模型训练算法的实现。本节我们将使用数学和计算图(computationa

  • 我正在尝试用RELU实现神经网络。 输入层- 以上是我的神经网络结构。我对这个relu的反向传播感到困惑。对于RELU的导数,如果x 有人能解释一下我的神经网络架构的反向传播“一步一步”吗?