Machine Learning
  • Introduction
  • 机器学习
    • 前言
      • 符号表
    • 监督式学习
      • 感知机
        • 感知机模型
        • 感知机学习算法
        • 算法python实现
      • Logistic回归
        • Logistic分布
        • Logistic回归模型
        • 算法python实现
      • 线性回归
        • 线性回归模型
        • 算法python实现
      • K近邻法
        • k近邻模型
        • kd树方法
        • kd树python实现
        • knn实例
      • 朴素贝叶斯法
        • 模型和原理
        • 参数估计
        • 算法和实现
      • 决策树
        • 模型与学习
        • 特征选择
        • 生成算法和剪枝
        • python实现
      • 支持向量机
    • 神经网络
      • 神经元模型和感知机
      • 神经网络
      • 神经网络的矩阵表达
      • 反向传播算法
        • 算法证明
        • 算法代码
        • 基于矩阵的计算
      • 改进神经网络的学习方法
        • 交叉熵代价函数
        • softmax
        • regularization
        • 权重初始化
      • 卷积神经网络
        • 基本介绍
    • 数学基础
      • 线性代数
        • 特征值和特征向量
      • 概率统计
        • 随机变量的特征
        • 样本统计量
        • 先验后验概率
      • 微积分
        • 向量内积
        • 方向导数和梯度
        • 梯度下降法
      • 信息论
        • 熵
        • 相对熵和交叉熵
        • 条件熵
        • 互信息
Powered by GitBook
On this page
  • 权重初始化
  • 改进后的权重初始化代码对比
  1. 机器学习
  2. 神经网络
  3. 改进神经网络的学习方法

权重初始化

PreviousregularizationNext卷积神经网络

Last updated 6 years ago

权重初始化

创建了神经网络之后,我们需要进行权重和偏置的初始化,之前的方式是根据独立高斯随机变量来选择权重和偏置,其被归一化均值为000,标准差为111。

我们来看看这样的初始化的网络。假设我们有一个使用大量输入神经元的网络,比如1000个,假设我们已经使用归一化的高斯分布初始化了连接第一个隐藏层的权重。现在我们将注意力集中在这一层的连接权重上,忽略网络的其他部分。

为了简化,假设我们使用训练输入xxx,其中一半的输入神经元为111,另一半的神经元输入为000,让我们考察隐藏神经元的输入带权和:

z=∑jwjxj+bz=\displaystyle\sum_{j} w_j x_j +bz=j∑​wj​xj​+b

其中500个项消去了,所以zzz是遍历总共501个归一化的高斯随机变量和,其中包含500个权重项和额外的1个偏置项。因此zzz本身是一个均值为0,标准差为501≈22.4\sqrt{501} \approx 22.4501​≈22.4的高斯分布。zzz其实是一个非常宽的高斯分布:

我们可以从图中看出∣z∣|z|∣z∣变得非常大,这样的话,隐藏神经元的输出σ(z)\sigma(z)σ(z)就会接近于111或000,也就表示我们的隐藏神经元会饱和。所以当出现这样的情况时,在权重中进行微小的调整仅仅会给隐藏神经元的激活值带来极其微弱的改变。而这种微弱的改变也会影响剩下的神经元,然后会带来相应的代价函数的改变。结果就是,这些权重在我们进行梯度下降算法时,学习的非常缓慢。

如何避免这种类型的饱和,最终避免学习速度的下降?

假设我们有ninn_{in}nin​个输入权重的神经元,我们会使用均值为000,标准差为1/nin1/\sqrt{n_{in}}1/nin​​的高斯随机分布初始化这些权重。也就是说,我们会向下挤压高斯分布,让我们的神经元更不可能饱和。我们会继续使用均值为0,标准差为1的高斯分布来对偏置进行初始化。有了这些设定,带权和

z=∑jwjxj+bz=\displaystyle\sum_{j} w_j x_j +bz=j∑​wj​xj​+b

仍然是一个均值为0,不过有尖锐峰值的高斯分布。假设我们有500个值为0的输入和500个值为1的输入,那么可以证明zzz是服从均值为0,标准差为3/2=1.22...\sqrt{3/2} = 1.22...3/2​=1.22...的高斯分布。(500∗(1/1000)+1\sqrt{500 * (1/1000) + 1}500∗(1/1000)+1​)

这样的一个神经元不可能饱和,因此也不太可能遇到学习速度下降的问题。

下面是两种方式的比较:

改进后的权重初始化代码对比

    def default_weight_initializer(self):
        """Initialize each weight using a Gaussian distribution with mean 0
        and standard deviation 1 over the square root of the number of
        weights connecting to the same neuron.  Initialize the biases
        using a Gaussian distribution with mean 0 and standard
        deviation 1.

        Note that the first layer is assumed to be an input layer, and
        by convention we won't set any biases for those neurons, since
        biases are only ever used in computing the outputs from later
        layers.

        """
        self.biases = [np.random.randn(y, 1) for y in self.sizes[1:]]
        self.weights = [np.random.randn(y, x)/np.sqrt(x)
                        for x, y in zip(self.sizes[:-1], self.sizes[1:])]

    def large_weight_initializer(self):
        """Initialize the weights using a Gaussian distribution with mean 0
        and standard deviation 1.  Initialize the biases using a
        Gaussian distribution with mean 0 and standard deviation 1.

        Note that the first layer is assumed to be an input layer, and
        by convention we won't set any biases for those neurons, since
        biases are only ever used in computing the outputs from later
        layers.

        This weight and bias initializer uses the same approach as in
        Chapter 1, and is included for purposes of comparison.  It
        will usually be better to use the default weight initializer
        instead.

        """
        self.biases = [np.random.randn(y, 1) for y in self.sizes[1:]]
        self.weights = [np.random.randn(y, x)
                        for x, y in zip(self.sizes[:-1], self.sizes[1:])]

其中 large_weight_initializer 是改进前,default_weight_initializer 是改进后,只是多了除以 np.sqrt(x)