【李沐】动手学深度学习 学习笔记

chenxiaowai_ 2024-09-03 09:35:02 阅读 97

目录

【内容介绍】动手学深度学习-基于pytorch版本【脉络梳理】预备知识数据操作数据预处理线性代数矩阵计算自动求导

线性神经网络线性回归深度学习的基础优化算法线性回归的从零开始实现线性回归的简洁实现Softmax回归损失函数图像分类数据集Softmax回归的从零开始实现Softmax回归的简洁实现

多层感知机感知机多层感知机多层感知机的从零开始实现多层感知机的简洁实现模型选择过拟合和欠拟合权重衰退暂退法(Dropout)数值稳定性模型初始化和激活函数

深度学习计算层和块参数管理自定义层读写文件

卷积神经网络从全连接层到卷积图像卷积填充和步幅多输入多输出通道池化层(汇聚层)LeNet

现代卷积神经网络深度卷积神经网络(AlexNet)使用块的网络(VGG)网络中的网络(NiN)含并行连结的网络(GoogLeNet)批量规范化(归一化)残差网络(ResNet)

计算性能深度学习硬件(CPU和GPU)深度学习硬件(TPU和其他)单机多卡并行分布式训练

计算机视觉图像增广微调物体检测和数据集锚框物体检测算法:R-CNN,SSD,YOLO单发多框检测(SSD)YOLO语义分割转置卷积全连接卷积神经网络 FCN样式迁移

循环神经网络序列模型语言模型循环神经网络

现代循环神经网络门控循环单元GRU长短期记忆网络(LSTM)深度循环神经网络双向循环神经网络编码器-解码器序列到序列学习束搜索注意力机制注意力分数使用注意力机制的seq2seq自注意力Transformer

自然语言处理:预训练BERT预训练

自然语言处理:应用BERT微调

优化算法优化算法

【内容介绍】动手学深度学习-基于pytorch版本

你好! 这是【李沐】动手学深度学习v2-基于pytorch版本的学习笔记

教材

源代码

安装教程(安装pytorch不要用pip,改成conda,pip太慢了,下载不下来)

个人推荐学习学习笔记

【脉络梳理】

预备知识

数据操作

本节代码文件在源代码文件的chapter_preliminaries/ndarray.ipynb中

创建数组

创建数组需要:

①形状

②每个元素的数据类型

③每个元素的值访问元素

①一个元素:[1,2]

②一行:[1,:]

③一列:[:,1]

④子区域:[1:3,1:] #第1到2行,第1到最后1列

⑤子区域:[::3,::2] #从第0行开始,每3行一跳,从第0列开始,每2列一跳。

数据预处理

本节代码文件在源代码文件的chapter_preliminaries/pandas.ipynb中

reshape函数

使用reshape函数后不指向同一块内存,但数据改变是同步的

<code>import torch

a=torch.arange(12)

b=a.reshape((3,4))

b[:]=2 # 改变b,a也会随之改变

print(a) # tensor([2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

a[:]=1 # 改变a,b也会随之改变

print(b) # tensor([[1, 1, 1, 1],[1, 1, 1, 1],[1, 1, 1, 1]])

print(id(b)==id(a)) # False

# 但a、b内存不同

print(id(a)) # 2157597781424

print(id(b)) # 2157597781424

线性代数

本节代码文件在源代码文件的chapter_preliminaries/linear-algebra.ipynb中

张量的按元素操作

标量、向量、矩阵和任意数量轴的张量(统称为张量)有一些实用的属性。 例如,你可能已经从按元素操作的定义中注意到,任何按元素的一元运算都不会改变其操作数的形状。 同样,给定具有相同形状的任意两个张量,任何按元素二元运算的结果都将是相同形状的张量。

例如,将两个相同形状的矩阵相加,会在这两个矩阵上执行按元素加法;两个矩阵的按元素乘法称为Hadamard积(Hadamard product)(数学符号

\bigodot

⨀)。 对于矩阵

A

R

m

n

,

B

R

m

n

\bf A\in\mathbb R^{mn},\bf B\in\mathbb R^{mn}

A∈Rmn,B∈Rmn, 其中第

i

\it i

i行和第

j

\it j

j列的元素是

b

i

j

b_{ij}

bij​。 矩阵

A

\bf A

A和

B

\bf B

B的Hadamard积为

在这里插入图片描述

<code>import torch

A = torch.arange(20, dtype=torch.float32).reshape(5, 4)

B = A.clone() # 通过分配新内存,将A的一个副本分配给B

print(A)

#tensor([[ 0., 1., 2., 3.],[ 4., 5., 6., 7.],[ 8., 9., 10., 11.],[12., 13., 14., 15.],[16., 17., 18., 19.]])

print(A+B)

#tensor([[ 0., 2., 4., 6.],[ 8., 10., 12., 14.],[ 16., 18., 20., 22.],[24., 26., 28., 30.],[32., 34., 36., 38.]])

print(A*B)

#tensor([[0., 1., 4., 9.],[16., 25., 36., 49.],[64., 81., 100., 121.],[144., 169., 196., 225.],[256., 289., 324., 361.]])

降维求和

①原始shape:[5,4]

· axis=0 sum:[ 4 ]

· axis=1 sum:[ 5 ]

②原始shape:[2,5,4]

· axis=1 sum:[2,4]

· axis=2 sum:[2,5]

· axis=[1,2] sum:[ 4 ]非降维求和

原始shape:[2,5,4] 参数 keepdims=True

· axis=1 sum:[2,1,4]

· axis=1 sum:[2,1,1]

矩阵计算

本节代码文件在源代码文件的chapter_preliminaries/calculus.ipynb中

将导数拓展到向量

将导数拓展到向量

标量对列向量求导

其中,

a

不是关于

x

的函数,

0

1

是向量

;

其中,\it a不是关于\bf x的函数,\color{black} 0和\bf 1是向量;

其中,a不是关于x的函数,0和1是向量;

在这里插入图片描述

列向量对列向量求导

结果是矩阵

列向量对列向量求导公式

样例:

x

R

n

,

y

R

m

,

y

x

R

m

n

;

a

,

a

A

不是关于

x

的函数,

0

I

是矩阵

;

\bf x\in\mathbb R^{n} ,\bf y\in\mathbb R^{m},\frac{\partial\bf y}{\partial\bf x}\in\mathbb R^{mn};\it a,\bf a和\bf A不是关于\bf x的函数,\color{black} 0和\bf I是矩阵;

x∈Rn,y∈Rm,∂x∂y​∈Rmn;a,a和A不是关于x的函数,0和I是矩阵;

列向量对列向量求导样例

将导数拓展到矩阵

将导数拓展到矩阵

自动求导

本节代码文件在源代码文件的chapter_preliminaries/autograd.ipynb中

向量链式法则

链式法则拓展到向量

样例:

链式法则拓展到向量的样例

自动求导的两种模式

在这里插入图片描述

反向累积模式

在这里插入图片描述

样例:

反向累积模式样例

正向累积与反向累积复杂度比较

