1. Tensor
- 什么是Tensor?
torch中的tensors是一种特殊的数据结构,和numpy的array比较类似,可以当成多维数组来用,tensor可以通过GPU加速 - 如何生成Tensor?
- torch包中提供了一系列直接生成Tensor的函数,如
zeros()
、ones()
、rand()
等 - 直接通过数据生成
tensor(data)
- 通过Numpy转换
from_numpy(np_array)
- 还可以生产和其他tensor具有相同dtype的tensor,使用torch的
ones_like(data)
或rand_like(data)
等函数
- torch包中提供了一系列直接生成Tensor的函数,如
- Tensor的属性
.shape
返回torch.size格式.dtype
显示Tensor中数据的格式.device
返回tensor当前存储位置
- Tensor可进行的操作
- 切片
- join:
.cat(tensors)
,stack(tensors)
- 加法:
add()
或+
- 乘法:元素层面乘法
mul
或*
,矩阵乘法matmul
或@
- resize
1.reshape()
或view()
Tensor.numpy()
将tensor转变为numpy数据
两方向的转换的数据对象都是占用同一储存空间,修改后变化也会体现在另一对象上。item()
函数返回只有一个元素的Tensor的该元素的值
2. Autograd
- autograd是自动求导包,这样就不用自己算神经网络偏导了
- 训练一个神经网络包括前向传播和反向传播,前向传播用函数计算预测值,反向传播就是通过预测值产生的error/loss来更新参数
- 神经网络的一轮训练:
- 创建一个随机数据张量,三通道64*64,初始化随机值;预训练模型中的标签为(1,1000)
- 前向传播:
prediction = model(data)
,其中model
为已经预训练好的模型,传入随机的data
数据 - 使用模型进行预测连同真实值计算损失loss
- 反向传播:
loss.backward()
(autograd会在这步进行计算梯度,存到相应参数的grad属性中) - 更新参数:
1. 加载optimizer(通过torch.optim
)
2.optimizer.step()
对参数使用梯度下降法进行更新(梯度来源自参数的grad属性)
autograd的工作细节,选修
- 自动求梯度的原理
- 将tensor的
require_grad
设为True,可以追踪autograd在其上每一步的操作 - 示例中,提供了两个
require_grad
设为True的Tensor(每个含两个元素的向量)a和b,设其损失函数为 Q = 3 a 2 − b 2 Q = 3a^2 - b^2 Q=3a2−b2 - 注意:在对Q计算梯度时,需要在
backward()
函数中添加gradient参数,这个gradient是和当前Tensor形状相同的Tensor,包含当前Tensor的梯度,(因为Q是向量而非标量,为了避免这个问题也可以直接将Q转化为标量然后使用backward()方法,如Q.sum().backward()
),
需要注意的是上一个全流程时直接使用了loss.backward()
计算梯度,这是因为loss是标量 - 计算梯度:
external_grad = torch.tensor([1., 1.])
Q.backward(gradient=external_grad)
- 如此Q对于a和b的梯度就被存到了a.grad和b.grad中,可以直接查看
- 将tensor的
- autograd的矢量分析:
- 从数学上分析,如果你有一个矢量函数$ y ⃗ = f ( x ⃗ ) \vec{y} = f( \vec{x} ) y=f(x),那么他的梯度是一个雅可比矩阵(不是特别懂,想起考研时张宇好像说过,大佬也不懂,先掠过)
- autograd的计算图
- autograd维护一个由function组成的DAG(有向无环图),输入量为页,输出量为根,从根向叶使用链式法则自动计算梯度
- 在前向传播中,自动梯度主要做两件事:计算输出向量,维护DAG中操作的gradient function
- 反向传播以根节点调用
backforward()
开始,做三件事:用数据的grad_fn属性计算梯度、将梯度依次累加到.grad属性中、根据链式法则传播到叶子节点上 - 如图为示例的DAG,箭头方向为前向传播的方向,其中节点是前向传播中每个操作的backward function,蓝色节点是a和b
- 需要注意的是DAG是动态的,每次调用
backward()
时都会重新填出一个DAG,因此在每个迭代后都能改变形状和操作
- 将tensor的requires_grad设置成false就可 将DAG排除,autograd就不会计算它的精度。
在神经网络中,这种不需要计算梯度的参数叫frozen parameters,可以冻结不需要知道梯度的参数(节省计算资源),也可以在微调预训练模型时使用(此时往往冻结绝大多数参数,仅调整classifier layer(最后分类层)参数,以在新标签上做预测)
类似功能也可以用上下文管理器torch.no_grad()
实现。