动⼿手学深度学习 PYTORCH 版(DEMO)
(https://github.com/ShusenTang/Dive-into-DL-PyTorch)
PDF 制作by [Marcus Yang](https://github.com/chenyang1999)
深度学习简介
(注:此节完全同原⽂文,为了了完整性⽽而搬运过来) 你可能已经接触过编程,并开发过⼀一两款程序。同时
你可能读过关于深度学习或者机器器学习的铺天盖地的报道,尽管很多时候它们被赋予了了更更⼴广义的名字:
⼈人⼯工智能。实际上,或者说幸运的是,⼤大部分程序并不不需要深度学习或者是更更⼴广义上的⼈人⼯工智能技术。
例例如,如果我们要为⼀一台微波炉编写⼀一个⽤用户界⾯面,只需要⼀一点⼉儿⼯工夫我们便便能设计出⼗十⼏几个按钮以及
⼀一系列列能精确描述微波炉在各种情况下的表现的规则。再⽐比如,假设我们要编写⼀一个电⼦子邮件客户端。
这样的程序⽐比微波炉要复杂⼀一些,但我们还是可以沉下⼼心来⼀一步⼀一步思考:客户端的⽤用户界⾯面将需要⼏几
个输⼊入框来接受收件⼈人、主题、邮件正⽂文等,程序将监听键盘输⼊入并写⼊入⼀一个缓冲区,然后将它们显示
在相应的输⼊入框中。当⽤用户点击“发送”按钮时,我们需要检查收件⼈人邮箱地址的格式是否正确,并检查
邮件主题是否为空,或在主题为空时警告⽤用户,⽽而后⽤用相应的协议传送邮件。
值得注意的是,在以上两个例例⼦子中,我们都不不需要收集真实世界中的数据,也不不需要系统地提取这些数
据的特征。只要有充⾜足的时间,我们的常识与编程技巧已经⾜足够让我们完成任务。
与此同时,我们很容易易就能找到⼀一些连世界上最好的程序员也⽆无法仅⽤用编程技巧解决的简单问题。例例
如,假设我们想要编写⼀一个判定⼀一张图像中有没有猫的程序。这件事听起来好像很简单,对不不对?程序
只需要对每张输⼊入图像输出“真”(表示有猫)或者“假”(表示⽆无猫)即可。但令⼈人惊讶的是,即使是世
界上最优秀的计算机科学家和程序员也不不懂如何编写这样的程序。
我们该从哪⾥里里⼊入⼿手呢?我们先进⼀一步简化这个问题:若假设所有图像的⾼高和宽都是同样的400像素⼤大
⼩小,⼀一个像素由红绿蓝三个值构成,那么⼀一张图像就由近50万个数值表示。那么哪些数值隐藏着我们需
要的信息呢?是所有数值的平均数,还是四个⻆角的数值,抑或是图像中的某⼀一个特别的点?事实上,要
想解读图像中的内容,需要寻找仅仅在结合成千上万的数值时才会出现的特征,如边缘、质地、形状、
眼睛、⿐鼻⼦子等,最终才能判断图像中是否有猫。
⼀一种解决以上问题的思路路是逆向思考。与其设计⼀一个解决问题的程序,不不如从最终的需求⼊入⼿手来寻找⼀一
个解决⽅方案。事实上,这也是⽬目前的机器器学习和深度学习应⽤用共同的核⼼心思想:我们可以称其为“⽤用数
据编程”。与其枯坐在房间⾥里里思考怎么设计⼀一个识别猫的程序,不不如利利⽤用⼈人类⾁肉眼在图像中识别猫的能
⼒力力。我们可以收集⼀一些已知包含猫与不不包含猫的真实图像,然后我们的⽬目标就转化成如何从这些图像⼊入
⼿手得到⼀一个可以推断出图像中是否有猫的函数。这个函数的形式通常通过我们的知识来针对特定问题选
定。例例如,我们使⽤用⼀一个⼆二次函数来判断图像中是否有猫,但是像⼆二次函数系数值这样的函数参数的具
体值则是通过数据来确定。
通俗来说,机器器学习是⼀一⻔门讨论各式各样的适⽤用于不不同问题的函数形式,以及如何使⽤用数据来有效地获
取函数参数具体值的学科。深度学习是指机器器学习中的⼀一类函数,它们的形式通常为多层神经⽹网络。近
年年来,仰仗着⼤大数据集和强⼤大的硬件,深度学习已逐渐成为处理理图像、⽂文本语料料和声⾳音信号等复杂⾼高维
度数据的主要⽅方法。
我们现在正处于⼀一个程序设计得到深度学习的帮助越来越多的时代。这可以说是计算机科学历史上的⼀一
个分⽔水岭。举个例例⼦子,深度学习已经在你的⼿手机⾥里里:拼写校正、语⾳音识别、认出社交媒体照⽚片⾥里里的好友
们等。得益于优秀的算法、快速⽽而廉价的算⼒力力、前所未有的⼤大量量数据以及强⼤大的软件⼯工具,如今⼤大多数
软件⼯工程师都有能⼒力力建⽴立复杂的模型来解决⼗十年年前连最优秀的科学家都觉得棘⼿手的问题。
本书希望能帮助读者进⼊入深度学习的浪潮中。我们希望结合数学、代码和样例例让深度学习变得触⼿手可
及。本书不不要求具有⾼高深的数学或编程背景,我们将随着章节的发展逐⼀一解释所需要的知识。更更值得⼀一
提的是,本书的每⼀一节都是⼀一个可以独⽴立运⾏行行的Jupyter记事本。读者可以从⽹网上获得这些记事本,并
且可以在个⼈人电脑或云端服务器器上执⾏行行它们。这样读者就可以随意改动书中的代码并得到及时反馈。我
们希望本书能帮助和启发新⼀一代的程序员、创业者、统计学家、⽣生物学家,以及所有对深度学习感兴趣
的⼈人。
动⼿手学深度学习 Pytorch 版(demo)
深度学习简介
起源
发展
成功案例例
特点
⼩小结
练习
参考⽂文献
2.1 环境配置
2.1.1 Anaconda
2.1.2 Jupyter
2.1.3 PyTorch
2.1.4 其他
2.2 数据操作
2.2.1 创建 Tensor
2.2.2 操作
算术操作
索引
改变形状
线性代数
2.2.3 ⼴广播机制
2.2.4 运算的内存开销
2.2.5 Tensor 和NumPy相互转换
Tensor 转NumPy
NumPy数组转 Tensor
2.2.6 Tensor on GPU
2.3 ⾃自动求梯度
2.3.1 概念
2.3.2 Tensor
2.3.2 梯度
3.1 线性回归
3.1.1 线性回归的基本要素
3.1.1.1 模型定义
3.1.1.2 模型训练
(1) 训练数据
(2) 损失函数
(3) 优化算法
3.1.1.3 模型预测
3.1.2 线性回归的表示⽅方法
3.1.2.1 神经⽹网络图
3.1.2.2 ⽮矢量量计算表达式
⼩小结
3.2 线性回归的从零开始实现
3.2.1 ⽣生成数据集
3.2.2 读取数据
3.2.3 初始化模型参数
3.2.4 定义模型
3.2.5 定义损失函数
3.2.6 定义优化算法
3.2.7 训练模型
⼩小结
3.3 线性回归的简洁实现
3.3.1 ⽣生成数据集
3.3.2 读取数据
3.3.3 定义模型
3.3.4 初始化模型参数
3.3.5 定义损失函数
3.3.6 定义优化算法
3.3.7 训练模型
⼩小结
3.4 softmax回归
3.4.1 分类问题
3.4.2 softmax回归模型
3.4.3 单样本分类的⽮矢量量计算表达式
3.4.4 ⼩小批量量样本分类的⽮矢量量计算表达式
3.4.5 交叉熵损失函数
3.4.6 模型预测及评价
⼩小结
3.5 图像分类数据集(Fashion-MNIST)
3.5.1 获取数据集
3.5.2 读取⼩小批量量
⼩小结
参考⽂文献
3.6 softmax回归的从零开始实现
3.6.1 获取和读取数据
3.6.2 初始化模型参数
3.6.3 实现softmax运算
3.6.4 定义模型
3.6.5 定义损失函数
3.6.6 计算分类准确率
3.6.7 训练模型
3.6.8 预测
⼩小结
3.7 softmax回归的简洁实现
3.7.1 获取和读取数据
3.7.2 定义和初始化模型
3.7.3 softmax和交叉熵损失函数
3.7.4 定义优化算法
3.7.5 训练模型
⼩小结
3.8 多层感知机
3.8.1 隐藏层
3.8.2 激活函数
3.8.2.1 ReLU函数
3.8.2.2 sigmoid函数
3.8.2.3 tanh函数
3.8.3 多层感知机
⼩小结
3.9 多层感知机的从零开始实现
3.9.1 获取和读取数据
3.9.2 定义模型参数
3.9.3 定义激活函数
3.9.4 定义模型
3.9.5 定义损失函数
3.9.6 训练模型
⼩小结
3.10 多层感知机的简洁实现
3.10.1 定义模型
3.10.2 读取数据并训练模型
⼩小结
3.11 模型选择、⽋欠拟合和过拟合
3.11.1 训练误差和泛化误差
3.11.2 模型选择
3.11.2.1 验证数据集
3.11.2.3 折交叉验证
3.11.3 ⽋欠拟合和过拟合
3.11.3.1 模型复杂度
3.11.3.2 训练数据集⼤大⼩小
3.11.4 多项式函数拟合实验
3.11.4.1 ⽣生成数据集
3.11.4.2 定义、训练和测试模型
3.11.4.3 三阶多项式函数拟合(正常)
3.11.4.4 线性函数拟合(⽋欠拟合)
3.11.4.5 训练样本不不⾜足(过拟合)
⼩小结
3.12 权重衰减
3.12.1 ⽅方法
3.12.2 ⾼高维线性回归实验
3.12.3 从零开始实现
3.12.3.1 初始化模型参数
3.12.3.2 定义 范数惩罚项
3.12.3.3 定义训练和测试
3.12.3.4 观察过拟合
3.12.3.5 使⽤用权重衰减
3.12.4 简洁实现
⼩小结
3.13 丢弃法
3.13.1 ⽅方法
3.13.2 从零开始实现
3.13.2.1 定义模型参数
3.13.2.2 定义模型
3.13.2.3 训练和测试模型
3.13.3 简洁实现
⼩小结
参考⽂文献
3.14 正向传播、反向传播和计算图
3.14.1 正向传播
3.14.2 正向传播的计算图
3.14.3 反向传播
3.14.4 训练深度学习模型
⼩小结
3.15 数值稳定性和模型初始化
3.15.1 衰减和爆炸
3.15.2 随机初始化模型参数
3.15.2.1 PyTorch的默认随机初始化
3.15.2.2 Xavier随机初始化
⼩小结
参考⽂文献
3.16 实战Kaggle⽐比赛:房价预测
3.16.1 Kaggle⽐比赛
3.16.2 获取和读取数据集
3.16.3 预处理理数据
3.16.4 训练模型
3.16.5 折交叉验证
3.16.6 模型选择
3.16.7 预测并在Kaggle提交结果
⼩小结
4.1 模型构造
4.1.1 继承 Module 类来构造模型
4.1.2 Module 的⼦子类
4.1.2.1 Sequential 类
4.1.2.2 ModuleList 类
4.1.2.3 ModuleDict 类
4.1.3 构造复杂的模型
⼩小结
4.2 模型参数的访问、初始化和共享
4.2.1 访问模型参数
4.2.2 初始化模型参数
4.2.3 ⾃自定义初始化⽅方法
4.2.4 共享模型参数
⼩小结
4.3 模型参数的延后初始化
4.4 ⾃自定义层
4.4.1 不不含模型参数的⾃自定义层
4.4.2 含模型参数的⾃自定义层
⼩小结
4.5 读取和存储
4.5.1 读写 Tensor
4.5.2 读写模型
4.5.2.1 state_dict
4.5.2.2 保存和加载模型
1. 保存和加载 state_dict (推荐⽅方式)
2. 保存和加载整个模型
⼩小结
4.6 GPU计算
4.6.1 计算设备
4.6.2 Tensor 的GPU计算
4.6.3 模型的GPU计算
⼩小结
5.1 ⼆二维卷积层
5.1.1 ⼆二维互相关运算
5.1.2 ⼆二维卷积层
5.1.3 图像中物体边缘检测
5.1.4 通过数据学习核数组
5.1.5 互相关运算和卷积运算
5.1.6 特征图和感受野
⼩小结
5.2 填充和步幅
5.2.1 填充