正向累积内存复杂度为O(1),反向累积内存复杂度为O(n);但神经网络通常不会用正向累积,因为正向累积每计算一个变量的梯度都需要扫一遍,计算复杂度太高。

正向累积与反向累积复杂度比较

线性神经网络

线性回归

本节代码文件在源代码文件的chapter_linear-networks/linear-regression.ipynb中

线性模型

线性模型

线性模型可以看做是单层神经网络:

线性模型可以看做是单层神经网络

衡量预估质量(损失函数):

衡量预估质量

训练数据

训练数据

参数学习

参数学习

显示解:

显示解

总结

总结

深度学习的基础优化算法

梯度下降

通过不断地在损失函数递减的方向上更新参数来降低误差。

梯度下降

学习率不能太大也不能太小:

学习率不能太大也不能太小

小批量随机梯度下降

小批量随机梯度下降

批量大小不能太大也不能太小:

批量大小不能太大也不能太小

总结

总结

线性回归的从零开始实现

本节代码文件在源代码文件的chapter_linear-networks/linear-regression-scratch.ipynb中

实现流程

其中,定义模型包括定义损失函数和定义优化算法

线性回归的简洁实现

本节代码文件在源代码文件的chapter_linear-networks/linear-regression-concise.ipynb中

简洁实现是指通过使用深度学习框架来实现线性回归模型,具体流程与从零开始实现大体相同,不过一些常用函数不需要我们自己写了(直接导库,用别人写好的)

实现流程

Softmax回归

本节代码文件在源代码文件的chapter_linear-networks/softmax-regression.ipynb中

回归vs分类(从回归到多类分类)

回归估计一个连续值;分类预测一个离散类别。

从回归到多类分类

从回归到多类分类 — 均方损失

均方损失

从回归到多类分类 — 无校验比例

无校验比例

从回归到多类分类 — 校验比例

校验比例

Softmax和交叉熵损失

Softmax和交叉熵损失

总结

总结

损失函数

本节代码文件在源代码文件的chapter_linear-networks/softmax-regression.ipynb中

损失函数用来衡量预测值与真实值之间的区别,是机器学习里非常重要的概念。下面介绍三种常用的损失函数。

①L2 Loss

l

(

y

,

y

)

=

y

y

