隐藏层中多个神经元的目的是什么?

数据挖掘 机器学习 神经网络 激活函数
2021-09-20 13:39:03

从表面上看,这听起来是一个非常愚蠢的问题。但是,我花了一天时间在各种来源中寻找答案,但找不到答案。

让我把问题说得更清楚。

以这张经典图片为例:

在此处输入图像描述

显然,输入层是一个包含 3 个分量的向量。这三个分量中的每一个都传播到隐藏层。隐藏层中的每个神经元都看到具有 3 个分量的相同向量——所有神经元都看到相同的数据。

所以我们现在处于隐藏层。根据我的阅读,这一层通常只是 ReLus 或 sigmoid。

如果我错了,请纠正我,但 ReLu 是 ReLu。为什么你需要 4 个完全相同的函数,都看到完全相同的数据?

是什么让隐藏层中的红色神经元彼此不同?他们应该是不同的吗?我还没有读过任何关于调整或设置参数或扰乱不同神经元以使它们不同的任何内容。但如果它们没有不同……那有什么意义呢?

上图下方的文字说:“神经网络实际上只是感知器的组合,以不同的方式连接。” 在我看来,它们都以完全相同的方式联系在一起。

2个回答

为了解释使用您提供的示例神经网络:

  1. 多个输入的目的:每个输入代表输入数据集的一个特征。
  2. 隐藏层的目的:每个神经元学习一组不同的权重来表示输入数据上的不同函数。
  3. 输出层的目的:每个神经元代表一个给定的输出类别(标签/预测变量)。

如果你只使用一个神经元并且没有隐藏层,这个网络将只能学习线性决策边界。为了在对输出进行分类时学习非线性决策边界,需要多个神经元。通过学习逼近输出数据集的不同函数,隐藏层能够降低数据的维数以及识别输入数据的模式复杂表示。如果它们都学习相同的权重,它们将是多余的并且没有用处。

当输入相同的数据时,他们将学习不同的“权重”并因此学习不同的函数的方式是,当使用反向传播来训练网络时,每个神经元的输出表示的误差是不同的。这些错误被反向处理到隐藏层,然后到输入层,以确定将这些错误最小化的权重的最佳值。

这就是为什么在实施反向传播算法时,最重要的步骤之一是在开始学习之前随机初始化权重。如果不这样做,那么你会观察到一个很大的数字。神经元学习完全相同的权重并给出次优结果。


编辑以回答其他问题:

  • 神经元不是冗余的唯一原因是因为它们都用不同的权重集“训练”过,因此,当呈现相同的数据时,会给出不同的输出。这是通过随机初始化和错误的反向传播来实现的。
  • 橙色神经元的输出(以您的图表为例)通过应用 sigmoid 或 Relu 函数与训练的权重和橙色神经元的输出,被每个蓝色神经元“压扁”。

我认为这里的关键是,在训练时,具有相同的权重(以及隐藏层中的相同神经元)不会导致最优解,而是不同的权重会导致实际值和预测值之间的差异较小。

我编写了这个非常愚蠢的神经网络(作为学习练习)。也许它可能会有所帮助。

import numpy as np

class NeuralNetwork(object):
    def __init__(self, X, Y, hidden_layer_dim):
        self.X = X / np.max(X)
        self.Y = Y / np.max(Y) # Used for training
        self.hidden_layer_dim = hidden_layer_dim

    def initialize_weights(self):
        self.w1 = np.random.normal(0,1, (self.X.shape[1], self.hidden_layer_dim))
        self.w2 = np.random.normal(0,1, self.hidden_layer_dim)

    def forward(self, xi):
        """
        x1 is 2d array
        """
        # This method is also used for training 
        xi = xi / np.max(xi)
        z2 = np.dot(xi, self.w1)
        a2 = sigmoid(z2)
        z3 = np.dot(a2, self.w2)
        y_hat = sigmoid(z3)
        return y_hat

    def dump_train(self, n_iterations):
        min_mse = np.inf
        for i in range(n_iterations):
            w1 = np.random.normal(0,1, (self.X.shape[1], self.hidden_layer_dim))
            w2 = np.random.normal(0,1, self.hidden_layer_dim)

            z2 = np.dot(self.X, w1)
            a2 = sigmoid(z2)
            z3 = np.dot(a2, w2)
            y_hat = sigmoid(z3)

            diff = self.Y - y_hat
            mse = np.dot(diff, diff)

            if mse < min_mse:
                min_mse = mse
                print("min_mse: {}, iteration: {}".format(mse, i))
                self.w1 = w1
                self.w2 = w2

def sigmoid(a):
    return 1 / (1 + np.e ** (-a))

if __name__ == "__main__":
    my_x = np.array([[8,5], [7,5], [8,4],[8,1], [4, 3], [5,2], [4,2]], dtype=np.float)
    my_y = np.array([100, 90, 88, 60, 50, 45, 40], dtype=np.float)

    NN = NeuralNetwork(my_x, my_y, hidden_layer_dim=3)
    NN.initialize_weights()
    NN.dump_train(100000)

    new_x = [[8,4], [7,1], [3,3]]

    y_hat = NN.forward(new_x)

    print("prediction: {}".format(y_hat))
    print("weight 1: {}".format(NN.w1))
    print("weight 2: {}".format(NN.w2)) 

结果:

weight 1: [[-0.13787113 -1.30913914  0.64624687]
 [-1.76733779  0.77449265  1.61122177]]
weight 2: [-1.42489674 -1.94360005  2.56365303]

权重不同。