[read]深度学习入门:基于Python的理论与实现


=Start=

缘由:

前段时间在ChatGPT很火的时候突然想学习一下神经网络和深度学习,单靠自己搜索阅读网络文章来学习这种专业性比较强的知识不太靠谱,因此买了2本书希望系统性的学习了解一下这块的内容,一本是“鱼书”《深度学习入门:基于Python的理论与实现》,另一本是“苹果书”《深入浅出神经网络与深度学习》,对我来说“鱼书”的阅读体验更好,这里先通过简单记录一下本书的目录结构和我觉得比较重要的内容和标记,方便以后参考。

快速翻阅完本书大部分内容的一个感受和想法——本书写的真的是非常深入浅出,很多知识点讲的都非常细,会从最简单最源头的地方讲起,让读者更容易理解,这个对于初学者而言尤为重要(那些一上来就讲概念,讲复杂原理的书/教材是最烦人的,就不是写给普通人看的),让人有信心继续读下去;

但即便是这样,在你通读完全书之后(或快或慢,但一般一周时间是够的),你最多也只能是知道初期的神经网络为什么要这么设计,涉及到哪些优化方法和思路,一般的处理步骤又是怎么样的,你还是很难自己手写出能实现相关功能的代码,但这个也是正常的,对于大部分普通人来说,凭什么你只花一周时间看完一本书就能习得甚至是想掌握绝世武功?你真当你是天选之子还是把这个问题想简单了?在现在这个社会上,大部分技能学会容易,但掌握很难,想学好掌握好那是需要持续不断的花时间精力去钻研的,没有什么人能随随便便成功,也没有什么值钱的经验和技能可以随随便便学会。要想会,先花时间花精力吧,投入了不一定能会,但不投入是绝不可能会的。

还有就是神经网络/深度学习或是编程,从来都是实践性很强的学科,一定要动手改代码/写代码以及运行测试,这样才能学的扎实,否则极有可能是眼睛会了但是手还不会。

正文:

参考解答:
#### 第 1 章 Python入门

1.1 Python是什么
1.2 Python的安装
1.2.1 Python版本
1.2.2 使用的外部库
1.2.3 Anaconda发行版
1.3 Python解释器
1.3.1 算术计算
1.3.2 数据类型
1.3.3 变量
1.3.4 列表
1.3.5 字典
1.3.6 布尔型
1.3.7 if 语句
1.3.8 for 语句
1.3.9 函数
1.4 Python脚本文件
1.4.1 保存为文件
1.4.2 类
1.5 NumPy
1.5.1 导入NumPy
1.5.2 生成NumPy数组
1.5.3 NumPy 的算术运算
**1.5.4 NumPy的N维数组**
**1.5.5 广播**
1.5.6 访问元素
1.6 Matplotlib
**1.6.1 绘制简单图形**
1.6.2 pyplot 的功能
1.6.3 显示图像
1.7 小结

#### 第 2 章 感知机

2.1 感知机是什么
2.2 简单逻辑电路
2.2.1 与门
2.2.2 与非门和或门
2.3 感知机的实现
**2.3.1 简单的实现**
2.3.2 导入权重和偏置
**2.3.3 使用权重和偏置的实现**
2.4 感知机的局限性
2.4.1 异或门
**2.4.2 线性和非线性**
2.5 多层感知机
2.5.1 已有门电路的组合
**2.5.2 异或门的实现**
2.6 从与非门到计算机
2.7 小结

#### 第 3 章 神经网络

3.1 从感知机到神经网络
3.1.1 神经网络的例子
3.1.2 复习感知机
**3.1.3 激活函数登场**
3.2 激活函数
3.2.1 sigmoid 函数
3.2.2 阶跃函数的实现
3.2.3 阶跃函数的图形
**3.2.4 sigmoid 函数的实现**
**3.2.5 sigmoid 函数和阶跃函数的比较**
**3.2.6 非线性函数**
3.2.7 ReLU函数
**3.3 多维数组的运算**
3.3.1 多维数组
3.3.2 矩阵乘法
3.3.3 神经网络的内积
3.4 3 层神经网络的实现
3.4.1 符号确认
3.4.2 各层间信号传递的实现
3.4.3 代码实现小结
3.5 输出层的设计
3.5.1 恒等函数和softmax 函数
**3.5.2 实现softmax 函数时的注意事项**
3.5.3 softmax 函数的特征
**3.5.4 输出层的神经元数量**
3.6 手写数字识别
**3.6.1 MNIST数据集**
**3.6.2 神经网络的推理处理**
**3.6.3 批处理**
3.7 小结

#### 第 4 章 神经网络的学习

4.1 从数据中学习
**4.1.1 数据驱动**
4.1.2 训练数据和测试数据
**4.2 损失函数**
4.2.1 均方误差
4.2.2 交叉熵误差
4.2.3 mini-batch 学习
4.2.4 mini-batch 版交叉熵误差的实现
**4.2.5 为何要设定损失函数**
4.3 数值微分
**4.3.1 导数**
4.3.2 数值微分的例子
4.3.3 偏导数
**4.4 梯度**
4.4.1 梯度法
**4.4.2 神经网络的梯度**
**4.5 学习算法的实现**
4.5.1 2 层神经网络的类
4.5.2 mini-batch 的实现
**4.5.3 基于测试数据的评价**
4.6 小结

#### 第 5 章 误差反向传播法

5.1 计算图
5.1.1 用计算图求解
5.1.2 局部计算
5.1.3 为何用计算图解题
**5.2 链式法则**
5.2.1 计算图的反向传播
5.2.2 什么是链式法则
5.2.3 链式法则和计算图
5.3 反向传播
**5.3.1 加法节点的反向传播**
**5.3.2 乘法节点的反向传播**
5.3.3 苹果的例子
5.4 简单层的实现
5.4.1 乘法层的实现
5.4.2 加法层的实现
5.5 激活函数层的实现
5.5.1 ReLU层
5.5.2 Sigmoid 层
**5.6 Affine/Softmax层的实现**
5.6.1 Affine层
5.6.2 批版本的Affine层
5.6.3 Softmax-with-Loss 层
5.7 误差反向传播法的实现
**5.7.1 神经网络学习的全貌图**
**5.7.2 对应误差反向传播法的神经网络的实现**
**5.7.3 误差反向传播法的梯度确认**
5.7.4 使用误差反向传播法的学习
5.8 小结