\it l(y,y') = \mid y-y' \mid

l(y,y′)=∣y−y′∣

L2 Loss

蓝色曲线:表示当y=0时,变换预测值y’。

绿色曲线:表示似然函数。

橙色曲线:表示损失函数的梯度,可以发现,当y与y’相差较大的时候,梯度的绝对值也较大。②L1 Loss

l

(

y

,

y

)

=

1

2

(

y

y

)

2

\it l(y,y') = \frac{1}{2} ( y-y')^2

l(y,y′)=21​(y−y′)2

L1 Loss

蓝色曲线:表示当y=0时,变换预测值y’。

绿色曲线:表示似然函数。

橙色曲线:表示损失函数的梯度,可以发现,当y’>0时,导数为1,当y’<0时,导数为-1。③Huber’s Robust Loss(鲁棒损失)

Huber's Robust Loss(鲁棒损失)

蓝色曲线:表示当y=0时,变换预测值y’。

绿色曲线:表示似然函数。

橙色曲线:表示损失函数的梯度。

图像分类数据集

本节代码文件在源代码文件的chapter_linear-networks/image-classification-dataset.ipynb中

MNIST数据集

是图像分类中广泛使用的数据集之一,但作为基准数据集过于简单。 我们将使用类似但更复杂的Fashion-MNIST数据集。Fashion-MNIST数据集

Fashion-MNIST由10个类别的图像组成,分别为t-shirt(T恤)、trouser(裤子)、pullover(套衫)、dress(连衣裙)、coat(外套)、sandal(凉鞋)、shirt(衬衫)、sneaker(运动鞋)、bag(包)和ankle boot(短靴)。

每个类别由训练数据集(train dataset)中的6000张图像 和测试数据集(test dataset)中的1000张图像组成。

每个输入图像的高度和宽度均为28像素。 数据集由灰度图像组成,其通道数为1。

Softmax回归的从零开始实现

本节代码文件在源代码文件的chapter_linear-networks/softmax-regression-scratch.ipynb中

实现流程

我们使用Fashion-MNIST数据集, 并设置数据迭代器的批量大小为256。每个样本都将用固定长度的向量表示。 原始数据集中的每个样本都是 28×28 的图像。 在本节中,我们将展平每个图像,把它们看作长度为784的向量。 在后面的章节中,我们将讨论能够利用图像空间结构的特征, 但现在我们暂时只把每个像素位置看作一个特征。

分类精度即正确预测数量与总预测数量之比

Softmax回归的简洁实现

本节代码文件在源代码文件的chapter_linear-networks/softmax-regression-concise.ipynb中

通过深度学习框架的高级API也能更方便地实现softmax回归模型。

实现流程

本节 继续使用Fashion-MNIST数据集,并保持批量大小为256。

多层感知机

感知机

感知机

感知机

感知机与回归和Softmax回归的区别

感知机是二分类(1或-1),而回归的输出是实数,Softmax回归的输出是概率。训练感知机

训练感知机

收敛定理

收敛定理

XOR问题

XOR问题

总结

在这里插入图片描述

多层感知机

本节代码文件在源代码文件的chapter_multilayer-perceptrons/mlp.ipynb中

学习XOR

学习XOR

单隐藏层

隐藏层大小是超参数(输入和输出大小由数据决定,输出大小人为决定。)

单隐藏层

单隐藏层 — 单分类

只有一个输出,即输出是标量。

单隐藏层 --- 单分类

Q:为什么需要非线性的激活函数?(σ(x)不可以等于x,也不可以等于nx)

A: 如果激活函数是线性的,那么单隐藏层的多层感知机就变成了最简单的线性模型。

在这里插入图片描述

激活函数

①Sigmoid 激活函数

Sigmoid 激活函数

②Tanh 激活函数

Tanh 激活函数

③ReLU 激活函数

ReLU 激活函数

单隐藏层 — 多类分类

单隐藏层 --- 多类分类

多隐藏层

多隐藏层

总结

在这里插入图片描述

多层感知机的从零开始实现

本节代码文件在源代码文件的chapter_multilayer-perceptrons/mlp-scratch.ipynb中

实现流程

我们实现一个具有单隐藏层的多层感知机, 它包含256个隐藏单元。 注意,我们可以将这两个变量都视为超参数。 通常,我们选择2的若干次幂作为层的宽度。 因为内存在硬件中的分配和寻址方式,这么做往往可以在计算上更高效。

多层感知机的简洁实现

本节代码文件在源代码文件的chapter_multilayer-perceptrons/mlp-concise.ipynb中

与softmax回归的简洁实现相比

唯一的区别是我们添加了2个全连接层(之前我们只添加了1个全连接层)。第一层是隐藏层,它包含256个隐藏单元,并使用了ReLU激活函数。第二层是输出层。

训练过程的实现与我们实现softmax回归时完全相同。

模型选择

本节代码文件在源代码文件的chapter_multilayer-perceptrons/underfit-overfit.ipynb中

训练误差和泛化误差

训练误差和泛化误差

验证数据集和测试数据集

验证数据集和测试数据集

K-折交叉验证

K-折交叉验证

总结

总结

过拟合和欠拟合

本节代码文件在源代码文件的chapter_multilayer-perceptrons/underfit-overfit.ipynb中

过拟合和欠拟合

过拟合和欠拟合

过拟合和欠拟合

数据复杂度

数据复杂度

模型容量

模型容量

模型容量的影响

模型容量的影响

估计模型容量

估计模型容量

其中,d+1中的1是偏移,m是隐藏层大小,k是分类的类别数VC 维

VC 维

线性分类器的 VC 维

线性分类器的 VC 维

VC 维的用处

VC 维的用处

总结

总结

权重衰退

本节代码文件在源代码文件的chapter_multilayer-perceptrons/weight-decay.ipynb中

权重衰退是一种常见的处理过拟合(模型复杂度过高)的方法

使用均方范数作为硬性限制

使用均方范数作为硬性限制

使用均方范数作为柔性限制

使用均方范数作为柔性限制

演示对最优解的影响

演示对最优解的影响

参数更新法则

参数更新法则

总结

总结

暂退法(Dropout)

本节代码文件在源代码文件的chapter_multilayer-perceptrons/dropout.ipynb中

暂退法(丢弃法)的动机

暂退法的动机

无偏差的加入噪音

无偏差的加入噪音

使用丢弃法

使用丢弃法

推理中的丢弃法

推理中的丢弃法

总结

总结

数值稳定性

本节代码文件在源代码文件的chapter_multilayer-perceptrons/numerical-stability-and-init.ipynb中

神经网络的梯度

神经网络的梯度

其中,矩阵乘法容易带来梯度爆炸和梯度消失的问题数值稳定性的常见两个问题

数值稳定性的常见两个问题

例子:MLP

MLP

梯度爆炸

↑ ↑ ↑ 此时,就会造成梯度爆炸

梯度消失

梯度消失

↑ ↑ ↑ 此时,就会造成梯度消失梯度爆炸的问题

梯度爆炸的问题

梯度消失的问题

梯度消失的问题

总结

总结

模型初始化和激活函数

本节代码文件在源代码文件的chapter_multilayer-perceptrons/numerical-stability-and-init.ipynb中

让训练更加稳定

让训练更加稳定

让每层的方差是个常数

让每层的方差是个常数

权重初始化

权重初始化

例子:MLP

MLP

①假设没有激活函数:

假设没有激活函数

正向方差:

正向方差

反向均值和方差:

反向均值和方差

②假设线性的激活函数:

正向:

假设线性的激活函数

反向:

反向

Xavier 初始

Xavier 是一种常见的权重初始化方法

Xavier 初始

检查常用激活函数

检查常用激活函数

总结

总结

深度学习计算

层和块

本节代码文件在源代码文件的chapter_deep-learning-computation/model-construction.ipynb中

块的组成

块(block)可以描述单个层、由多个层组成的组件或整个模型本身。 使用块进行抽象的一个好处是可以将一些块组合成更大的组件, 这一过程通常是递归的。

块的组成

从编程的角度来看,块由类(class)表示。 它的任何子类都必须定义一个将其输入转换为输出的前向传播函数, 并且必须存储任何必需的参数。 注意,有些块不需要任何参数。 最后,为了计算梯度,块必须具有反向传播函数在定义我们自己的块时,由于自动微分提供了一些后端实现,我们只需要考虑前向传播函数和必需的参数。

块需要提供的基本功能

①将输入数据作为其前向传播函数的参数。

②通过前向传播函数来生成输出。注:输出的形状可能与输入的形状不同。

③计算其输出关于输入的梯度,可通过其反向传播函数进行访问。通常这是自动发生的。

④存储和访问前向传播计算所需的参数。

⑤根据需要初始化模型参数。

自定义块

在下面的代码片段中,我们从零开始编写一个块。 它包含一个多层感知机,其具有256个隐藏单元的隐藏层和一个10维输出层。 注意,下面的MLP类继承了表示块的类。我们的实现只需要提供我们自己的构造函数(Python中的__init__函数)和前向传播函数。

<code>class MLP(nn.Module):

# 用模型参数声明层。这里,我们声明两个全连接的层

def __init__(self):

# 调用MLP的父类Module的构造函数来执行必要的初始化。

# 这样,在类实例化时也可以指定其他函数参数,例如模型参数params(稍后将介绍)

super().__init__()

self.hidden = nn.Linear(20, 256) # 隐藏层

self.out = nn.Linear(256, 10) # 输出层

# 定义模型的前向传播,即如何根据输入X返回所需的模型输出

def forward(self, X):

# 注意,这里我们使用ReLU的函数版本,其在nn.functional模块中定义。

return self.out(F.relu(self.hidden(X)))

注意一些关键细节: 首先,我们定制的__init__函数通过super().init() 调用父类的__init__函数, 省去了重复编写模版代码的痛苦。 然后,我们实例化两个全连接层, 分别为self.hidden和self.out。 注意,除非我们实现一个新的运算符, 否则我们不必担心反向传播函数或参数初始化, 系统将自动生成这些。

顺序块

回想一下Sequential的设计是为了把其他模块串起来。 为了构建我们自己的简化的MySequential, 我们只需要定义两个关键函数:

①一种将块逐个追加到列表中的函数。

②一种前向传播函数,用于将输入按追加块的顺序传递给块组成的“链条”。

下面的MySequential类提供了与默认Sequential类相同的功能:

class MySequential(nn.Module):

def __init__(self, *args):

super().__init__()

for idx, module in enumerate(args):

# 这里,module是Module子类的一个实例。我们把它保存在'Module'类的成员

# 变量_modules中。_module的类型是OrderedDict

self._modules[str(idx)] = module

def forward(self, X):

# OrderedDict保证了按照成员添加的顺序遍历它们

for block in self._modules.values():

X = block(X)

return X

_modules:__init__函数将每个模块逐个添加到有序字典_modules中,_modules的主要优点是: 在模块的参数初始化过程中, 系统知道在_modules字典中查找需要初始化参数的子块。

参数管理

本节代码文件在源代码文件的chapter_deep-learning-computation/parameters.ipynb中

参数访问

为方便解释,先定义如下神经网络:

import torch

from torch import nn

net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))

X = torch.rand(size=(2, 4))

net(X)

我们从已有模型中访问参数。 当通过Sequential类定义模型时, 我们可以通过索引来访问模型的任意层。 这就像模型是一个列表一样,每层的参数都在其属性中。 如下所示,我们可以检查第二个全连接层的参数。

print(net[2].state_dict())

#OrderedDict([('weight', tensor([[ 0.0251, -0.2952, -0.1204, 0.3436, -0.3450, -0.0372, 0.0462, 0.2307]])), ('bias', tensor([0.2871]))])

提取目标参数

