动手深度学习pytorch 1-4章

引言 

一:过去⼗年中取 得巨⼤进步的想法

1.如dropout (Srivastava et al., 2014),有助于减轻过拟合的危险。这是通过在整个神 经⽹络中应⽤噪声注⼊ (Bishop, 1995) 来实现的,出于训练⽬的,⽤随机变量来代替权重

2.注意⼒机制解决了困扰统计学⼀个多世纪的问题:如何在不增加可学习参数的情况下增加系统的记忆 和复杂性。

3.多阶段设计

4.GAN

5.随机梯度下降

6.并行计算能力

7.深度学习框架

⼈⼯智能系统是以⼀种 特定的、⾯向⽬标的⽅式设计、训练和部署的。虽然他们的⾏为可能会给⼈⼀种通⽤智能的错觉,但设计的 基础是规则、启发式和统计模型的结合。其次,⽬前还不存在能够⾃我改进、⾃我推理、能够在试图解决⼀ 般任务的同时,修改、扩展和改进⾃⼰的架构的“⼈⼯通⽤智能”⼯具

预备知识

1.广播机制

形状不同的张量运算。复制/按元素操作

2.索引和切片

  [1:3]选择第二个和第三个元素

  [0:2,:] 第一行和第二行所有元素

3.注意原地分配内存

  X[:] = X + Y或X += Y

4.pandas.get_dummies

  是pandas中一种非常高效的方法。它最主要的作用是可以将分类变量转变成dummy变量,也就是虚拟变量

5.对⾮标量调⽤backward

需要传⼊⼀个gradient参数,该参数指定微分函数关于self的梯度

6.分离计算

u = y.detach()

7.b.norm()

是一个 PyTorch 中的方法,用于计算张量 b 的 L2 范数(也称为欧几里得范数)。具体地,L2 范数是指一个向量中所有元素的平方和的平方根2

8.torch.randn()

方法生成一个具有随机值的张量,其值是从均值为 0,标准差为 1 的正态分布中随机抽取的。这个方法的输入参数是一个元组,用于指定张量的形状

9.两次反向传播会报错

loss.backward(retain_graph=True)这样设置后就不会了,第二次的backward其实把梯度再次回传一遍叠加在了第一次上面

10.执行loss.backward()时带参数,就可以计算随机向量或矩阵

11.multinomial.Multinomial(1, fair_probs)

是一个 PyTorch 中的方法,用于创建一个多项式分布对象,该分布对象的参数为 1 和 fair_probs。其中,第一个参数 1 表示抽样次数为 1,第二个参数 fair_probs 表示每个元素的概率分布

sample() 是一个 PyTorch 中的方法,用于从多项式分布中抽样

线性神经网络

1. 线性回归的解析解:

通过数学公式直接计算出最优的回归系数的方法,而不是通过迭代算法(如梯度下降)来计算

min ||y - Xb||2

其中,||.||2表示欧几里得范数,y是因变量向量,X是自变量矩阵,b是回归系数向量。

b = (XTX)-1XTy

这个公式就是线性回归的解析解,它直接计算出最优的回归系数

2. 泛化:

找到一组参数使得这组参数能够再我们从未见过的数据上实现较低的损失

3. 矢量化代码:

带来数量级的加速,更多的数学运算放到库中

4. f'{time.stop():.5f} sec'  

  • time.stop() 表示调用名为 stop 的函数,返回一个时间值(通常是秒数)。
  • :.5f 表示将这个时间值格式化为一个浮点数,并保留 5 位小数。
  • sec 表示在最后输出一个字符串 "sec",表示这个时间值是秒数

5. 高斯噪声的假设下,最小化均方误差等价于对线性模型的极大似然估计

6. 线性回归算法

过程:

X = torch.normal(0, 1, (num_examples, len(w)))