#### 第 6 章 与学习相关的技巧

**6.1 参数的更新**
6.1.1 探险家的故事
6.1.2 SGD
6.1.3 SGD的缺点
6.1.4 Momentum
6.1.5 AdaGrad
6.1.6 Adam
6.1.7 使用哪种更新方法呢
6.1.8 基于MNIST数据集的更新方法的比较
**6.2 权重的初始值**
6.2.1 可以将权重初始值设为0 吗
6.2.2 隐藏层的激活值的分布
6.2.3 ReLU的权重初始值
6.2.4 基于MNIST数据集的权重初始值的比较
**6.3 Batch Normalization**
6.3.1 Batch Normalization 的算法
6.3.2 Batch Normalization 的评估
**6.4 正则化**
6.4.1 过拟合
6.4.2 权值衰减
6.4.3 Dropout
6.5 超参数的验证
6.5.1 验证数据
6.5.2 超参数的最优化
6.5.3 超参数最优化的实现
6.6 小结

#### 第 7 章 卷积神经网络

7.1 整体结构
7.2 卷积层
7.2.1 全连接层存在的问题
7.2.2 卷积运算
7.2.3 填充
7.2.4 步幅
7.2.5 3 维数据的卷积运算
7.2.6 结合方块思考
7.2.7 批处理
7.3 池化层
7.4 卷积层和池化层的实现
7.4.1 4 维数组
7.4.2 基于im2col 的展开
7.4.3 卷积层的实现
7.4.4 池化层的实现
7.5 CNN的实现
7.6 CNN的可视化
7.6.1 第 1 层权重的可视化
7.6.2 基于分层结构的信息提取
7.7 具有代表性的CNN
7.7.1 LeNet
7.7.2 AlexNet
7.8 小结

#### 第 8 章 深度学习

8.1 加深网络
8.1.1 向更深的网络出发
8.1.2 进一步提高识别精度
8.1.3 加深层的动机
8.2 深度学习的小历史
8.2.1 ImageNet
8.2.2 VGG
8.2.3 GoogLeNet
8.2.4 ResNet
8.3 深度学习的高速化
8.3.1 需要努力解决的问题
8.3.2 基于GPU的高速化
8.3.3 分布式学习
8.3.4 运算精度的位数缩减
8.4 深度学习的应用案例
8.4.1 物体检测
8.4.2 图像分割
8.4.3 图像标题的生成
8.5 深度学习的未来
8.5.1 图像风格变换
8.5.2 图像的生成
8.5.3 自动驾驶
8.5.4 Deep Q-Network(强化学习)
8.6 小结

附录A Softmax-with-Loss 层的计算图
A.1 正向传播
A.2 反向传播
A.3 小结

参考文献
深度学习入门

#### 第2章 感知机

本章将介绍感知机(perceptron)这一算法。感知机是由美国学者 Frank Rosenblatt 在 1957 年提出来的。为何我们现在还要学习这一很久以前就有的算法呢?因为感知机也是作为神经网络(深度学习)的起源的算法。因此,学习感知机的构造也就是学习通向神经网络和深度学习的一种重要思想。

2.1 感知机是什么

感知机接收多个输入信号,输出一个信号。感知机的多个输入信号都有各自固有的权重,这些权重发挥着控制各个信号的重要性的作用。也就是说,权重越大,对应该权重的信号的重要性就越高。

2.2 简单逻辑电路 

与门/或门/与非门
AND/OR/NAND gate
NAND gate = Not AND gate 与非门就是颠倒了与门的输出。

真值表

2.3 感知机的实现
2.3.1 简单的实现
2.3.2 导入权重和偏置
2.3.3 使用权重和偏置的实现

2.4 感知机的局限性

2.4.1 异或门 
2.4.2 线性和非线性

感知机的局限性就在于它只能表示由一条直线分割的空间。

由曲线分割而成的空间称为非线性空间,由直线分割而成的空间称为线性空间。

2.5 多层感知机

2.5.2 异或门的实现

叠加了多层的感知机也称为多层感知机(multi-layered perceptron)。

通过叠加层(加深层),感知机能进行更加灵活的表示。

理论上可以说 2 层感知机就能构建计算机。这是因为,已有研究证明,2层感知机(严格地说是激活函数使用了非线性的sigmoid函数的感知机,具体请参照下一章)可以表示任意函数。但是,使用2层感知机的构造,通过设定合适的权重来构建计算机是一件非常累人的事情。实际上,在用与非门等低层的元件构建计算机的情况下,分阶段地制作所需的零件(模块)会比较自然,即先实现与门和或门,然后实现半加器和全加器,接着实现算数逻辑单元(ALU),然后实现 CPU。因此,通过感知机表示计算机时,使用叠加了多层的构造来实现是比较自然的流程。


#### 第3章 神经网络

3.1 从感知机到神经网络

从阈值改写成偏置,引入新函数用于控制输出。新引入的函数就是激活函数——用于决定如何来激活输入信号的总和(信号乘以权重加上偏置)。

将输入信号的总和转换为输出信号,这种函数一般称为激活函数(activation function)。如“激活”一词所示,激活函数的作用在于决定如何来激活输入信号的总和。

先计算输入信号的加权总和,然后用激活函数转换这一总和。



3.2 激活函数

阶跃函数
sigmoid函数

一般而言,“朴素感知机”是指单层网络,指的是激活函数使用了阶跃函数的模型。“多层感知机”是指神经网络,即使用 sigmoid 函数等平滑的激活函数的多层网络。

实际上,上一章介绍的感知机和接下来要介绍的神经网络的主要区别就在于这个激活函数。其他方面,比如神经元的多层连接的构造、信号的传递方法等,基本上和感知机是一样的。

sigmoid 函数和阶跃函数的比较 
    0.  (不同)平滑性。sigmoid 函数的平滑性对神经网络的学习具有重要意义。 
    0.  (不同)sigmoid函数可以返回连续的实数。相对于阶跃函数只能返回 0 或 1,sigmoid 函数可以返 回 0.731 . . .、0.880 . . . 等实数(这一点和刚才的平滑性有关)。也就是说,感 知机中神经元之间流动的是 0 或 1 的二元信号,而神经网络中流动的是连续的实数值信号。
    0.  (相同)从宏观角度来看,形状是相似的,且输出的值都在0和1之间。
    0.  (相同)两者均为非线性函数。