从第二个全连接层(即第三个神经网络层)提取偏置, 提取后返回的是一个参数类实例,并进一步访问该参数的值:

print(type(net[2].bias))

#<class 'torch.nn.parameter.Parameter'>

print(net[2].bias)

#Parameter containing:

#tensor([0.2871], requires_grad=True)

print(net[2].bias.data)

#tensor([0.2871])

参数是复合的对象,包含值、梯度和额外信息。 这就是我们需要显式参数值的原因。 除了值之外,我们还可以访问每个参数的梯度。 在上面这个网络中,由于我们还没有调用反向传播,所以参数的梯度处于初始状态。

print(net[2].weight.grad == None)

#True

一次性访问所有参数

当我们需要对所有参数执行操作时,逐个访问它们可能会很麻烦。 当我们处理更复杂的块(例如,嵌套块)时,情况可能会变得特别复杂, 因为我们需要递归整个树来提取每个子块的参数。 下面,我们将通过演示来比较访问第一个全连接层的参数访问所有层:

print(*[(name, param.shape) for name, param in net[0].named_parameters()])

#('weight', torch.Size([8, 4])) ('bias', torch.Size([8]))

print(*[(name, param.shape) for name, param in net.named_parameters()])

#('0.weight', torch.Size([8, 4])) ('0.bias', torch.Size([8])) ('2.weight', torch.Size([1, 8])) ('2.bias', torch.Size([1]))

这为我们提供了另一种访问网络参数的方式,如下所示:

net.state_dict()['2.bias'].data

#tensor([0.2871])

从嵌套块收集参数

我们首先定义一个生成块的函数(可以说是“块工厂”),然后将这些块组合到更大的块中。

def block1():

return nn.Sequential(nn.Linear(4, 8), nn.ReLU(),

nn.Linear(8, 4), nn.ReLU())

def block2():

net = nn.Sequential()

for i in range(4):

# 在这里嵌套

net.add_module(f'block { i}', block1())

return net

rgnet = nn.Sequential(block2(), nn.Linear(4, 1))

rgnet(X)

#tensor([[0.1713],

# [0.1713]], grad_fn=<AddmmBackward0>)

设计了网络后,我们看看它是如何工作的:

print(rgnet)

'''

Sequential(

(0): Sequential(

(block 0): Sequential(

(0): Linear(in_features=4, out_features=8, bias=True)

(1): ReLU()

(2): Linear(in_features=8, out_features=4, bias=True)

(3): ReLU()

)

(block 1): Sequential(

(0): Linear(in_features=4, out_features=8, bias=True)

(1): ReLU()

(2): Linear(in_features=8, out_features=4, bias=True)

(3): ReLU()

)

(block 2): Sequential(

(0): Linear(in_features=4, out_features=8, bias=True)

(1): ReLU()

(2): Linear(in_features=8, out_features=4, bias=True)

(3): ReLU()

)

(block 3): Sequential(

(0): Linear(in_features=4, out_features=8, bias=True)

(1): ReLU()

(2): Linear(in_features=8, out_features=4, bias=True)

(3): ReLU()

)

)

(1): Linear(in_features=4, out_features=1, bias=True)

)

'''

因为层是分层嵌套的,所以我们也可以像通过嵌套列表索引一样访问它们。 下面,我们访问第一个主要的块中、第二个子块的第一层的偏置项:

rgnet[0][1][0].bias.data

#tensor([-0.0444, -0.4451, -0.4149, 0.0549, -0.0969, 0.2053, -0.2514, 0.0220])

参数初始化

深度学习框架提供默认随机初始化, 也允许我们创建自定义初始化方法, 满足我们通过其他规则实现初始化权重。默认情况下,PyTorch会根据一个范围均匀地初始化权重和偏置矩阵, 这个范围是根据输入和输出维度计算出的。 PyTorch的nn.init模块提供了多种预置初始化方法。

①内置初始化

下面的代码将所有权重参数初始化为标准差为0.01的高斯随机变量, 且将偏置参数设置为0。

def init_normal(m):

if type(m) == nn.Linear:

nn.init.normal_(m.weight, mean=0, std=0.01)

nn.init.zeros_(m.bias)

net.apply(init_normal)

net[0].weight.data[0], net[0].bias.data[0]

#(tensor([-0.0017, 0.0232, -0.0026, 0.0026]), tensor(0.))

我们还可以将所有参数初始化为给定的常数,比如初始化为1:

def init_constant(m):

if type(m) == nn.Linear:

nn.init.constant_(m.weight, 1)

nn.init.zeros_(m.bias)

net.apply(init_constant)

net[0].weight.data[0], net[0].bias.data[0]

#(tensor([1., 1., 1., 1.]), tensor(0.))

我们还可以对某些块应用不同的初始化方法。 例如,下面我们使用Xavier初始化方法初始化第一个神经网络层, 然后将第三个神经网络层初始化为常量值42:

def xavier(m):

if type(m) == nn.Linear:

nn.init.xavier_uniform_(m.weight)

def init_42(m):

if type(m) == nn.Linear:

nn.init.constant_(m.weight, 42)

net[0].apply(xavier)

net[2].apply(init_42)

print(net[0].weight.data[0])

#tensor([-0.4645, 0.0062, -0.5186, 0.3513])

print(net[2].weight.data)

#tensor([[42., 42., 42., 42., 42., 42., 42., 42.]])

②自定义初始化

有时,深度学习框架没有提供我们需要的初始化方法。 在下面的例子中,我们使用以下的分布为任意权重参数 𝑤 定义初始化方法:

w

{

U

(

5

,

10

)

,

可能性1/4

0

,

可能性1/2

U

(

10

,

5

)

,

可能性1/4

w \backsim \begin{cases} U(5,10), & \text{可能性1/4} \\ 0, & \text{可能性1/2} \\ U(-10,-5), & \text{可能性1/4} \\ \end{cases}

w∽⎩

⎧​U(5,10),0,U(−10,−5),​可能性1/4可能性1/2可能性1/4​

def my_init(m):

if type(m) == nn.Linear:

print("Init", *[(name, param.shape)

for name, param in m.named_parameters()][0])

nn.init.uniform_(m.weight, -10, 10)

m.weight.data *= m.weight.data.abs() >= 5

'''

Init weight torch.Size([8, 4])

Init weight torch.Size([1, 8])

'''

net.apply(my_init)

net[0].weight[:2]

'''

tensor([[ 8.8025, 6.4078, 0.0000, -8.4598],

[-0.0000, 9.0582, 8.8258, 7.4997]], grad_fn=<SliceBackward0>)

'''

注意,我们始终可以直接设置参数:

net[0].weight.data[:] += 1

net[0].weight.data[0, 0] = 42

net[0].weight.data[0]

#tensor([42.0000, 7.4078, 1.0000, -7.4598])

参数绑定

有时我们希望在多个层间共享参数: 我们可以定义一个稠密层,然后使用它的参数来设置另一个层的参数。

# 我们需要给共享层一个名称,以便可以引用它的参数

shared = nn.Linear(8, 8)

net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),