这行代码使用 PyTorch 创建了一个张量(tensor)X,它是一个大小为 (num_examples, len(w)) 的矩阵,其中每个元素都是从标准正态分布中随机采样得到的。具体来说,该语句的参数解释如下:

  • torch.normal:表示使用 PyTorch 中的正态分布函数来生成随机数。
  • 0:表示正态分布的均值为 0。
  • 1:表示正态分布的标准差为 1。
  • (num_examples, len(w)):表示生成的矩阵的大小为 (num_examples, len(w))。

因此,该语句的作用是随机生成一个大小为 (num_examples, len(w)) 的矩阵 X,用于后续的线性回归训练

 简单表达:

next(iter(data_iter))

  • iter(data_iter):表示使用 iter() 函数将数据迭代器 data_iter 转换为一个迭代器对象,以便在后续的代码中使用 next() 函数逐个取出数据样本。
  • next(iter(data_iter)):表示使用 next() 函数从迭代器对象中取出下一个数据样本。在这里,iter(data_iter) 的作用是将数据迭代器转换为迭代器对象,以便使用 next() 函数逐个取出数据样本。

net[0].weight.data.normal_(0,0.01)

net[0].bias.data.fill_(0)

  • net[0].weight.data.normal_(0,0.01):使用正态分布来初始化权重,其中平均值为0,标准差为0.01。这个操作将在net神经网络的第一层中的权重数据上执行,即net的第一个nn.Linear层的权重数据。这个操作将使权重数据随机地从一个平均值为0、标准差为0.01的正态分布中取样,然后用这些值来初始化权重
  • net[0].bias.data.fill_(0):将偏置设置为0。这个操作将在net神经网络的第一层中的偏置数据上执行,即net的第一个nn.Linear层的偏置数据。这个操作将把偏置数据设置为0

7. softmax函数

非负和为1 同时让模型保持可导

y^j=exp(oj)kexp(ok)

通常用于多分类问题中,将一组任意实数转化为一个概率分布,exp是自然指数函数,sum是对所有j的求和。通过指数函数将原始的实数转化为正数,然后再将其归一化

从零开始实现:

  

8.计算损失的三种方法 

  a) 最小二乘

  b) 极大似然估计  结果去反推概率模型 

  c) 交叉熵损失   i)从最大似然角度  ii)从信息量角度

加起来的熵越大系统越不确定

单个信息量想要贡献给整体需要乘以自己的比例 

相对熵:   KL散度

 交叉熵越小,模型越接近,以2为底代表计算出来的信息熵单位比特,(纳特约等于1.44比特,以e为底的对数)

9. transforms.Compose(trans) 

  将这些变换组合在一起并返回一个新的变换对象 trans

10. net.eval() 

  将神经网络设置为评估模式。在评估模式下,神经网络的行为会有所不同,主要是为了减少内存占用和加快推理速度。在评估模式下,通常会关闭 dropout 和 batch normalization 层,并且不会计算梯度。这个函数通常用于在测试数据集上进行推理时,以确保神经网络的输出是正确的

11. metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())

  这行代码是用来更新指定的度量指标的。metric 是一个 AccuracyMetric 实例,它包含了准确率的计算方法。add 方法用来将当前批次的预测结果、真实标签和样本数量传递给 AccuracyMetric 实例,并更新准确率指标的值。具体来说,l.sum() 是当前批次的损失值之和,accuracy(y_hat, y) 是当前批次的准确率,y.numel() 是当前批次的样本数量。

多层感知机

1. 激活函数

  ReLU:使⽤ReLU的原因是,它求导表现得特别好:要么让参数消失,要么让参数通过。这使得优化表现得更好,并且ReLU减轻了困扰以往神经⽹络的梯度消失问题

  sigmoid函数 \(\sigma(x) = \frac{1}{1+e^{-x}} \),适用于二分类​​

  tanh函数:$\tanh(x) = \frac{e^{x}-e^{-x}}{e^{x}+e^{-x}}$,适用于多分类

  sigmoid 和tanh函数图像相似,当输入值非常大或非常小时,sigmoid函数的梯度会很小,这使得神经网络的训练变得困难。tanh函数也存在类似的问题