非线性函数——线性函数是一条笔直的直线。而非线性函数,顾名思义,指的是不像线性函数那样呈现出一条直线的函数。

神经网络的激活函数必须使用非线性函数。换句话说,激活函数不能使用线性函数。为什么不能使用线性函数呢?因为使用线性函数的话,加深神经网络的层数就没有意义了。

线性函数的问题在于,不管如何加深层数,总是存在与之等效的“无隐藏层的神经网络”。

3.5 输出层的设计

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

输出层所用的激活函数,要根据求解问题的性质决定。一般地,回归问题可以使用恒等函数,二元分类问题可以使用 sigmoid 函数,多元分类问题可以使用 softmax 函数。

机器学习的问题大致可以分为分类问题和回归问题。分类问题是数据属于哪一个类别的问题。比如,区分图像中的人是男性还是女性的问题就是分类问题。而回归问题是根据某个输入预测一个(连续的) 数值的问题。比如,根据一个人的图像预测这个人的体重的问题就是回归问题(类似“57.4kg”这样的预测)。

3.5.1 恒等函数和 softmax 函数

恒等函数会将输入按原样输出,对于输入的信息,不加以任何改动地直接输出。 

3.5.2 实现 softmax 函数时的注意事项

3.5.3 softmax 函数的特征

Softmax函数的特征——输出是0.0到1.0之间到实数,并且函数的输出值的综合是1。

一般而言,神经网络只把输出值最大的神经元所对应的类别作为识别结果。并且,即便使用 softmax 函数,输出值最大的神经元的位置也不会变。因此,神经网络在进行分类时,输出层的 softmax 函数可以省略。在实际的问题中,由于指数函数的运算需要一定的计算机运算量,因此输出层的 softmax 函数 一般会被省略。

3.5.4 输出层的神经元数量

输出层的神经元数量需要根据待解决的问题来决定。对于分类问题,输出层的神经元数量一般设定为类别的数量。比如,对于某个输入图像,预测是图中的数字 0 到 9 中的哪一个的问题(10 类别分类问题),可以将输出层的神经元设定为 10 个。



像这样把数据限定到某个范围内的处理称为正规化(normalization)。此外,对神经网络的输入数据 进行某种既定的转换称为预处理(pre-processing)。这里,作为对输入图像的一种预处理,我们进行了正规化。

预处理在神经网络(深度学习)中非常实用,其有效性已在提高识别性能和学习的效率等众多实验中得到证明。在刚才的例子中,作为一种预处理,我们将各个像素值除以 255,进行了简单的正规化。实际上,很多预处理都会考虑到数据的整体分布。比如,利用数据 整体的均值或标准差,移动数据,使数据整体以 0 为中心分布,或者进行正规化,把数据的延展控制在一定范围内。除此之外,还有将数据整体的分布形状均匀化的方法,即数据白化(whitening)等。

#### 第4章 神经网络的学习

本章的主题是神经网络的学习。这里所说的“学习”是指从训练数据中自动获取最优权重参数的过程。本章中,为了使神经网络能进行学习,将导入损失函数这一指标。而学习的目的就是以该损失函数为基准,找出能使它的值达到最小的权重参数。为了找出尽可能小的损失函数的值,本章我们将介绍利用了函数斜率的梯度法。

4.1 从数据中学习

神经网络的特征就是可以从数据中学习。所谓“从数据中学习”,是指可以由数据自动决定权重参数的值。这是非常了不起的事情!因为如果所有的参数都需要人工决定的话,工作量就太大了。

4.1.1 数据驱动

数据是机器学习的命根子。从数据中寻找答案、从数据中发现模式、根据数据讲故事......这些机器学习所做的事情,如果没有数据的话,就无从谈起。因此,数据是机器学习的核心。这种数据驱动的方法,也可以说脱离了过往以人为中心的方法。

通常要解决某个问题,特别是需要发现某种模式时,人们一般会综合考虑各种因素后再给出回答。“这个问题好像有这样的规律性?”“不对,可能原因在别的地方。”——类似这样,人们以自己的经验和直觉为线索,通过反复试验推进工作。而机器学习的方法则极力避免人为介入,尝试从收集到的数据中发现答案(模式)。神经网络或深度学习则比以往的机器学习方法更能 避免人为介入。



深度学习有时也称为端到端机器学习(end-to-end machine learning)。这里所说的端到端是指从一端到另一端的意思,也就是 从原始数据(输入)中获得目标结果(输出)的意思。 

神经网络的优点是对所有的问题都可以用同样的流程来解决。比如,不管要求解的问题是识别 5,还是识别狗,抑或是识别人脸,神经网络都是通过不断地学习所提供的数据,尝试发现待求解的问题的模式。也就是说,与待处理的问题无关,神经网络可以将数据直接作为原始数据,进行“端对端” 的学习。 

4.2 损失函数(loss function)

损失函数是表示神经网络性能的“恶劣程度”的指标,即当前的神经网络对监督数据在多大程度上不拟合,在多大程度上不一致。(损失函数表示的是神经网络对监督数据不拟合的程度,即推理效果有多差)

神经网络以某个指标为线索寻找最优权重参数。神经网络的学习中所用的指标称为损失函数(loss function)。这个损失函数可以使用任意函数,但一般用均方误差(MSE,mean squared error)和交叉熵误差等(CEE,cross entropy error)。

t 是监督数据,将正确解标签设为 1,其他均设为 0。这里,标签“2”为 1, 表示正确解是“2”。将正确解标签表示为 1,其他标签表示为 0 的表示方法称 为 one-hot 表示。

对于分类任务,可以选用交叉熵做为模型的损失函数;对于回归任务,可以选用MSE来作为模型的损失函数。

交叉熵使得梯度与绝对误差成正比——当梯度为0时,误差也为0,也即当寻找到损失函数的极值/最值点时,误差小到可以忽略的程度,这时也就得到了好的权重偏置数据。