shared, nn.ReLU(),

shared, nn.ReLU(),

nn.Linear(8, 1))

net(X)

# 检查参数是否相同

print(net[2].weight.data[0] == net[4].weight.data[0])

'''

tensor([True, True, True, True, True, True, True, True])

'''

net[2].weight.data[0, 0] = 100

# 确保它们实际上是同一个对象,而不只是有相同的值

print(net[2].weight.data[0] == net[4].weight.data[0])

'''

tensor([True, True, True, True, True, True, True, True])

'''

这个例子表明第三个和第五个神经网络层的参数是绑定的。 它们不仅值相等,而且由相同的张量表示。 因此,如果我们改变其中一个参数,另一个参数也会改变。 你可能会思考:当参数绑定时,梯度会发生什么情况? 答案是由于模型参数包含梯度,因此在反向传播期间第二个隐藏层 (即第三个神经网络层)和第三个隐藏层(即第五个神经网络层)的梯度会加在一起。

自定义层

本节代码文件在源代码文件的chapter_deep-learning-computation/custom-layer.ipynb中

不带参数的层

下面的CenteredLayer类要从其输入中减去均值。 要构建它,我们只需继承基础层类并实现前向传播功能。

import torch

import torch.nn.functional as F

from torch import nn

class CenteredLayer(nn.Module):

def __init__(self):

super().__init__()

def forward(self, X):

return X - X.mean()

让我们向该层提供一些数据,验证它是否能按预期工作。

layer = CenteredLayer()

layer(torch.FloatTensor([1, 2, 3, 4, 5]))

#tensor([-2., -1., 0., 1., 2.])

我们可以将层作为组件合并到更复杂的模型中,比如:

net = nn.Sequential(nn.Linear(8, 128), CenteredLayer())

带参数的层

下面我们定义具有参数的层, 这些参数可以通过训练进行调整。 我们可以使用内置函数来创建参数,这些函数提供一些基本的管理功能。 比如管理访问、初始化、共享、保存和加载模型参数。 这样做的好处之一是:我们不需要为每个自定义层编写自定义的序列化程序。

现在,让我们实现自定义版本的全连接层。该层需要两个参数,一个用于表示权重,另一个用于表示偏置项。 在此实现中,我们使用修正线性单元作为激活函数。该层需要输入参数:in_units和units,分别表示输入数(输入维度)和输出数(输出维度)。

class MyLinear(nn.Module):

def __init__(self, in_units, units):

super().__init__()

self.weight = nn.Parameter(torch.randn(in_units, units))

self.bias = nn.Parameter(torch.randn(units,))

def forward(self, X):

linear = torch.matmul(X, self.weight.data) + self.bias.data

return F.relu(linear)

linear = MyLinear(5, 3)

linear.weight

'''

Parameter containing:

tensor([[ 1.9054, -3.4102, -0.9792],

[ 1.5522, 0.8707, 0.6481],

[ 1.0974, 0.2568, 0.4034],

[ 0.1416, -1.1389, 0.5875],

[-0.7209, 0.4432, 0.1222]], requires_grad=True)

'''

我们可以使用自定义层直接执行前向传播计算:

linear(torch.rand(2, 5))

'''

tensor([[2.4784, 0.0000, 0.8991],

[3.6132, 0.0000, 1.1160]])

'''

我们还可以使用自定义层构建模型,就像使用内置的全连接层一样使用自定义层:

net = nn.Sequential(MyLinear(64, 8), MyLinear(8, 1))

net(torch.rand(2, 64))

'''

tensor([[0.],

[0.]])

'''

读写文件

本节代码文件在源代码文件的chapter_deep-learning-computation/read-write.ipynb中

有时我们希望保存训练的模型, 以备将来在各种环境中使用(比如在部署中进行预测)。 此外,当运行一个耗时较长的训练过程时, 最佳的做法是定期保存中间结果, 以确保在服务器电源被不小心断掉时,我们不会损失几天的计算结果。

加载和保存张量

对于单个张量,我们可以直接调用load和save函数分别读写它们。 这两个函数都要求我们提供一个名称,save要求将要保存的变量作为输入。

import torch

from torch import nn

from torch.nn import functional as F

x = torch.arange(4)

torch.save(x, 'x-file')

我们现在可以将存储在文件中的数据读回内存。

x2 = torch.load('x-file')

x2

#tensor([0, 1, 2, 3])

我们可以存储一个张量列表,然后把它们读回内存。

y = torch.zeros(4)

torch.save([x, y],'x-files')

x2, y2 = torch.load('x-files')

(x2, y2)

#(tensor([0, 1, 2, 3]), tensor([0., 0., 0., 0.]))

我们甚至可以写入或读取从字符串映射到张量的字典。 当我们要读取或写入模型中的所有权重时,这很方便。

mydict = { 'x': x, 'y': y}

torch.save(mydict, 'mydict')

mydict2 = torch.load('mydict')

mydict2

#{'x': tensor([0, 1, 2, 3]), 'y': tensor([0., 0., 0., 0.])}

加载和保存模型参数

保存单个权重向量(或其他张量)确实有用, 但是如果我们想保存整个模型,并在以后加载它们, 单独保存每个向量则会变得很麻烦。 毕竟,我们可能有数百个参数散布在各处。 因此,深度学习框架提供了内置函数来保存和加载整个网络。 需要注意的一个重要细节是,这将保存模型的参数而不是保存整个模型。 例如,如果我们有一个3层多层感知机,我们需要单独指定架构。 因为模型本身可以包含任意代码,所以模型本身难以序列化。 因此,为了恢复模型,我们需要用代码生成架构, 然后从磁盘加载参数。 让我们从熟悉的多层感知机开始尝试一下。

class MLP(nn.Module):

def __init__(self):

super().__init__()

self.hidden = nn.Linear(20, 256)

self.output = nn.Linear(256, 10)

def forward(self, x):

return self.output(F.relu(self.hidden(x)))

net = MLP()

X = torch.randn(size=(2, 20))

Y = net(X)

接下来,我们将模型的参数存储在一个叫做“mlp.params”的文件中。

torch.save(net.state_dict(), 'mlp.params')

为了恢复模型,我们实例化了原始多层感知机模型的一个备份。 这里我们不需要随机初始化模型参数,而是直接读取文件中存储的参数。

clone = MLP()

clone.load_state_dict(torch.load('mlp.params'))

clone.eval()

'''

MLP(

(hidden): Linear(in_features=20, out_features=256, bias=True)

(output): Linear(in_features=256, out_features=10, bias=True)

)

'''

由于两个实例具有相同的模型参数,在输入相同的X时, 两个实例的计算结果应该相同。 让我们来验证一下。

Y_clone = clone(X)

Y_clone == Y

'''

tensor([[True, True, True, True, True, True, True, True, True, True],

[True, True, True, True, True, True, True, True, True, True]])

'''

卷积神经网络

从全连接层到卷积

本节代码文件在源代码文件的chapter_convolutional-neural-networks/why-conv.ipynb中

重新考察全连接层

重新考察全连接层