2. 学习周期和学习率

  学习周期是指将整个训练集数据遍历一次的次数。在训练过程中,每个学习周期会将训练集数据分成若干个batch,每个batch中包含多个样本,模型会对每个batch进行一次前向传播和反向传播,然后根据反向传播计算得到的梯度来更新模型参数。当整个训练集数据都被用于训练时,一个学习周期结束。通常情况下,我们会将训练集数据遍历多次,以提高模型的训练效果。

学习率是指模型在每次参数更新时,参数值沿着梯度方向移动的步长大小。学习率的大小直接影响模型参数的更新速度和方向。当学习率较大时,模型参数的更新速度会更快,但也容易出现震荡和不稳定的情况;而当学习率较小时,模型参数的更新速度会更慢,但也更容易收敛到稳定的结果

3. kaiming_normal是一种常用的权重初始化方法

  核心思想是根据激活函数的特点来初始化权重。具体来说,假设网络中某一层的输入特征的维度为n,则该层的权重矩阵应该采用均值为0、标准差为2n的正态分布来初始化。这样可以使得网络在前向传播和反向传播过程中的激活值的方差保持不变,从而更容易收敛。

需要注意的是,kaiming_normal方法只适用于使用ReLU激活函数的网络层。如果使用其他的激活函数,如sigmoid或tanh,需要使用其他的权重初始化方法。在PyTorch中,可以使用torch.nn.init.kaiming_normal_函数

4. 模型泛化 

  影响因素:  可调整参数数量 /参数采用的值/ 训练样本的数量

  泛化误差: 模型应用在同样从原始样本的分布中抽取的无限多数据样本时,模型误差的期望

 5. ndarray 和 tensor

  ndarraytensor都是用于存储和处理多维数组数据的数据结构,但是它们在具体实现和使用方式上有一些区别。

  ndarrayNumPy库中的一个数据结构,用于存储和处理多维数组数据。ndarray是一个类似于矩阵的数据结构,可以支持基本的数学运算、切片、索引等操作。ndarray在计算机内存中是连续的一块区域,可以直接通过指针来访问和修改其中的元素。ndarray的数据类型可以是整数、浮点数、布尔值等,支持自定义数据类型。

  tensorPyTorch库中的一个数据结构,用于存储和处理多维数组数据。tensorndarray类似,也可以支持基本的数学运算、切片、索引等操作。与ndarray不同的是,tensor还可以在GPU上进行计算,从而加速模型的训练和推理。tensor的数据类型可以是整数、浮点数、布尔值等,支持自定义数据类型。

  总的来说,ndarraytensor都是用于存储和处理多维数组数据的数据结构,但是它们在具体实现和使用方式上有一些区别。ndarray主要用于科学计算和数据分析,而tensor则主要用于深度学习和神经网络。在使用时,需要根据具体的应用场景和需求选择合适的数据结构

6. 龙格现象

指在数值计算中,使用较低阶数的数值方法计算高阶微分方程时,会出现误差振荡的现象。这种现象最早是由瑞士数学家J.龙格在1924年发现的,因此被称为“龙格现象”。

具体来说,当使用较低阶数的数值方法(如欧拉法)计算高阶微分方程时,由于步长较大,导致数值解与真实解之间存在较大误差,而这种误差会在每个步长上累积,从而导致误差振荡。这种误差振荡会在数值解中产生高频分量,从而使得数值解与真实解之间的误差更加复杂。

为了避免龙格现象,可以采用较高阶数的数值方法(如龙格-库塔法),或者采用自适应步长控制的数值方法,从而使得步长能够自适应地调整,以适应不同的解析度和精度要求。此外,还可以采用数值稳定性分析的方法,对数值方法的稳定性进行分析,从而避免龙格现象的出现。