机器学习使用训练数据进行学习。使用训练数据进行学习,严格来说, 就是针对训练数据计算损失函数的值,找出使该值尽可能小的参数。
4.2.5 为何要设定损失函数 

在神经网络的学习中,寻找最优参数(权重和偏置)时,要寻找使损失函数的值尽可能小的参数。为了找到使损失函数的值尽可能小的地方,需要计算参数的导数(确切地讲是梯度),然后以这个导数为指引,逐步更新参数的值。

假设有一个神经网络,现在我们来关注这个神经网络中的某一个权重参数。此时,对该权重参数的损失函数求导,表示的是“如果稍微改变这个权重参数的值,损失函数的值会如何变化”。如果导数的值为负,通过使该权重参数向正方向改变,可以减小损失函数的值;反过来,如果导数的值为正,则通过使该权重参数向负方向改变,可以减小损失函数的值。不过,当导数的值为 0 时,无论权重参数向哪个方向变化,损失函数的值都不会改变,此时该权重参数的更新会停在此处。

之所以不能用识别精度作为指标,是因为这样一来绝大多数地方的导数都会变为 0,导致参数无法更新。话说得有点多了,我们来总结一下上面的内容。

在进行神经网络的学习时,不能将识别精度作为指标。因为如果以识别精度为指标,则参数的导数在绝大多数地方都会变为 0。

识别精度对微小的参数变化基本上没有什么反应,即便有反应,它的值也是不连续地、突然地变化。作为激活函数的阶跃函数也有同样的情况。出于相同的原因,如果使用阶跃函数作为激活函数,神经网络的学习将无法进行。

如果使用了阶跃函数,那么即便将损失函数作为指标,参数的微小变化也会被阶跃函数抹杀,导致损失函数的值不会产生任何变化。

sigmoid 函数的导数在任何地方都不为 0。这对神经网络的学习非常重要。得益于这个斜率不会为 0 的性质,神经网络的学习得以正确进行(往正确的方向进行)。

梯度法使用梯度的信息决定前进的方向。

4.3 数值微分

利用微小的差分求导数的过程称为数值微分(numerical differentiation)。

我们把这里讨论的有多个变量的函数的导数称为偏导数。 

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

4.4 梯度

由全部变量的偏导数汇总而成的向量称为梯度(gradient)。

机器学习的主要任务是在学习时寻找最优参数。同样地,神经网络也必须在学习时找到最优参数(权重和偏置)。这里所说的最优参数是指损失函数取最小值时的参数。但是,一般而言,损失函数很复杂,参数空间庞大,我们不知道它在何处能取得最小值。而通过巧妙地使用梯度来寻找函数最小值 (或者尽可能小的值)的方法就是梯度法。

这里需要注意的是,梯度表示的是各点处的函数值减小最多的方向。因此,无法保证梯度所指的方向就是函数的最小值或者真正应该前进的方向。实际上,在复杂的函数中,梯度指示的方向基本上都不是函数值最小处。



η 表示更新量,在神经网络的学习中,称为学习率(learning rate)。学习率决定在一次学习中,应该学习多少,以及在多大程度上更新参数。 

学习率需要事先确定为某个值,比如 0.01 或 0.001。一般而言,这个值过大或过小,都无法抵达一个“好的位置”。在神经网络的学习中,一般会一边改变学习率的值,一边确认学习是否正确进行了。

实验结果表明,学习率过大的话,会发散成一个很大的值;反过来,学习率过小的话,基本上没怎么更新就结束了。也就是说,设定合适的学习率是一个很重要的问题。 

像学习率这样的参数称为超参数。这是一种和神经网络的参数(权重和偏置)性质不同的参数。相对于神经网络的权重参数是通过训练数据和学习算法自动获得的,学习率这样的超参数则是人工设定的。 一般来说,超参数需要尝试多个值,以便找到一种可以使学习顺利进行的设定。

4.4.2 神经网络的梯度

神经网络的学习也要求梯度。这里所说的梯度是指损失函数关于权重参数的梯度。





#### 第5章 误差反向传播法

上一章中,我们介绍了神经网络的学习,并通过数值微分计算了神经网络的权重参数的梯度(严格来说,是损失函数关于权重参数的梯度)。数值微分虽然简单,也容易实现,但缺点是计算上比较费时间。本章我们将学习一个能够高效计算权重参数的梯度的方法——误差反向传播法。

5.1 计算图

计算图将计算过程用图形表示出来。 

综上,用计算图解题的情况下,需要按如下流程进行。 
1. 构建计算图。2. 在计算图上,从左向右进行计算。 
这里的第 2 歩“从左向右进行计算”是一种正方向上的传播,简称为正 向传播(forward propagation)。正向传播是从计算图出发点到结束点的传播。 既然有正向传播这个名称,当然也可以考虑反向(从图上看的话,就是从右向左) 的传播。实际上,这种传播称为反向传播(backward propagation)。反向传 播将在接下来的导数计算中发挥重要作用。 

计算图的特征是可以通过传递“局部计算”获得最终结果。“局部”这个词的意思是“与自己相关的某个小范围”。局部计算是指,无论全局发生了什么,都能只根据与自己相关的信息输出接下来的结果。

用计算图解题的好处:
1、可以将复杂问题分解从而简化问题;
2、中间的计算结果可保存,从而可以通过反向传播高效计算导数;

综上,计算图的优点是,可以通过正向传播和反向传播高效地计算各个变量的导数值。

5.2 链式法则

如果某个函数由复合函数表示,则该复合函数的导数可以用构成复合函数的各个函数的导数的乘积表示。

5.3 反向传播 

5.3.1 加法节点的反向传播 
因为加法节点的反向传播只乘以 1,所以输入的值 会原封不动地流向下一个节点。

5.3.2 乘法节点的反向传播
乘法的反向传播会将上游的值乘以正向传播时的输入信号的“翻转值”后传递给下游。

乘法的反向传播会乘以输入信号的翻转值 
加法的反向传播只是将上游的值传给下游,并不需要正向传播的输入信号。但是,乘法的反向传播需要正向传播时的输入信号值。因此,实现乘法节点的反向传播时,要保存正向传播的输入信号。 