平移不变性

不管检测对象出现在图像中的哪个位置,神经网络的前面几层应该对相同的图像区域具有相似的反应,即为“平移不变性”。

平移不变性

局部性

局部性

全连接层与卷积层的关系

总结

图像卷积

本节代码文件在源代码文件的chapter_convolutional-neural-networks/conv-layer.ipynb中

互相关运算

在卷积层中,输入张量和核张量通过互相关运算产生输出张量。

二维交叉相关

二维卷积层

不同的卷积核可以带来不同的效果:

不同的卷积核的举例

交叉相关vs卷积

交叉相关vs卷积

一维和三维交叉相关

一维和三维交叉相关

一维和三维交叉相关

总结

填充和步幅

本节代码文件在源代码文件的chapter_convolutional-neural-networks/padding-and-strides.ipynb中

填充和步幅是卷积层的两个控制输出大小的超参数

填充

填充

由于卷积核的宽度和高度通常大于1,在应用多层卷积时,我们常常丢失边缘像素。 由于我们通常使用小卷积核,因此对于任何单个卷积,我们可能只会丢失几个像素。 但随着我们应用许多连续卷积层,累积丢失的像素数就多了。 解决这个问题的简单方法即为填充:

填充

填充原则:

填充原则

步幅

步幅

有时候为了高效计算或是缩减采样次数,卷积窗口可以跳过中间位置,每次滑动多个元素。

步幅

步幅原则:

步幅原则

总结

总结

多输入多输出通道

本节代码文件在源代码文件的chapter_convolutional-neural-networks/channels.ipynb中

多个输入通道

多个输入通道

当输入包含多个通道时,需要构造一个与输入数据具有相同输入通道数的卷积核,以便与输入数据进行互相关运算。

多个输入通道

多个输入通道

多个输出通道

多个输出通道

多个输入和输出通道

多个输入和输出通道

1x1卷积层

1x1卷积层

二维卷积层

二维卷积层

总结

总结

池化层(汇聚层)

本节代码文件在源代码文件的chapter_convolutional-neural-networks/pooling.ipynb中

卷积层的缺点

卷积层的缺点

二维最大池化层

二维最大池化层

二维最大池化层

池化层vs卷积层

池化层没有可学习的参数,也不会融合多输入通道。

池化层vs卷积层

平均池化层

平均池化层

总结

总结

LeNet

本节代码文件在源代码文件的chapter_convolutional-neural-networks/lenet.ipynb中

手写数字识别

手写数字识别

MNIST数据集

MNIST数据集

LeNet

LeNet是最早发布的卷积神经网络之一,因其在计算机视觉任务中的高效性能而受到广泛关注。 这个模型是由AT&T贝尔实验室的研究员Yann LeCun在1989年提出的(并以其命名),目的是识别图像中的手写数字。 当时,LeNet取得了与支持向量机性能相媲美的成果,成为监督学习的主流方法。 LeNet被广泛用于自动取款机(ATM)机中,帮助识别处理支票的数字。 时至今日,一些自动取款机仍在运行Yann LeCun和他的同事Leon Bottou在上世纪90年代写的代码呢!

总体来看,LeNet(LeNet-5)由两个部分组成:

①卷积编码器:由两个卷积层组成。

②全连接层密集块:由三个全连接层组成。

LeNet

总结

总结

现代卷积神经网络

深度卷积神经网络(AlexNet)

本节代码文件在源代码文件的chapter_convolutional-modern/alexnet.ipynb中

机器学习VS神经网路

在上世纪90年代初到2012年之间的大部分时间里,神经网络往往被其他机器学习方法超越,如支持向量机(support vector machines)。

机器学习

计算机视觉与几何学

卷积神经网络通常用在计算机视觉,在2000年时,计算机视觉的知识主要来源于几何学。

几何学

计算机视觉与特征工程

15年前,计算机视觉中,最重要的是特征工程。

特征工程

深度学习的崛起原因

尽管一直有一群执着的研究者不断钻研,试图学习视觉数据的逐级表征,然而很长一段时间里这些尝试都未有突破。深度卷积神经网络的突破出现在2012年。突破可归因于两个关键因素。

①硬件

2012年,当Alex Krizhevsky和Ilya Sutskever实现了可以在GPU硬件上运行的深度卷积神经网络时,一个重大突破出现了。他们意识到卷积神经网络中的计算瓶颈:卷积和矩阵乘法,都是可以在硬件上并行化的操作。 于是,他们使用两个显存为3GB的NVIDIA GTX580 GPU实现了快速卷积运算。他们的创新cuda-convnet几年来它一直是行业标准,并推动了深度学习热潮。

硬件

②数据

2009年,ImageNet数据集发布,并发起ImageNet挑战赛:要求研究人员从100万个样本中训练模型,以区分1000个不同类别的对象。ImageNet数据集由斯坦福教授李飞飞小组的研究人员开发,利用谷歌图像搜索(Google Image Search)对每一类图像进行预筛选,并利用亚马逊众包(Amazon Mechanical Turk)来标注每张图片的相关类别。这种规模是前所未有的。这项被称为ImageNet的挑战赛推动了计算机视觉和机器学习研究的发展,挑战研究人员确定哪些模型能够在更大的数据规模下表现最好。

数据

AlexNet vs LeNet

AlexNet vs LeNet

AlexNet vs LeNet

AlexNet

AlexNet的更多细节

AlexNet的复杂度

总结

总结

使用块的网络(VGG)

本节代码文件在源代码文件的chapter_convolutional-modern/vgg.ipynb中

VGG 出现的背景

VGG出现的背景

VGG 块

VGG块

VGG 架构

VGG架构

进度(发展)

进度

下图横坐标代表速率,纵坐标代表准确率,圆的大小代表内存占用的大小:

进度

总结

总结

网络中的网络(NiN)

本节代码文件在源代码文件的chapter_convolutional-modern/nin.ipynb中

全连接层的问题

全连接层的问题

NiN 块

NiN块

NiN 架构

NiN架构

NiN 网络

NiN网络

NiN网络

总结

总结

含并行连结的网络(GoogLeNet)

本节代码文件在源代码文件的chapter_convolutional-modern/googlenet.ipynb中

GoogLeNet 出现的背景

我们往往不确定到底选取什么样的层效果更好,到底是3X3卷积层还是5X5的卷积层,诸如此类的问题是GooLeNet选择了另一种思路“小学生才做选择,我全都要”,这也使得GooLeNet成为了第一个模型中超过1000个层的模型。

GoogLeNet出现的背景

GoogLeNet出现的背景

Inception 块

Inception块由四条并行路径组成。 前三条路径使用窗口大小为1x1、3x3和5x5的卷积层,从不同空间大小中提取信息。 中间的两条路径在输入上执行1x1卷积,以减少通道数,从而降低模型的复杂性。 第四条路径使用3x3最大汇聚层,然后使用1x1卷积层来改变通道数。 这四条路径都使用合适的填充来使输入与输出的高和宽一致,最后我们将每条线路的输出在通道维度上连结,并构成Inception块的输出。在Inception块中,通常调整的超参数是每层输出通道数。