7. 常用的正则化方法

   1)权重衰减 :通过对模型的权重参数进行惩罚,来限制模型的复杂度,从而提高模型的泛化能力

   2)dropout:以p的概率将隐藏单元设置为0

    掩码:mask = (torch.rand(X.shape) > dropout).float()

      这段代码中,使用了PyTorch中的torch库,生成了一个掩码mask,用于实现Dropout正则化方法中的随机删除操作。

      具体来说,torch.rand(X.shape)生成了一个与输入张量X形状相同的张量,其中每个元素都是从均匀分布[0, 1)中随机采样得到的。然后,使用>(dropout)将这个张量中的每                 个元素与dropout进行比较,返回一个布尔类型的张量,其中大于dropout的元素为True,小于等于dropout的元素为False。最后,使用.float()将这个布尔类型的张量转换为               一个浮点类型的张量,其中True被转换为1.0,False被转换为0.0。

    i)class Net 中的forward方法调用 out = net(X)

  在PyTorch中,当我们调用一个继承自nn.Module的类的实例时,实际上是在调用该类的__call__方法,而__call__方法内部会自动调用forward方法。因此,当我们执行out = net(X)时,实际上是在调用net对象的__call__方法,而__call__方法内部会自动调用forward方法,从而得到模型的输出。

 8. 启发式的初始化方法

  指在神经网络模型的权重初始化过程中,根据一定的启发式规则来设置权重初值的方法。这种方法可以帮助我们更快地找到合适的权重初值,从而加速模型的训练过程,提高模型的性能

常用的启发式初始化方法包括:

  1. Xavier初始化方法:该方法根据输入层和输出层的神经元个数来设置权重初值,使得权重的方差与神经元个数的倒数成反比。这种方法适用于使用sigmoid和tanh等激活函数的神经网络。

  2. He初始化方法:该方法根据输入层的神经元个数来设置权重初值,使得权重的方差与神经元个数的一半成反比。这种方法适用于使用ReLU等带有正半轴的激活函数的神经网络。

  3. Lecun初始化方法:该方法根据输入层的神经元个数来设置权重初值,使得权重的方差与神经元个数成反比。这种方法适用于使用tanh等S型激活函数的神经网络。

以上三种启发式初始化方法都是通过合理地设置权重初值来加速模型的训练过程,提高模型的性能。在PyTorch中,可以通过设置nn.Linear层的weight参数来实现启发式初始化。

9. 分布偏移 (训练集和测试集不来自同一个分布)

类型

  1)协变量偏移:输入的分布随时间改变,标签函数没有

  2)标签偏移:y导致x时,标签偏移是一个合理的假设。例如疾病会引起症状

  3)概念偏移:因为位置不同和产生不同的理解

纠正

  经验风险和实际风险

    从真实分布中抽取的所有数据的总体损失的期望值 Ep(x,y)[L(f(x), y)] =∫ ∫L(f(x), y)p(x, y) dxdy

    加权经验最下化来训练模型

  1)协变量偏移纠正:1. 根据数据来⾃正确分布与来⾃错误分布的概率之⽐,来重新衡量每个数据样本的权重 2. 对数几率回归,区分来自两个分布的数据,任何可以很好区分的样本都应该相应的增加或减少权重。

    典型算法:

          以上算法依赖假设,目标分布中的每个数据样本在训练时出现的概率非零,如果p(x)>0,q(x)= 0 ,那么相应的权重会无穷大

  2)标签偏移纠正: 标签偏移假设,标签的分布随时间变化,但类别条件分布保持不变。

          重要性权重对应于标签似然比率

          如果我们的分类器⼀开始就相当准确,并且⽬标数据只包含我们以前⻅过的类别,以及如果标签偏移假设成⽴,我们就可以通过求解⼀个简单的线性系统来估计测试集的标签分布。

  3)概念偏移纠正:使用新数据更新现有的网络权重

10. 实战Kaggle⽐赛:预测房价

1.  clipped_preds = torch.clamp(net(features), 1, float('inf'))

  clamp()函数,用于将张量(tensor)中的元素限制在给定的范围内。

  这行代码的作用是将神经网络(net)对输入数据(features)的预测结果进行裁剪,将小于1的值设置为1,将大于正无穷大(float('inf'))的值设置为正无穷大

posted @   dunimaa  阅读(234)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示