pytorch知识点
- 1、tensor张量
- 2、variable(变量)
- 1.variable&autograd(自动求导)
- 2.autograd&.backward()
- 3.forward前向&backward反向
- 4、Parameter&torch.optim(优化)
- 3、Module(模型)
- 4、神经网络训练过程
- 5、pytorch与TensorFlow对比
- 6、Pytorch Hub
- 7、常见运算
pytorch主要包括三个层次:tensor(张量),variable(变量),Module(模型)
官方中文文档:https://pytorch.apachecn.org/#/
1、tensor张量
张量是具有统一类型(称为 dtype)的多维数组。您可以在 tf.dtypes.DType 中查看所有支持的 dtypes。如果您熟悉 NumPy,就会知道张量与 np.arrays 有一定的相似性。就像 Python 数值和字符串一样,所有张量都是不可变的:永远无法更新张量的内容,只能创建新的张量。
Tensor是PyTorch中重要的数据结构,可认为是一个高维数组。它可以是一个数(标量)、一维数组(向量)、二维数组(矩阵)以及更高维的数组。Tensor和Numpy的ndarrays类似,但Tensor可以使用GPU进行加速。Tensor的使用和Numpy及Matlab的接口十分相似取值,切片,等等与numpy一样。Tensor和numpy之间的互操作非常容易且非常快速。对于Tensor不支持的操作,可以先转为Numpy数组处理,之后再转回Tensor。张量如同数组和矩阵一样, 是一种特殊的数据结构。张量的使用和Numpy中的ndarrays很类似, 区别在于张量可以在GPU或其它专用硬件上运行, 这样可以得到更快的加速效果。
- 张量的数据类型
① scalar 标量
② vector 向量
③ matrix 矩阵
④ n-dimensional vector 多维张量
矩阵表示
1、二维数组:3行4列矩阵
a = torch.tensor([[1,5,62,54], [2,6,2,6], [2,65,2,6]])
tensor([[ 1, 5, 62, 54],
[ 2, 6, 2, 6],
[ 2, 65, 2, 6]])
2、三维数组,大小是2x2x3
a = np.array([
-----------------------------------------
[
[1.5, 6.7, 2.4],
[6.8, 3.4, 9.3]
],
-------------------------------------------
[
[3.1, 6.5, 1.9],
[8.9, 1.2, 2.5]
]
---------------------------------------------
])
3、三维数组(3, 5, 2)
[[['参赛者A1' '国籍A1']
['参赛者A2' '国籍A2']
['参赛者A3' '国籍A3']
['参赛者A4' '国籍A4']
['参赛者A5' '国籍A5']]
[['参赛者B1' '国籍B1']
['参赛者B2' '国籍B2']
['参赛者B3' '国籍B3']
['参赛者B4' '国籍B4']
['参赛者B5' '国籍B5']]
[['参赛者C1' '国籍C1']
['参赛者C2' '国籍C2']
['参赛者C3' '国籍C3']
['参赛者C4' '国籍C4']
['参赛者C5' '国籍C5']]]
张量形状
形状:张量的每个轴的长度(元素数量)。shape(n*m)
秩:张量轴数。标量的秩为 0,向量的秩为 1,矩阵的秩为 2。
轴或维度:张量的一个特殊维度。
大小:张量的总项数,即形状矢量元素的乘积
索引&切片
TensorFlow 遵循标准 Python 索引编制规则(类似于在 Python 中为列表或字符串编制索引)以及 NumPy 索引编制的基本规则。
- 单轴索引
索引从 0 开始编制
负索引表示按倒序编制索引
冒号 : 用于切片:start:stop:step - 多轴索引
更高秩的张量通过传递多个索引来编制索引。对于高秩张量的每个单独的轴,遵循与单轴情形完全相同的规则。
2、variable(变量)
1.variable&autograd(自动求导)
variable提供了自动求导功能,和Tensor没有本质区别,Variable会被放入一个计算图,进行前向传播,反向传播,自动求导。注意:Tensor不能反向传播,variable可以。如果我想取出网络输出的结果时,由于网络输入输出都是Variable,也需要执行Variable2Tensor,如果进一步我们想把loss显示出来,就需要Tensor2Numpy。
variable是一种可以不断变化的变量,符合反向传播,参数更新的属性。pytorch的variable是一个存放会变化值的地理位置,里面的值会不停变化。pytorch都是由tensor计算的,而tensor里面的参数是variable形式。autograd根据用户对Variable的操作来构建其计算图。 variable默认是不需要被求导的,即requires_grad属性默认为False,如果某一个节点的requires_grad为True,那么所有依赖它的节点requires_grad都为True。Variable 在torch.autograd.Variable,如果将一个tensor变成variable: variable(a)。
- Variable有三个属性:
.data:tensor本身
.grad:对应tensor的梯度
.grad_fn:该Variable是通过什么方式获得的
2.autograd&.backward()
通过调用backward(),我们可以对某个Variable(譬如说y)进行一次自动求导,但如果我们再对这个Variable进行一次backward()操作,会发现程序报错。这是因为PyTorch默认做完一次自动求导后,就把计算图丢弃了。我们可以通过设置retain_graph来实现多次求导。
autograd(自动微分):我们知道,神经网络是需要依靠反向传播求解梯度后来更新参数,求梯度是一个极其繁琐且容易出错的过程,而Pytorch可以帮助我们自动完成梯度运算,这边是Pytorch的autograd(自动微分)机制。autograd.Variable 是包的中央类, 它包裹着Tensor, 支持几乎所有Tensor的操作,并附加额外的属性, 在进行操作以后, 通过调用.backward()来计算梯度, 通过.data来访问原始raw data (tensor), 并将变量梯度累加到.grad。
调用.backward()时,开始反向传播,Autograd 会为每个模型参数计算梯度并将其存储在参数的.grad属性中。调用.backward()时,反向传递开始, autograd然后:
- 从每个.grad_fn计算梯度,
- 将它们累积在各自的张量的.grad属性中,然后
- 使用链式规则,一直传播到叶子张量。
3.forward前向&backward反向
torch.nn.functional进行前向传播运算,torch.autograd做后向传播运算
前向传播是通过数据,计算出每个变量以及每层的权重,得出loss的过程
反向传播是在得到loss之后,反过去调整每个变量以及每层的权重,通常需要计算偏导。
一般来说,权重的调整通过学习度以及偏导(梯度)来计算:
得到新的权重后,继续进行前向传播,计算loss,然后再反向传播进行迭代,直到loss达到最优。
4、Parameter&torch.optim(优化)
与其像以前那样手动更新模型的权重,不如使用optim包定义一个优化器,该优化器将为我们更新权重。 optim包定义了许多深度学习常用的优化算法,包括 SGD + 动量,RMSProp,Adam 等。
这将使我们替换之前的手动编码优化步骤:
with torch.no_grad():
for p in model.parameters(): p -= p.grad * lr
model.zero_grad()
而是只使用:opt.step()和opt.zero_grad()
(optim.zero_grad()将梯度重置为 0,我们需要在计算下一个小批量的梯度之前调用它。)
1、手动更新
with torch.no_grad():
for p in model.parameters(): p -= p.grad * lr
model.zero_grad()
或
with torch.no_grad():
for param in model.parameters():
param -= learning_rate * param.grad
2、potim优化
def get_model():
model = Mnist_Logistic()
return model, optim.SGD(model.parameters(), lr=lr)
model, opt = get_model()
print(loss_func(model(xb), yb))
for epoch in range(epochs):
for i in range((n - 1) // bs + 1):
start_i = i * bs
end_i = start_i + bs
xb = x_train[start_i:end_i]
yb = y_train[start_i:end_i]
pred = model(xb)
loss = loss_func(pred, yb)
loss.backward()
opt.step()
opt.zero_grad()
print(loss_func(model(xb), yb))
在定义自已的神经网络的时候,需要继承 nn.Module 类,并 重新实现 构造函数 init 和 forward 这两个方法。构造函数 init 中定义 网络结构,各层参数,传入指定的参数等,forward() 函数定义网络的 前向传播方法(前向传播顺序),一般需要传入 self 以及输入参数 input。
nn.Module(神经网络):nn.Module是专门为神经网络设计的模块化接口,构建于autograd之上,可以用来定义和运行神经网络,是搭建神经网络时需要继承的父类。
神经网络的典型训练过程如下:
- 定义模型
1.1 绘制模型
1.2 模型参数 - 前向传播
- 计算损失
- 反向传播
- 更新参数
- 1.定义模型:用torch.nn定义网络的参数结构,。
- 2.前向传播:torch.nn.functional的forward进行前向传播运算
- 3.损失函数:计算目标量和网络输出量的误差,有很多种定义。nn包下有几种不同的损失函数。 一个简单的损失是:nn.MSELoss,它计算输入和目标之间的均方误差。
- 4.反向传播:基于loss调用后向传播函数backward()。
- 5.更新参数:torch.optim随机梯度下降( Stochastic Gradient Descent ,SGD)是最实用简单的更新法则,weight = weight - learning_rate * gradient。
import torch
import torch.nn as nn
import torch.nn.functional as F
1.定义模型
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 1 input image channel, 6 output channels, 5x5 square convolution
# kernel
self.conv1 = nn.Conv2d(1, 6, 5)
self.conv2 = nn.Conv2d(6, 16, 5)
# an affine operation: y = Wx + b
self.fc1 = nn.Linear(16 * 5 * 5, 120) # 5*5 from image dimension
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# Max pooling over a (2, 2) window
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# If the size is a square, you can specify with a single number
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = torch.flatten(x, 1) # flatten all dimensions except the batch dimension
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
2.前向传播
net = Net()
input = torch.randn(1, 1, 32, 32)
output = net(input)
target = torch.randn(10) # a dummy target, for example
target = target.view(1, -1) # make it the same shape as output
3.损失函数
criterion = nn.MSELoss()
loss = criterion(output, target)
print(loss)
4.反向传播
net.zero_grad() # zeroes the gradient buffers of all parameters
loss.backward()
5.更新参数
import torch.optim as optim
# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)
# in your training loop:
optimizer.zero_grad() # zero the gradient buffers
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step() # Does the update
对于图像,Pillow,OpenCV 等包很有用
对于音频,请使用 SciPy 和 librosa 等包
对于文本,基于 Python 或 Cython 的原始加载,或者 NLTK 和 SpaCy 很有用
专门针对视觉,我们创建了一个名为torchvision的包,其中包含用于常见数据集(例如 Imagenet,CIFAR10,MNIST 等)的数据加载器,以及用于图像(即torchvision.datasets和torch.utils.data.DataLoader)的数据转换器。
torch.nn
Module:创建一个行为类似于函数的可调用对象,但也可以包含状态(例如神经网络层权重)。 它知道其中包含的 Parameter ,并且可以将其所有坡度归零,遍历它们以进行权重更新等。
Parameter:张量的包装器,用于告知 Module 具有在反向传播期间需要更新的权重。 仅更新具有require_grad属性集的张量
functional:一个模块(通常按照惯例导入到 F 名称空间中),其中包含激活函数,损失函数等。 以及卷积和线性层等层的无状态版本。
torch.optim:包含诸如 SGD 的优化程序,这些优化程序在后退步骤
Dataset 中更新 Parameter 的权重。 具有 len 和 getitem 的对象,包括 Pytorch 提供的类,例如 TensorDataset
DataLoader:获取任何 Dataset 并创建一个迭代器,该迭代器返回批量数据。
Pytorch:与TensorFlow等主流深度学习框架相比,Pytorch之所以可以与之分庭抗礼,是因为它有如下优点
- 很简洁:Pytorch的设计追求最少的封装,尽量避免重复造轮子,API设计的相当简洁一致。Pytorch的设计遵循tensor→variable(autograd)→nn.Module 三个由低到高的抽象层次,分别代表高维数组(张量)、自动求导(变量)和神经网络(层/模块),而且这三个抽象之间联系紧密,可以同时进行修改和操作
- 速度快:Pytorch的灵活性不以速度为代价,在许多评测中,Pytorch的速度表现胜过TensorFlow和Keras等框架
- 易调试:由于Pytorch采用动态图,所以你可以像调试普通Python代码一样调试Pytorch
- 代码美:Pytorch是所有的框架中面向对象设计的最优雅的一个。PyTorch的面向对象的接口设计来源于Torch,而Torch的接口设计以灵活易用而著称
- 我们现在已经知道了PyTorch为了实现GPU加速功能,引入了Tensor,为了实现自动求导功能引入了Variable。我们一般读取的数据都是以Numpy Array方式的。在TensorFlow,Numpy的数据会在输入网络后自动转换为Tensor,一般不需要我们进行显性操作,但是在PyTorch,需要我们自己进行显性操作才可以的。
TensorFlow包含了二个层次:tensor,Module ;而pytorch包括了三个层次:tensor,variable,Module。为什么多了一个variable了,其实variable只是tensor的一个封装,这样一个封装,最重要的目的,就是能够保存住该variable在整个计算图中的位置,详细来说就是:能够知道计算图中各个变量之间的相互依赖关系。而主要的目的也是为了反向求梯度了;而Module,是一个更高的层次,如果使用这个Module,那可厉害了,这是一个神经网络的层次,可以直接调用全连接层,卷积层,等等神经网络。
6、Pytorch HubPytorch Hub是一个预先训练的模型存储库,旨在促进研究的重现性。简单来说就是很多人把各种项目训练的预训练模型上传到Pytorch Hub,然后我们直接通过torch.hub.load()接口就可以直接调用,迅速实现项目中的效果!
7、常见运算卷积运算参数如何计算
numpy矩阵如何用数组表示
Python中的item()和items()虽然一字之差但是用法却毫无关联,
item()
item()的作用是取出单元素张量的元素值并返回该值,保持该元素类型不变。
items()的作用是把字典中的每对key和value组成一个元组,并把这些元祖放在列表中返回。
Python 中的 with 语句用于异常处理,封装了 try…except…finally 编码范式,提高了易用性。
with torch.no_grad的作用
在该模块下,所有计算得出的tensor的requires_grad都自动设置为False。
先看torch.squeeze() 这个函数主要对数据的维度进行压缩,去掉维数为1的的维度,比如是一行或者一列这种,一个一行三列(1,3)的数去掉第一个维数为一的维度之后就变成(3)行。squeeze(a)就是将a中所有为1的维度删掉。不为1的维度没有影响。a.squeeze(N) 就是去掉a中指定的维数为一的维度。还有一种形式就是b=torch.squeeze(a,N) a中去掉指定的定的维数为一的维度
torch.max(input, dim, keepdim=False, out=None)
按维度dim 返回最大值以及最大值的索引。
dim = 0 表示按列求最大值,并返回其引
dim = 1 表示按行求最大值,并返回其索引
pow() 方法返回 xy(x 的 y 次方) 的值。
在PyTorch中,对模型参数的梯度置0时通常使用两种方式:model.zero_grad()和optimizer.zero_grad()。
view是 numpy 的reshape的 PyTorch 版本)