Inception块

Inception块

GoogLeNet

GoogLeNet一共使用9个Inception块和全局平均汇聚层(Global AvgPool)的堆叠来生成其估计值。Inception块之间的最大汇聚层可降低维度。 第一个模块类似于AlexNet和LeNet,Inception块的组合从VGG继承,全局平均汇聚层避免了在最后使用全连接层(FC)。

GoogLeNet

段1&2

段3

段4&5

Inception 有各种后续变种

v3是在v2基础上变化的:

Inception有各种后续变种

Inception V3块,段3

Inception V3块,段4

Inception V3块,段5

Inception与其他网络的比较

下图横坐标代表速率,纵坐标代表准确率,圆的大小代表内存占用的大小。由图可见,Inception V3速率较低,占用内存较大,但准确率很高。

Inception与其他网络的比较

总结

总结

批量规范化(归一化)

本节代码文件在源代码文件的chapter_convolutional-modern/batch-norm.ipynb中

背景

背景

批量归一化

批量归一化

批量归一化层

批量归一化层

批量归一化在做什么?

批量归一化在做什么

总结

总结

残差网络(ResNet)

本节代码文件在源代码文件的chapter_convolutional-modern/resnet.ipynb中

加更多的层总是改进精度吗?

加更多的层总是改进精度吗

残差块

残差块

ResNet 块细节

ResNet 块细节

不同的残差块

不同的残差块

ResNet 块

ResNet 块

ResNet 架构

ResNet 架构

ResNet与其他网络的比较

下图横坐标代表速率,纵坐标代表准确率,圆的大小代表内存占用的大小。由图可见,ResNet 152 速率较低,但占用内存较小,且准确率很高。

ResNet与其他网络的比较

总结

总结

计算性能

深度学习硬件(CPU和GPU)

电脑CPU、GPU、内存之间的关系

电脑CPU、GPU、内存之间的关系

CPU芯片图

CPU芯片图

提升CPU利用率

提升CPU利用率

样例分析

提升CPU利用率

样例分析

GPU芯片图

GPU芯片图

GPU vs CPU

GPU vs CPU

提升GPU利用率

提升GPU利用率

CPU/GPU 带宽

CPU/GPU 带宽

更多的 CPUs 和 GPUs

更多的 CPUs 和 GPUs

CPU/GPU 高性能计算编程

CPU/GPU 高性能计算编程

总结

总结

深度学习硬件(TPU和其他)

手机内部的芯片

手机内部的芯片

DSP:数字信号处理

DSP:数字信号处理

可编程阵列(FPGA)

可编程阵列(FPGA)

AI ASIC

AI ASIC

Systolic Array

Systolic Array

Systolic Array的矩阵乘法

Systolic Array的矩阵乘法

Systolic Array的矩阵乘法

Systolic Array的矩阵乘法

Systolic Array的矩阵乘法

Systolic Array的矩阵乘法

Systolic Array的矩阵乘法

Systolic Array的矩阵乘法

Systolic Array

总结

· 灵活性、易用性:Intel(CPU) > GPU > DSP > FPGA > ASIC

· 性能功耗:Intel(CPU) < GPU < DSP < FPGA < ASIC

总结

单机多卡并行

多GPU并行

多GPU并行

单机多卡并行

单机多卡并行

数据并行 vs 模型并行

数据并行 vs 模型并行

数据并行

数据并行

总结

总结

分布式训练

分布式计算

本质上来说和之前讲的单机多卡并行没有区别。二者之间的区别是分布式计算是通过网络把数据从一台机器搬到另一台机器。

分布式计算

分布式计算

GPU机器架构

总的来说,gpu到gpu的通讯是很快的,gpu到cpu慢一点。机器到机器更慢。因而总体性能的关键就是尽量在本地做通讯而少在机器之间做通讯。

GPU机器架构

举例:计算一个小批量:

计算一个小批量

计算一个小批量

计算一个小批量

计算一个小批量

计算一个小批量

计算一个小批量

计算一个小批量

计算一个小批量

同步 SGD

同步 SGD

性能

性能

性能的权衡

性能的权衡

实践时的建议

实践时的建议

总结

总结

计算机视觉

图像增广

本节代码文件在源代码文件的chapter_computer-vision/image-augmentation.ipynb中

数据增广

数据增广

数据增广

数据增强

数据增强

使用增强数据训练

使用增强数据训练

翻转

翻转

切割

切割

颜色

颜色

几十种其他办法

几十种其他办法

总结

总结

微调

本节代码文件在源代码文件的chapter_computer-vision/fine-tuning.ipynb中

微调的原因

微调的原因

神经网络的网络架构

神经网络的网络架构

神经网络的微调

微调中的权重初始化

微调中的权重初始化

训练时的微调

训练时的微调

重用分类器权重

重用分类器权重

固定一些层

固定一些层

总结

总结

物体检测和数据集

本节代码文件在源代码文件的chapter_computer-vision/bounding-box.ipynb中

图片分类与目标检测的区别

目标检测更加复杂,需要进行多个物体的识别,还要找出每个物体的位置。目标检测的应用场景也更多。

在这里插入图片描述

边缘框

边缘框

目标检测数据集

目标检测数据集

总结

总结

锚框

本节代码文件在源代码文件的chapter_computer-vision/anchor.ipynb中

锚框

锚框

IoU - 交并比

IoU - 交并比

赋予锚框标号

赋予锚框标号

赋予锚框标号

使用非极大值抑制(NMS)输出

使用非极大值抑制(NMS)输出

总结

总结

物体检测算法:R-CNN,SSD,YOLO

本节代码文件在源代码文件的chapter_computer-vision/rcnn.ipynb中

R-CNN

R-CNN

兴趣区域(RoI)池化层

目的:每个锚框都可以变成想要的形状

兴趣区域(RoI)池化层

Fast RCNN

RCNN需要对每个锚框进行CNN运算,这些特征抽取计算有重复,并且锚框数量大,特征抽取的计算量也大。Fast RCNN改进了这种计算量大的问题,使用CNN对整张图片抽取特征(快的关键),再使用Rol池化层对每个锚框(将在原图片中搜索到的锚框,映射到CNN得到的结果上),生成固定长度的特征。

Fast RCNN

Faster RCNN

将CNN结果输入到卷积层,然后用锚框去圈区域,这些锚框很多有好有坏,然后进行预测,binary 预测是预测这个锚框的好坏,即有没有有效的圈住物体,bounding box prediction预测是对锚框进行一些改进,最后用NMS(非极大值抑制)对锚框进行合并。

Faster RCNN

Mask RCNN

Mask RCNN

如图,Faster RCNN精度高但是速度慢(贵):

精度比较

总结

总结

单发多框检测(SSD)

本节代码文件在源代码文件的chapter_computer-vision/ssd.ipynb中

生成锚框

生成锚框

SSD模型

SSD模型

如图,SSD速度快但精度不高:

比较

总结

总结

YOLO

YOLO(你只看一次)

