《PyTorch深度学习实践》B站视频学习笔记
练习只做了简单的,剩下的都没做。
B站视频【《PyTorch深度学习实践》完结合集】-刘二大人
Overview
深度学习的系统
- 基于规则的深度学习
- 经典的机器学习——手动提取一些简单的特征
- 表示学习方法——提取特征
起因:“维数诅咒”——维度越高,训练一个性能较好的模型对数据量的要求就越高。
解决方法:希望通过降维的方法减少对数据量的要求,同时在降维的过程中还需要保持在高维空间里的一些度量信息,这样的过程就是“表示学习”。 - 深度学习——利用一些简单的特征,即较为原始的特征
- 深度学习与传统学习的区别:传统学习中特征学习和学习器是分开的;但是在深度学习中,所有的训练都是统一的。
线性模型
数据集的划分
样本损失和trainning过程整体损失(也叫平均平方损失MSE)
用穷举法确定线性模型的参数
visdom库可用于可视化
另外,np.meshgrid()可用于绘制三维图
梯度下降算法
分治法
即通过划分不同精度的搜索范围,逐步缩小搜索范围,以解决搜索范围过大的问题。
梯度下降算法
-
梯度下降算法是贪心算法的一种,贪心算法即只走眼前最好的一步,容易陷入局部最优。
-
深度学习的损失函数其实并没有太多的局部最优点,但是会有鞍点,当在鞍点时没有办法继续迭代。
其实在深度学习中最需要解决的是鞍点问题,高维空间中的鞍点是指在某个方向可能是最小点,但在另一个方向是最大点。 -
对上讲中的线性模型利用梯度下降算法编程求解
-
画图时可以对损失值进行一个平滑,更容易观察整体的下降趋势
其中 c i c_i ci是第i次的损失值,下面一行是平滑后的损失值,平滑的计算公式如下:
训练失败时的损失值变化情况
如果损失值的变化如下图所示,就说明这次训练失败了,训练发散。
随机梯度下降
在深度学习中梯度下降用的并不多,更多使用随机梯度下降。梯度下降用的是所有样本的损失平均值求梯度更新参数,而随机梯度下降是用一个样本的损失值求梯度来更新参数。
为什么要使用随机梯度下降
因为损失函数有可能是如下图所示的样子,存在鞍点,但是如果只用一个样本,因为我们拿到的样本基本都是有噪声的,这样就引入了一个随机噪声,有可能帮助我们跳出这个鞍点,继续训练。(??)
使用随机梯度下降后的变化
-
迭代公式的变化
-
代码实现的变化
使用随机梯度下降和梯度下降的优缺点
- 随机梯度下降
因为随机梯度下降在求下一个样本的值时是需要依赖上一个样本对参数的更新,所以随机梯度下降不能并行计算,时间效率较低,但是它的结果一般较好。 - 梯度下降
时间效率高,因为样本间值的求解,(即f(x))不存在依赖关系,但是结果不一定好。
深度学习中常用batch
综合考虑梯度下降和随机梯度下降的优缺点,深度学习中一般使用batch来训练,即小批量的随机梯度下降算法。
PS:实际上,在原始的表达中,batch代表整体的数据,小批量的数据用mini-batch表示,但因为目前mini-batch是主流,在说小批量时会将mini省略而说成batch。
反向传播算法
矩阵求导的计算公式可以在《matrix-cook-book》这本书中找到。
-
对于线性的模型,不论加多少层,最终都可以化简成一个只有一层的线性模型,即增加网络深度没有意义。
-
为了解决上述问题,加了一个非线性函数的变换
反向传播backward
正向传播——forward
-
反向传播过程图
-
举例
这里z对x和w求偏导都是根据f的计算得到的,这里没有解释损失对z求偏导的过程(??)。
3. 反向传播的计算过程
其中r为残差项,是y与y_hat的差值,即r=y_hat-y,在前向传播的过程中,根据每一步进行的运算可以很容易求出对应的偏导。接下来是梯度反向传播的过程:
Pytorch中的tensor
tensor中最重要的两个成员data和grad,它们分别存储值及对应的导数。
代码实现
step 1
step 2
-
注意这里的x转化为tensor类型,且在这一步已经构建了如右边所示的计算图,而且因为输入中有w需要计算梯度,所以两者相乘的结果也是需要计算梯度的。
-
看到这些代码要意识到它是在构建计算图。
step 3
-
这里计算的l是一个张量,故可以调用其backward()方法,从而将前向传播中所有需要梯度的地方都求出来。一旦调用完bachward()方法后,计算图就被释放了,下次计算loss时就会获得新的计算图。
-
这里的grad也是一个tensor数据,直接取它的data进行计算,否则又会生成一个计算图计算其梯度。
-
item()是将其变为一个标量。
-
注意如果要算整体数据的损失值,不能用sum+=l,而应该是sum+=l.item()。因为直接加l,当数据量很多的时候,在一次又一次加的过程中会生成一个很大的计算图,很吃内存。(tensor数据类型在做运算时会构建计算图。)
-
w.grad.data.zero_()对梯度清零,如果不对其清零,那么下一次求的梯度值就是在原梯度值的基础上再加上下一次的梯度值。
一个练习
import torch
x_data=[1,2,3]
y_data=[2,4,6]
w1=torch.Tensor([1.0])
w1.requires_grad=True
w2=torch.Tensor([1.0])
w2.requires_grad=True
b=torch.Tensor([1.0])
b.requires_grad=True
def forward(x):
return w1*x**2+w2*x+b
def loss(x,y):
y_pred=forward(x)
return (y_pred-y)**2
print('Predict (before training):',4,forward(4).item())
for epoch in range(100):
for x,y in zip(x_data,y_data):
l=loss(x,y)
l.backward()
w1.data=w1.data-0.01*w1.grad.data
w2.data = w2.data -