5.4 简单层的实现
本节将用 Python 实现前面的购买苹果的例子。这里,我们把要实现的计算图的乘法节点称为“乘法层”(MulLayer),加法节点称为“加法层”(AddLayer)。

层的实现中有两个共通的方法(接口)forward()和backward()。forward()对应正向传播,backward()对应反向传播。

5.5 激活函数层的实现 

5.6 Affine/Softmax 层的实现 

5.6.1 Affine 层 
神经网络的正向传播中进行的矩阵的乘积运算在几何学领域被称为“仿射变换”。因此,这里将进行仿射变换的处理实现为“Affine 层”。

5.6.2 批版本的 Affine 层

5.6.3 Softmax-with-Loss 层


神经网络中进行的处理有推理(inference)和学习两个阶段。神经网络的推理通常不使用 Softmax 层。比如,用图 5-28 的网络进行推理时,会将最后一个 Affine 层的输出作为识别结果。神经网络中未被正规化的输出结果(图 5-28 中 Softmax 层前面的 Affine 层的输出)有时被称为“得分”。也就是说,当神经网络的推理只需要给出一个答案的情况下,因为此时只对得分最大值感兴趣,所以不需要 Softmax 层。 不过,神经网络的学习阶段则需要 Softmax 层。



5.7 误差反向传播法的实现

通过像组装乐高积木一样组装上一节中实现的层,可以构建神经网络。本节我们将通过组装已经实现的层来构建神经网络。



5.7.2 对应误差反向传播法的神经网络的实现 

5.7.3 误差反向传播法的梯度确认 

数值微分的优点是实现简单,因此,一般情况下不太容易出错。而误差反向传播法的实现很复杂,容易出错。所以,经常会比较数值微分的结果和误差反向传播法的结果,以确认误差反向传播法的实现是否正确。确认数值微分求出的梯度结果和误差反向传播法求出的结果是否一致(严格地讲,是非常相近)的操作称为梯度确认(gradient check)。

5.7.4 使用误差反向传播法的学习 



#### 第6章 与学习相关的技巧

6.1 参数的更新

神经网络的学习的目的是找到使损失函数的值尽可能小的参数。这是寻找最优参数的问题,解决这个问题的过程称为最优化(optimization)。遗憾的是, 神经网络的最优化问题非常难。这是因为参数空间非常复杂,无法轻易找到最优解(无法使用那种通过解数学式一下子就求得最小值的方法)。而且,在深度神经网络中,参数的数量非常庞大,导致最优化问题更加复杂。

在前几章中,为了找到最优参数,我们将参数的梯度(导数)作为了线索。 使用参数的梯度,沿梯度方向更新参数,并重复这个步骤多次,从而逐渐靠近最优参数,这个过程称为随机梯度下降法(stochastic gradient descent), 简称 SGD。SGD 是一个简单的方法,不过比起胡乱地搜索参数空间,也算是“聪明”的方法。但是,根据不同的问题,也存在比 SGD 更加聪明的方法。



6.1.2 SGD
6.1.3 SGD 的缺点 

虽然 SGD 简单,并且容易实现,但是在解决某些问题时可能没有效率。 

SGD 的缺点是,如果函数的形状非均向(anisotropic),比如呈延伸状,搜索的路径就会非常低效。因此,我们需要比单纯朝梯度方向前进的 SGD 更聪明的方法。SGD 低效的根本原因是,梯度的方向并没有指向最小值的方向。

为了改正 SGD 的缺点,下面我们将介绍 Momentum、AdaGrad、Adam 这 3 种方法来取代 SGD。

6.1.4 Momentum 

6.1.5 AdaGrad 

在神经网络的学习中,学习率(数学式中记为 η)的值很重要。学习率过小,会导致学习花费过多时间;反过来,学习率过大,则会导致学习发散而不能正确进行。

在关于学习率的有效技巧中,有一种被称为学习率衰减(learning rate decay)的方法,即随着学习的进行,使学习率逐渐减小。实际上,一开始“多” 学,然后逐渐“少”学的方法,在神经网络的学习中经常被使用。

逐渐减小学习率的想法,相当于将“全体”参数的学习率值一起降低。 而 AdaGrad [6] 进一步发展了这个想法,针对“一个一个”的参数,赋予其“定制”的值。

AdaGrad 会为参数的每个元素适当地调整学习率,与此同时进行学习 (AdaGrad 的 Ada 来自英文单词 Adaptive,即“适当的”的意思)。

AdaGrad 会记录过去所有梯度的平方和。因此,学习越深入,更新的幅度就越小。实际上,如果无止境地学习,更新量就会变为 0,完全不再更新。为了改善这个问题,可以使用 RMSProp 方法。 RMSProp 方法并不是将过去所有的梯度一视同仁地相加,而是逐渐地遗忘过去的梯度,在做加法运算时将新梯度的信息更多地反映出来。这种操作从专业上讲,称为“指数移动平均”,呈指数函数式地减小 过去的梯度的尺度。

6.1.6 Adam 

Momentum 参照小球在碗中滚动的物理规则进行移动,AdaGrad 为参 数的每个元素适当地调整更新步伐。如果将这两个方法融合在一起会怎么样呢?这就是 Adam 方法的基本思路。

Adam 是 2015 年提出的新方法。它的理论有些复杂,直观地讲,就是融合了 Momentum 和 AdaGrad 的方法。通过组合前面两个方法的优点,有望实现参数空间的高效搜索。此外,进行超参数的“偏置校正”也是 Adam 的特征。这里不再进行过多的说明,详细内容请参考原作者的论文。

Adam 会设置 3 个超参数。一个是学习率(论文中以 α 出现),另外两个是一次 momentum 系数 β1 和二次 momentum 系数 β2 。根据论文,标准的设定值是 β1 为 0.9,β2 为 0.999。设置了这些值后,大多数情况下都能顺利运行。

6.1.7 使用哪种更新方法呢

到目前为止,我们已经学习了 4 种(SGD、Momentum、AdaGrad、Adam)更新参数的方法。这里我们来比较一下这 4 种方法(源代码在 ch06/optimizer_compare_naive.py 中)。

如图 6-8 所示,根据使用的方法不同,参数更新的路径也不同。只看这个图的话,AdaGrad 似乎是最好的,不过也要注意,结果会根据要解决的问题而变。并且,很显然,超参数(学习率等)的设定值不同,结果也会发生变化。