在这里插入图片描述

如图,相同精度下YoLo比SSD速度快:

比较

语义分割

本节代码文件在源代码文件的chapter_computer-vision/semantic-segmentation-and-dataset.ipynb中

语义分割

语义分割

应用:背景虚化

应用

应用:路面分割

应用

应用:实例分割

应用

转置卷积

本节代码文件在源代码文件的chapter_computer-vision/transposed-conv.ipynb中

转置卷积

转置卷积

为什么称之为“转置”

为什么称之为“转置”

转置卷积是一种卷积

转置卷积是一种卷积

重新排列输入和核

重新排列输入和核

重新排列输入和核

重新排列输入和核

形状换算

形状换算

同反卷积的关系

同反卷积的关系

总结

总结

全连接卷积神经网络 FCN

本节代码文件在源代码文件的chapter_computer-vision/fcn.ipynb中

全连接卷积神经网络(FCN)

全连接卷积神经网络(FCN)

全连接卷积神经网络(FCN)

样式迁移

本节代码文件在源代码文件的chapter_computer-vision/neural-style.ipynb中

样式迁移

样式迁移

样式迁移

基于CNN的样式迁移

基于CNN的样式迁移

循环神经网络

序列模型

本节代码文件在源代码文件的chapter_recurrent-neural-networks/sequence.ipynb中

序列数据

序列数据

序列数据 - 更多例子

序列数据 - 更多例子

统计工具

统计工具

统计工具

序列模型

序列模型

序列模型

序列模型

总结

总结

语言模型

本节代码文件在源代码文件的chapter_recurrent-neural-networks/language-models-and-dataset.ipynb中

语言模型

语言模型

语言模型

使用计数来建模

使用计数来建模

N元语法

N元语法

总结

总结

循环神经网络

本节代码文件在源代码文件的chapter_recurrent-neural-networks/rnn.ipynb中

潜变量自回归模型

潜变量自回归模型

循环神经网络

循环神经网络

使用循环神经网络的语言模型

使用循环神经网络的语言模型

困惑度(perplexity)

困惑度(perplexity)

梯度裁剪

梯度裁剪

更多的应用RNNs

更多的应用RNNs

总结

总结

现代循环神经网络

门控循环单元GRU

本节代码文件在源代码文件的chapter_recurrent-modern/gru.ipynb中

门控循环单元GRU

门控循环单元GRU

关注一个序列

关注一个序列

门

候选隐状态

候选隐状态

隐状态

隐状态

总结

总结

长短期记忆网络(LSTM)

本节代码文件在源代码文件的chapter_recurrent-modern/lstm.ipynb中

长短期记忆网络

长短期记忆网络

门

候选记忆单元

候选记忆单元

记忆单元

记忆单元

隐状态

隐状态

总结

总结

深度循环神经网络

本节代码文件在源代码文件的chapter_recurrent-modern/deep-rnn.ipynb中

回顾:循环神经网络

回顾:循环神经网络

Plan A - Nonlinearity in the units

Plan A - Nonlinearity in the units

更深

更深

更深

总结

总结

双向循环神经网络

本节代码文件在源代码文件的chapter_recurrent-modern/bi-rnn.ipynb中

未来很重要

未来很重要

未来很重要

双向RNN

双向RNN

双向RNN

推理

推理

总结

总结

编码器-解码器

本节代码文件在源代码文件的chapter_recurrent-modern/encoder-decoder.ipynb中

重新考察CNN

重新考察CNN

重新考察RNN

重新考察CNN

编码器-解码器架构

编码器-解码器架构

总结

总结

序列到序列学习

本节代码文件在源代码文件的chapter_recurrent-modern/seq2seq.ipynb中

序列到序列学习(seq2seq)

序列到序列学习(seq2seq)

机器翻译

机器翻译

Seq2seq

Seq2seq

编码器-解码器细节

编码器-解码器细节

训练

训练

衡量生成序列的好坏的BLEU

衡量生成序列的好坏的BLEU

总结

总结

束搜索

本节代码文件在源代码文件的chapter_recurrent-modern/beam-search.ipynb中

贪心搜索

贪心搜索

穷举搜索

穷举搜索

束搜索

束搜索

束搜索

总结

总结

注意力机制

本节代码文件在源代码文件的chapter_attention-mechanisms/attention-cues.ipynb中

心理学

心理学

注意力机制

注意力机制

非参注意力池化层

非参注意力池化层

Nadaraya-Watson核回归

Nadaraya-Watson核回归

参数化的注意力机制

参数化的注意力机制

总结

总结

注意力分数

本节代码文件在源代码文件的chapter_attention-mechanisms/attention-scoring-functions.ipynb中

注意力分数

注意力分数

拓展到高维度

拓展到高维度

Additive Attention

Additive Attention

Scaled Dot-Product Attention

Scaled Dot-Product Attention

总结

总结

使用注意力机制的seq2seq

本节代码文件在源代码文件的chapter_attention-mechanisms/bahdanau-attention.ipynb中

动机

动机

加入注意力

加入注意力

总结

总结

自注意力

本节代码文件在源代码文件的chapter_attention-mechanisms/self-attention-and-positional-encoding.ipynb中

自注意力

自注意力

跟CNN,RNN对比

跟CNN,RNN对比

位置编码

位置编码

位置编码矩阵

位置编码矩阵

绝对位置信息

绝对位置信息

绝对位置信息

总结

总结

Transformer

本节代码文件在源代码文件的chapter_attention-mechanisms/transformer.ipynb中

Transformer架构

Transformer架构

多头注意力

多头注意力

多头注意力

有掩码的多头注意力

有掩码的多头注意力

基于位置的前馈网络

基于位置的前馈网络

层归一化

层归一化

信息传递

信息传递

预测

预测

总结

总结

自然语言处理:预训练

BERT预训练

本节代码文件在源代码文件的chapter_natural-language-processing-pretraining/bert-pretraining.ipynb中

NLP里的迁移学习

NLP里的迁移学习

BERT的动机

BERT的动机

BERT架构

BERT架构

对输入的修改

对输入的修改

预训练任务1:带掩码的语言模型

预训练任务1:带掩码的语言模型

预训练任务2:下一句子预测

预训练任务2:下一句子预测

总结

总结

自然语言处理:应用

BERT微调

本节代码文件在源代码文件的chapter_natural-language-processing-applications/finetuning-bert.ipynb中

微调 Bert

微调bert

句子分类

句子分类

命名实体识别

命名实体识别

问题回答

问题回答

总结

总结

优化算法

优化算法

本节代码文件在源代码文件的chapter_optimization/optimization-intro.ipynb中

优化问题

优化问题

局部最小 vs 全局最小

局部最小 vs 全局最小

凸集

凸集

凸函数

凸函数

凸函数优化

凸函数优化

凸和非凸例子

凸和非凸例子

梯度下降

梯度下降

随机梯度下降

随机梯度下降

小批量随机梯度下降

小批量随机梯度下降

冲量法

冲量法

Adam

Adam

Adam

总结

总结



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。