pytorch知识点

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、二维数组:34列矩阵
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))

3、Module(模型)

在定义自已的神经网络的时候,需要继承 nn.Module 类,并 重新实现 构造函数 init 和 forward 这两个方法。构造函数 init 中定义 网络结构,各层参数,传入指定的参数等,forward() 函数定义网络的 前向传播方法(前向传播顺序),一般需要传入 self 以及输入参数 input。
nn.Module(神经网络):nn.Module是专门为神经网络设计的模块化接口,构建于autograd之上,可以用来定义和运行神经网络,是搭建神经网络时需要继承的父类。

4、神经网络训练过程

神经网络的典型训练过程如下:

  1. 定义模型
    1.1 绘制模型
    1.2 模型参数
  2. 前向传播
  3. 计算损失
  4. 反向传播
  5. 更新参数
  • 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 的权重。 具有 lengetitem 的对象,包括 Pytorch 提供的类,例如 TensorDataset
DataLoader:获取任何 Dataset 并创建一个迭代器,该迭代器返回批量数据。

5、pytorch与TensorFlow对比

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 Hub

Pytorch Hub是一个预先训练的模型存储库,旨在促进研究的重现性。简单来说就是很多人把各种项目训练的预训练模型上传到Pytorch Hub,然后我们直接通过torch.hub.load()接口就可以直接调用,迅速实现项目中的效果!
参考:https://juejin.cn/post/7098957600049659918

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 版本)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值