上面我们介绍了 SGD、Momentum、AdaGrad、Adam 这 4 种方法,那么用哪种方法好呢?非常遗憾,(目前)并不存在能在所有问题中都表现良好的方法。这 4 种方法各有各的特点,都有各自擅长解决的问题和不擅长解决的问题。

很多研究中至今仍在使用 SGD。Momentum 和 AdaGrad 也是值得一试的方法。最近,很多研究人员和技术人员都喜欢用 Adam。本书将主要使用 SGD 或者 Adam,读者可以根据自己的喜好多多尝试。

6.1.8 基于 MNIST 数据集的更新方法的比较

我们以手写数字识别为例,比较前面介绍的SGD、Momentum、 AdaGrad、Adam 这 4 种方法,并确认不同的方法在学习进展上有多大程度的差异。 先来看一下结果,如图 6-9 所示(源代码在 ch06/optimizer_compare_mnist.py 中)。

这个实验以一个 5 层神经网络为对象,其中每层有 100 个神经元。激活 函数使用的是 ReLU。 

从图 6-9 的结果中可知,与 SGD 相比,其他 3 种方法学习得更快,而且速度基本相同,仔细看的话,AdaGrad 的学习进行得稍微快一点。这个实验需要注意的地方是,实验结果会随学习率等超参数、神经网络的结构(几层深等)的不同而发生变化。不过,一般而言,与SGD相比,其他3种方法可以学习得更快,有时最终的识别精度也更高。

6.2 权重的初始值

在神经网络的学习中,权重的初始值特别重要。实际上,设定什么样的权重初始值,经常关系到神经网络的学习能否成功。本节将介绍权重初始值的推荐值,并通过实验确认神经网络的学习是否会快速进行。

6.2.1 可以将权重初始值设为 0 吗

后面我们会介绍抑制过拟合、提高泛化能力的技巧——权值衰减(weight decay)。简单地说,权值衰减就是一种以减小权重参数的值为目的进行学习的方法。通过减小权重参数的值来抑制过拟合的发生。

如果想减小权重的值,一开始就将初始值设为较小的值才是正途。

为了防止“权重均一化” (严格地讲,是为了瓦解权重的对称结构),必须随机生成初始值。

6.2.2 隐藏层的激活值的分布

各层的激活值的分布都要求有适当的广度。为什么呢?因为通过在各层间传递多样性的数据,神经网络可以进行高效的学习。反过来,如果传递的是有所偏向的数据,就会出现梯度消失或者“表现力受限”的问题,导致学习可能无法顺利进行。

6.2.3 ReLU 的权重初始值

总结一下,当激活函数使用 ReLU 时,权重初始值使用 He 初始值,当激活函数为 sigmoid 或 tanh 等 S 型曲线函数时,初始值使用 Xavier 初始值。 这是目前的最佳实践。

6.2.4 基于 MNIST 数据集的权重初始值的比较

综上,在神经网络的学习中,权重初始值非常重要。很多时候权重初始值的设定关系到神经网络的学习能否成功。权重初始值的重要性容易被忽视,而任何事情的开始(初始值)总是关键的,因此在结束本节之际,再次强调一下权重初始值的重要性。

6.3 Batch Normalization

6.3.1 Batch Normalization 的算法

Batch Normalization(下文简称Batch Norm)是2015年提出的方法。 Batch Norm虽然是一个问世不久的新方法,但已经被很多研究人员和技术人员广泛使用。实际上,看一下机器学习竞赛的结果,就会发现很多通过使用这个方法而获得优异结果的例子。

为什么Batch Norm这么惹人注目呢?因为Batch Norm有以下优点。 
* 可以使学习快速进行(可以增大学习率)。• 不那么依赖初始值(对于初始值不用那么神经质)。
* 抑制过拟合(降低Dropout等的必要性)。

Batch Norm,顾名思义,以进行学习时的mini-batch为单位,按mini-batch 进行正规化。具体而言,就是进行使数据分布的均值为 0、方差为 1 的正规化。

6.3.2 Batch Normalization的评估
我们发现,几乎所有的情况下都是使用Batch Norm时学习进行得更快。同时也可以发现,实际上,在不使用Batch Norm的情况下,如果不赋予一个尺度好的初始值,学习将完全无法进行。

综上,通过使用Batch Norm,可以推动学习的进行。并且,对权重初始值变得健壮(“对初始值健壮”表示不那么依赖初始值)。Batch Norm具备了如此优良的性质,一定能应用在更多场合中。

6.4 正则化

机器学习的问题中,过拟合是一个很常见的问题。过拟合指的是只能拟合训练数据,但不能很好地拟合不包含在训练数据中的其他数据的状态。机器学习的目标是提高泛化能力,即便是没有包含在训练数据里的未观测数据,也希望模型可以进行正确的识别。我们可以制作复杂的、表现力强的模型,但是相应地,抑制过拟合的技巧也很重要。

为了避免过拟合,一种手段是使用正则化(Regularizaiton)来限制模型的复杂程度。Regularization从英文直译过来是“规则化”,就是说,在原来的问题求解条件上加一些规则限制,避免模型过于复杂,出现过拟合的情况。
需要注意的是,在正则化的时候,bais是不需要正则化的,不然可能会导致欠拟合!

6.4.1 过拟合

发生过拟合的原因,主要有以下两个。
* 模型拥有大量参数、表现力强。
* 训练数据少。

6.4.2 权值衰减

权值衰减是一直以来经常被使用的一种抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来抑制过拟合。很多过拟合原本就是因为权重参数取值过大才发生的。

复习一下,神经网络的学习目的是减小损失函数的值。这时,例如为损失函数加上权重的平方范数(L2范数)。这样一来,就可以抑制权重变大。 

L2 范数相当于各个元素的平方和。用数学式表示的话,假设有权重 W = (w1,w2,...,wn),则L2范数可用 计算 出来。除了 L2 范数,还有 L1 范数、L ∞范数等。L1 范数是各个元素的绝对值之和,相当于 |w1| + |w2| + . . . + |wn|。L∞范数也称为 Max 范数,相当于各个元素的绝对值中最大的那一个。L2 范数、L1 范数、L∞范数都可以用作正则化项,它们各有各的特点,不过这里我们要实现的是比较常用的 L2 范数。

