|
目录【内容介绍】动手学深度学习-基于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函数后不指向同一块内存,但数据改变是同步的importtorcha=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))#2157597781424print(id(b))#21575977814241234567891011线性代数 本节代码文件在源代码文件的chapter_preliminaries/linear-algebra.ipynb中张量的按元素操作 标量、向量、矩阵和任意数量轴的张量(统称为张量)有一些实用的属性。例如,你可能已经从按元素操作的定义中注意到,任何按元素的一元运算都不会改变其操作数的形状。同样,给定具有相同形状的任意两个张量,任何按元素二元运算的结果都将是相同形状的张量。 例如,将两个相同形状的矩阵相加,会在这两个矩阵上执行按元素加法;两个矩阵的按元素乘法称为Hadamard积(Hadamardproduct)(数学符号⨀\bigodot⨀)。对于矩阵A∈Rmn,B∈Rmn\bfA\in\mathbbR^{mn},\bfB\in\mathbbR^{mn}A∈Rmn,B∈Rmn,其中第i\itii行和第j\itjj列的元素是bijb_{ij}bij。矩阵A\bfAA和B\bfBB的Hadamard积为importtorchA=torch.arange(20,dtype=torch.float32).reshape(5,4)B=A.clone()#通过分配新内存,将A的一个副本分配给Bprint(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.]])123456789降维求和 ①原始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是向量;其中,\ita不是关于\bfx的函数,\color{black}0和\bf1是向量;其中,a不是关于x的函数,0和1是向量; 列向量对列向量求导 结果是矩阵 样例: x∈Rn,y∈Rm,∂y∂x∈Rmn;a,a和A不是关于x的函数,0和I是矩阵;\bfx\in\mathbbR^{n},\bfy\in\mathbbR^{m},\frac{\partial\bfy}{\partial\bfx}\in\mathbbR^{mn};\ita,\bfa和\bfA不是关于\bfx的函数,\color{black}0和\bfI是矩阵;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和交叉熵损失 总结 损失函数 本节代码文件在源代码文件的chapter_linear-networks/softmax-regression.ipynb中损失函数用来衡量预测值与真实值之间的区别,是机器学习里非常重要的概念。下面介绍三种常用的损失函数。①L2Loss l(y,y′)=∣y−y′∣\itl(y,y')=\midy-y'\midl(y,y′)=∣y−y′∣ 蓝色曲线:表示当y=0时,变换预测值y’。绿色曲线:表示似然函数。橙色曲线:表示损失函数的梯度,可以发现,当y与y’相差较大的时候,梯度的绝对值也较大。②L1Loss l(y,y′)=12(y−y′)2\itl(y,y')=\frac{1}{2}(y-y')^2l(y,y′)=21(y−y′)2 蓝色曲线:表示当y=0时,变换预测值y’。绿色曲线:表示似然函数。橙色曲线:表示损失函数的梯度,可以发现,当y’>0时,导数为1,当y’print(net[2].bias)#Parametercontaining:#tensor([0.2871],requires_grad=True)print(net[2].bias.data)#tensor([0.2871])1234567参数是复合的对象,包含值、梯度和额外信息。这就是我们需要显式参数值的原因。除了值之外,我们还可以访问每个参数的梯度。在上面这个网络中,由于我们还没有调用反向传播,所以参数的梯度处于初始状态。print(net[2].weight.grad==None)#True12一次性访问所有参数 当我们需要对所有参数执行操作时,逐个访问它们可能会很麻烦。当我们处理更复杂的块(例如,嵌套块)时,情况可能会变得特别复杂,因为我们需要递归整个树来提取每个子块的参数。下面,我们将通过演示来比较访问第一个全连接层的参数和访问所有层:print(*[(name,param.shape)forname,paraminnet[0].named_parameters()])#('weight',torch.Size([8,4]))('bias',torch.Size([8]))print(*[(name,param.shape)forname,paraminnet.named_parameters()])#('0.weight',torch.Size([8,4]))('0.bias',torch.Size([8]))('2.weight',torch.Size([1,8]))('2.bias',torch.Size([1]))1234这为我们提供了另一种访问网络参数的方式,如下所示:net.state_dict()['2.bias'].data#tensor([0.2871])12从嵌套块收集参数 我们首先定义一个生成块的函数(可以说是“块工厂”),然后将这些块组合到更大的块中。defblock1():returnnn.Sequential(nn.Linear(4,8),nn.ReLU(),nn.Linear(8,4),nn.ReLU())defblock2():net=nn.Sequential()foriinrange(4):#在这里嵌套net.add_module(f'block{i}',block1())returnnetrgnet=nn.Sequential(block2(),nn.Linear(4,1))rgnet(X)#tensor([[0.1713],#[0.1713]],grad_fn=
|
|