0%

【深度学习入门】实践课

基于 Python 的理论与实践,从零开始实现深度学习底层的内容。


更新历史

  • 2020.02.18:重新上线
  • 2019.07.30:完成阅读与读后感
  • 2018.11.12:完成第三章
  • 2018.11.09:完成前两章的阅读

读后感

基于 Python 的理论与实践,从零开始实现深度学习底层的内容。通过实现深度学习的过程,来逼近深度学习的本质。

在光看数学式和理论说明无法理解的情况下,可以尝试阅读源代码并运行,很多时候思路都会变得清晰起来。这本书帮助我再次深入理解了 BP,也通过从零实现神经网络了解到了很多细节。

不过这里没有涉及到 RNN 的部分,介绍更多也偏向于图像,少了 NLP 等其他热门领域的介绍。

读书笔记

第一章 Python 入门

所使用的版本和库,通过 Anaconda 安装

  • Python 3.X
  • NumPy
  • Matplotlib

Numpy 常用操作

  • 一维数组 A = np.array([1, 2, 3])
  • 二维数组 B = np.array([[1,2], [3,4]]
  • 矩阵大小 B.shape
  • 矩阵元素类型 B.dtype
  • 转为一维数组 C = B.flatten()

第二章 感知机 Perceptron

感知机接收多个输入信号,输出一个信号。感知机的多个输入信号都有各种固有的权重,这些权重发挥着控制各个信号的重要性的作用。

使用感知机可以表示与门、与非门、或门的逻辑电路。感知机的局限在于它只能表示由一条直线分割的空间,没有办法实现异或门,这也成了神经网络最开始被打压的原因。

异或门可以通过与门、与非门、或门的组合来实现,同样的,我们可以用多层感知机 multi-layered perceptron 来实现异或门。

第三章 神经网络

激活函数 activation function 作用在于决定如何激活输入信号的总和。

感知机中使用阶跃函数作为激活函数,而神经网络使用的是其他函数,常用的有:

  1. sigmoid 函数(非线性函数,这是神经网络的要求,不然多层叠加无意义)
  2. ReLU, Rectified Linear Unit 函数

神经网络可以用在分类和回归问题上,不过需要根据情况改变输出层的激活函数。一般而言,回归问题用恒等函数,分类问题用 softmax 函数。

一般而言,神经网络只把输出值最大的神经元所对应的类别作为识别结果,在进行分类时,输出层的 softmax 函数可以省略(但是在学习阶段是不能省略的)

第四章 神经网络的学习

学习的目的是以损失函数为基准,找出能使它的值达到最小的权重的参数。

深度学习的价值在于从人工设计规则转变为由机器从数据中学习。

神经网络的学习中所用的指标称为损失函数 loss function。这个损失函数可以使用任意函数,但一般用均方误差和交叉熵误差等。

利用微小的差分求导数的过程称为数值微分 numerical differentiation。而基于数学式的推导来求导数的过程称为解析性求导。数值微分求出来的是有误差的(只是一个近似)

偏导数和单变量的导数一样,都是求某个地方的斜率。不过,偏导数需要将多个变量中的某一个变量定为目标变量,并将其他变量固定为某个值。

由全部变量的偏导数汇总而成的向量称为梯度 gradient。梯度表示的是各点处的函数值减少最多的方向。

机器学习的主要任务是在学习时寻找最优参数。同样地,神经网络也必须在学习时找到最优参数(权重和偏置)

学习率是超参数,是人工设定的,一般来说需要尝试多个不同的值。

神经网络的学习步骤如下:

  1. mini-batch,从训练数据中随机选出一部分数据,称为 mini-batch,我们的目标是减少 mini-batch 的损失函数的值。
  2. 计算梯度,为了减少 mini-batch 损失函数的值,需要求出各个权重参数的梯度。梯度表示损失函数的值减少最多的方向。
  3. 更新参数,将权重参数沿梯度方向进行微小更新。
  4. 重复,重复前三个步骤。

第五章 误差反向传播法

  • 神经网络的正向传播中进行的矩阵的乘积运算在几何学领域被称为“仿射变换”(Affine)
  • 通过使用计算图,可以直观把握计算过程
  • 计算图的节点是由局部计算构成的。局部计算构成全局计算
  • 计算图的正向传播进行一般的计算。通过计算图的反向传播,可以计算各个节点的导数
  • 通过将神经网络的组成元素实现为层,可以高效地计算梯度

第六章 与学习相关的技巧

  • 神经网络的学习的目的是找到使损失函数的值尽可能小的参数。这是寻找最优参数的问题,解决这个问题的过程称为最优化(optimization)
    • 随机梯度下降 SGD(stochastic gradient descent):如果函数的形状非均相 anisotropic,比如呈延伸状,搜索的路径就会非常低效。根本原因:梯度的方向并没有指向最小值的方向
    • Momentum 动量:保存物体的速度,可以减弱 之 字形变动
    • AdaGrad:会记录过去所有梯度的平方和。大幅更新的参数其学习率会变小。这样可能导致学习率无限趋近与 0。这时可以使用 RMSProp 方法,会逐渐遗忘最早的梯度(指数移动平均)
    • Adam:融合 Momentum 和 AdaGrad 方法。设置学习率,beta 系数的标准值为 0.9 和 0.999,一般这样设置就可以。
  • 为了防止“权重均一化”,必须随机生成初始值
  • 偏向 0 和 1 的数据分布会造成反向传播中梯度的值不断变小,最后消失,也就是梯度消失问题(gradient vanishing)
  • 各层的激活值的分布都要求有适当的广度,如果传递的是有所偏向的数据,就会出现梯度消失或者“表现力受限”的问题,导致学习可能无法顺利进行。
  • Xavier 初始值:与前一层有 n 个节点连接时,初始值用标准差为 $1/\sqrt{n}$ 的分布
  • 如果设定了合适的权重初始值,则各层的激活值分布会有适当的广度,从而可以顺利进行学习。那么为了使各层拥有适当的广度,“强制性”调整激活值的分布,这就是 batch normalization 的原始想法
    • 可以增大学习率
    • 不那么依赖初始值
    • 抑制过拟合(降低 Dropout 等的必要性)
  • 发生过拟合的原因主要有两个:1)模型拥有大量参数、表现力强;2)训练数据少
  • 权值衰减是常用的抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来抑制过拟合(也就是正则化
  • Dropout 是一种在学习的过程中随机删除神经元的方法
  • 逐渐缩小“好值”存在范围是搜索超参数的一个有效方法

第七章 卷积神经网络

  • 新增了 Convolution 层和 Pooling 层
  • 全连接的问题在于数据的形状被“忽视”了
  • 新增概念:卷积运算、填充 padding、步幅 stride
  • 对于多个通道的输入数据,滤波器也需要有同样的通道数,但是计算得到的卷积,最终只输出一个特征图。如果需要生成多个,就需要多个滤波器(这里的参数数量需要仔细理解!)
  • 池化层的特征
    • 没有要学习的参数:只是选取最大值、平均值
    • 通道数不发生变化:计算按照通道独立运行
    • 对微小的位置变化具有鲁棒性
  • Numpy 中访问元素最好不要用 for 语句,可以使用 im2col 语句
  • 具有代表性的 CNN
    • 1998 LeNet:sigmoid,用 subsampling 而非 maxpooling
    • 2012 AlexNet:relu,局部正规化 LRN 层,Dropout

第八章 深度学习

  • VGG 网络
    • 基于 3x3 的小型滤波器的卷积层
    • 激活函数 ReLU
    • 全连接后面使用 Dropout
    • 基于 Adam 的最优化
    • 使用 He 初始值作为权重初始值
  • Data Augmentation 方法简单,但可以显著提高识别精度
  • 加深层可以减少网络的参数数量,用更少的参数达到同等水平的表现力
  • 叠加小型滤波器来加深网络的好处是可以减少参数的数量,扩大感受野 receptive field。
  • 加深层可以分层次地分解需要学习的问题,可以分层次传递信息
  • VGG, GoogLeNet, ResNet
  • 深度学习的高速化的主要课题就是如何高速、高效地进行大量乘积累加运算
  • 在深度学习中,即使是 16 位的半精度浮点数也可以顺利进行学习,计算量减半
  • 深度学习的应用:物体检测、图像分割、图像标题生成(引申出多模态处理)
  • 未来发展:图像风格变换、图像的生成(GAN)、自动驾驶、强化学习
  • 注,本章代码可以参考 这里