6.4.3 Dropout

作为抑制过拟合的方法,前面我们介绍了为损失函数加上权重的 L2 范数的权值衰减方法。该方法可以简单地实现,在某种程度上能够抑制过拟合。但是,如果网络的模型变得很复杂,只用权值衰减就难以应对了。在这种情况下,我们经常会使用 Dropout 方法。

Dropout 是一种在学习的过程中随机删除神经元的方法。训练时,随机选出隐藏层的神经元,然后将其删除。被删除的神经元不再进行信号的传递,如图 6-22 所示。训练时,每传递一次数据,就会随机选择要删除的神经元。然后,测试时,虽然会传递所有的神经元信号,但是对于各个神经元的输出,要乘上训练时的删除比例后再输出。 

机器学习中经常使用集成学习。所谓集成学习,就是让多个模型单独进行学习,推理时再取多个模型的输出的平均值。用神经网络的语境来说,比如,准备5个结构相同(或者类似)的网络,分别进行学习,测试时,以这 5 个网络的输出的平均值作为答案。实验告诉我们,通过进行集成学习,神经网络的识别精度可以提高好几个百分点。这个集成学习与 Dropout 有密切的关系。这是因为可以将 Dropout 理解为,通过在学习过程中随机删除神经元,从而每一次都让不同的模型进行学习。并且,推理时,通过对神经元的输出乘以删除比例(比如,0.5 等),可以取得模型的平均值。也就是说,可以理解成, Dropout 将集成学习的效果(模拟地)通过一个网络实现了。

6.5 超参数的验证

神经网络中,除了权重和偏置等参数,超参数(hyper-parameter)也经常出现。这里所说的超参数是指,比如各层的神经元数量、batch大小、参数更新时的学习率或权值衰减等。如果这些超参数没有设置合适的值,模型的性能就会很差。虽然超参数的取值非常重要,但是在决定超参数的过程中一般会伴随很多的试错。本节将介绍尽可能高效地寻找超参数的值的方法。

6.5.1 验证数据

下面我们要对超参数设置各种各样的值以进行验证。这里要注意的是, 不能使用测试数据评估超参数的性能。这一点非常重要,但也容易被忽视。

为什么不能用测试数据评估超参数的性能呢?这是因为如果使用测试数据调整超参数,超参数的值会对测试数据发生过拟合。换句话说,用测试数据确认超参数的值的“好坏”,就会导致超参数的值被调整为只拟合测试数据。这样的话,可能就会得到不能拟合其他数据、泛化能力低的模型。

因此,调整超参数时,必须使用超参数专用的确认数据。用于调整超参数的数据,一般称为验证数据(validation data)。我们使用这个验证数据来评估超参数的好坏。

根据不同的数据集,有的会事先分成训练数据、验证数据、测试数据三部分,有的只分成训练数据和测试数据两部分,有的则不进行分割。在这种情况下,用户需要自行进行分割。如果是 MNIST 数据集,获得验证数据的最简单的方法就是从训练数据中事先分割 20% 作为验证数据。

6.5.2 超参数的最优化

进行超参数的最优化时,逐渐缩小超参数的“好值”的存在范围非常重要。所谓逐渐缩小范围,是指一开始先大致设定一个范围,从这个范围中随机选出一个超参数(采样),用这个采样到的值进行识别精度的评估;然后,多次重复该操作,观察识别精度的结果,根据这个结果缩小超参数的“好值”的范围。通过重复这一操作,就可以逐渐确定超参数的合适范围。



6.5.3 超参数最优化的实现

像这样,观察可以使学习顺利进行的超参数的范围,从而缩小值的范围。然后,在这个缩小的范围中重复相同的操作。这样就能缩小到合适的超参数的存在范围,然后在某个阶段,选择一个最终的超参数的值。

6.6 小结



#### 第7章 卷积神经网络

本章的主题是卷积神经网络(Convolutional Neural Network,CNN)。CNN 被用于图像识别、语音识别等各种场合,在图像识别的比赛中,基于深度学习的方法几乎都以 CNN 为基础。本章将详细介绍 CNN 的结构,并用 Python 实现其处理内容。


#### 第8章 深度学习

深度学习是加深了层的深度神经网络。基于之前介绍的网络,只需通过叠加层,就可以创建深度网络。本章我们将看一下深度学习的性质、课题和可能性,然后对当前的深度学习进行概括性的说明。

8.1 加深网络

关于神经网络,我们已经学了很多东西,比如构成神经网络的各种层、学习时的有效技巧、对图像特别有效的CNN、参数的最优化方法等,这些都是深度学习中的重要技术。本节我们将这些已经学过的技术汇总起来,创建一个深度网络,挑战 MNIST 数据集的手写数字识别。

8.1.1 向更深的网络出发

8.1.2 进一步提高识别精度

8.1.3 加深层的动机

下面我们说一下加深层的好处。其中一个好处就是可以减少网络的参数数量。说得详细一点,就是与没有加深层的网络相比,加深了层的网络可以用更少的参数达到同等水平(或者更强)的表现力。这一点结合卷积运算中的滤波器大小来思考就好理解了。

8.2 深度学习的小历史

8.2.1 ImageNet
8.2.2 VGG
8.2.3 GoogLeNet
8.2.4 ResNet

8.3 深度学习的高速化

8.3.1 需要努力解决的问题
8.3.2 基于GPU的高速化
8.3.3 分布式学习
8.3.4 运算精度的位数缩减

……
参考链接:

深度学习入门:基于Python的理论与实现
https://www.ituring.com.cn/book/1921
https://github.com/oreilly-japan/deep-learning-from-scratch

《深度学习入门:基于Python的理论与实现》电子版及配套代码
https://github.com/qiaohaoforever/DeepLearningFromScratch
https://github.com/chapin666/books/tree/master/ai

《深度学习入门:基于python的理论与实现》
https://zhuanlan.zhihu.com/p/598623709

=END=


《 “[read]深度学习入门:基于Python的理论与实现” 》 有 4 条评论

  1. 什么是批标准化 (Batch Normalization)
    https://zhuanlan.zhihu.com/p/24810318
    `
    数学是达成目的的工具, 理解才是达成目的桥梁, 所以这篇文章用浅显易懂的动画阐述了复杂的机器学习概念.

    普通数据标准化
    Batch Normalization, 批标准化, 和普通的数据标准化类似, 是将分散的数据统一的一种做法, 也是优化神经网络的一种方法. 在之前 Normalization 的简介视频中我们一提到, 具有统一规格的数据, 能让机器学习更容易学习到数据之中的规律.

    每层都做标准化
    在神经网络中, 数据分布对训练会产生影响. 比如某个神经元 x 的值为1, 某个 Weights 的初始值为 0.1, 这样后一层神经元计算结果就是 Wx = 0.1; 又或者 x = 20, 这样 Wx 的结果就为 2. 现在还不能看出什么问题, 但是, 当我们加上一层激励函数, 激活这个 Wx 值的时候, 问题就来了. 如果使用像 tanh 的激励函数, Wx 的激活值就变成了 ~0.1 和 ~1, 接近于 1 的部已经处在了激励函数的饱和阶段, 也就是如果 x 无论再怎么扩大, tanh 激励函数输出值也还是接近1. 换句话说, 神经网络在初始阶段已经不对那些比较大的 x 特征范围敏感了. 这样很糟糕, 想象我轻轻拍自己的感觉和重重打自己的感觉居然没什么差别, 这就证明我的感官系统失效了. 当然我们是可以用之前提到的对数据做 normalization 预处理, 使得输入的 x 变化范围不会太大, 让输入值经过激励函数的敏感部分. 但刚刚这个不敏感问题不仅仅发生在神经网络的输入层, 而且在隐藏层中也经常会发生.
    只是时候 x 换到了隐藏层当中, 我们能不能对隐藏层的输入结果进行像之前那样的normalization 处理呢? 答案是可以的, 因为大牛们发明了一种技术, 叫做 batch normalization, 正是处理这种情况.

    BN 添加位置
    Batch normalization 的 batch 是批数据, 把数据分成小批小批进行 stochastic gradient descent. 而且在每批数据进行前向传递 forward propagation 的时候, 对每一层都进行 normalization 的处理

    BN 效果
    Batch normalization 也可以被看做一个层面. 在一层层的添加神经网络的时候, 我们先有数据 X, 再添加全连接层, 全连接层的计算结果会经过 激励函数 成为下一层的输入, 接着重复之前的操作. Batch Normalization (BN) 就被添加在每一个全连接和激励函数之间.
    之前说过, 计算结果在进入激励函数前的值很重要, 如果我们不单单看一个值, 我们可以说, 计算结果值的分布对于激励函数很重要. 对于数据值大多分布在这个区间的数据, 才能进行更有效的传递. 对比这两个在激活之前的值的分布. 上者没有进行 normalization, 下者进行了 normalization, 这样当然是下者能够更有效地利用 tanh 进行非线性化的过程.
    `

    7.5. 批量规范化
    https://zh.d2l.ai/chapter_convolutional-modern/batch-norm.html

    Batch normalization in 3 levels of understanding
    https://towardsdatascience.com/batch-normalization-in-3-levels-of-understanding-14c2da90a338

    Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
    http://static.googleusercontent.com/media/research.google.com/zh-CN//pubs/archive/43442.pdf

  2. 机器学习的通俗讲解
    Machine Learning for Everyone – In simple words. With real-world examples. Yes, again
    https://vas3k.com/blog/machine_learning/
    `
    Why do we want machines to learn?

    Three components of machine learning
    Data,Features,Algorithms

    Learning vs Intelligence

    The map of the machine learning world

    Part 1. Classical Machine Learning

    1.1 Supervised Learning
    Classification
    Regression

    1.2 Unsupervised learning
    Clustering
    Dimensionality Reduction (Generalization)
    Association rule learning

    Part 2. Reinforcement Learning
    强化学习现在被广泛用于:
    自动驾驶
    游戏
    自动化交易
    企业资源管理

    Part 3. Ensemble Methods
    Stacking
    Bagging
    Boosting

    Part 4. Neural Networks and Deep Leaning
    Convolutional Neural Networks (CNN)
    Recurrent Neural Networks (RNN)
    神经网络和深度学习现在被广泛用于:
    替换以上所有算法
    照片和视频上的物体识别
    语音识别与合成
    图像处理,风格转换
    机器翻译

    The End: when the war with the machines?
    要相信人类大脑的可能性是无限的,我们可以借助机器等工具扩展我们大脑的能力,所以别总想着“机器什么时候会变得比我们更聪明,并奴役所有人?”这种问题了。
    `

  3. 我推荐一篇名为《神经网络动物园》(Neural Network Zoo)的好文章,其中收集并简要介绍了几乎所有类型的神经网络。
    https://www.asimovinstitute.org/neural-network-zoo/
    `
    Feed forward neural networks (FF or FFNN) and perceptrons (P)
    Radial basis function (RBF)
    Recurrent neural networks (RNN)
    Long / short term memory (LSTM)
    Gated recurrent units (GRU)
    Bidirectional recurrent neural networks, bidirectional long / short term memory networks and bidirectional gated recurrent units (BiRNN, BiLSTM and BiGRU respectively)
    Autoencoders (AE)
    Variational autoencoders (VAE)
    Denoising autoencoders (DAE)
    Sparse autoencoders (SAE)
    Markov chains (MC or discrete time Markov Chain, DTMC)
    Hopfield network (HN)
    Boltzmann machines (BM)
    Restricted Boltzmann machines (RBM)
    Deep belief networks (DBN)
    Convolutional neural networks (CNN or deep convolutional neural networks, DCNN)
    Deconvolutional networks (DN)
    Deep convolutional inverse graphics networks (DCIGN)
    Generative adversarial networks (GAN)
    Liquid state machines (LSM)
    Extreme learning machines (ELM)
    Echo state networks (ESN)
    Deep residual networks (DRN)
    Neural Turing machines (NTM)
    Differentiable Neural Computers (DNC)
    Capsule Networks (CapsNet)
    Kohonen networks (KN, also self organising (feature) map, SOM, SOFM)
    Attention networks (AN)
    `

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注