pytorch入门篇

张量

张量(Tensors)类似于NumPy的ndarrays,但张量可以在GPU上进行计算。 所以从本质上来说,PyTorch是一yi个处理张量的库。一个张量是一个数字、向量、矩阵或任何n维数组。
在这里插入图片描述

张量的创建

直接创建

torch.tensor(data, dtype=None, device=None, requires_grad=False, pin_memory=False)

data: 数据,可以是list,numpy
dtype: 数据类型,默认与data的一致
device: 所在设备,cuda/cpu
requires_grad: 是否需要梯度
pin_memory: 是否存于锁页内存

依据数值创建

torch.zeros(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
torch.ones(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

size: 张量的形状,如(3, 3)、(3, 224, 224)
out: 输出的张量
layout: 内存中布局形式,有strided, sparse_coo等
device: 所在设备,gpu/cpu
requires_grad: 是否需要梯度

torch.zeros_like(input, dtype=None, layout=None, device=None, requires_grad=False)
torch.ones_like(input, dtype=None, layout=None, device=None, requires_grad=False)

input: 创建与input同形状的全0张量
dtype: 数据类型
layout: 内存中布局形式

torch.full(size, fill_value, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)
torch.full_like(input, dtype=None, layout=torch.strided, device=None, requires_grad=False)

size: 张量的形状,如(3, 3)
fill_value: 张量的值

torch.arange(start=0, end. step=1, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:创建等差的1维张量
start: 数列起始值
end: 数列“结束值”
step: 数列公差,默认为1
注意事项:数值区间为 [start,end)

依概率分布创建张量

torch.normal(mean, std, out=None)

功能:生成正态分布(高斯分布)
mean: 均值
std: 标准差
四种模式:
mean为标量,std为标量
mean为标量,std为张量
mean为张量,std为标量
mean为张量,std为张量

torch.normal(mean, std, size, out=None)

功能:生成一定大小的生成正态分布(高斯分布)

在这里插入图片描述

torch.randn(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:生成标准正态分布
size: 张量的形状

在这里插入图片描述

torch.rand(*size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:在区间 [0,1) 上,生成均匀分布

在这里插入图片描述

torch.randint(low=0, high, size, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False)

功能:区间 [low,high) 生成整数均匀分布
size:张量的形状

在这里插入图片描述

张量的操作

张量的拼接与切分

torch.cat(tensors, dim=0, out=None)

功能:将张量按维度dim进行拼接
tensors:张量序列
dim:要拼接的维度

在这里插入图片描述

torch.stack(tensors, dim=0, out=None)

功能:在新创建的维度dim上进行拼接
tensors:张量序列
dim:要拼接的维度

torch.split(tensor, split_size_or_sections, dim=0)

返回值:张量列表
tensor:要切分的张量
split_size_or_sections:为int时,表示每一份的长度;为list时,按list元素切分
dim:要切分的维度

在这里插入图片描述

张量索引

torch.index_select(input, dim, index, out=None)

功能:在维度dim上,按index索引数据
返回值:依index索引数据拼接的张量
index:要索引的张量
dim:要索引的维度
index:要索引数据的序号

在这里插入图片描述

torch.masked_select(input, mask, out=None)

功能:按mask中的True进行索引
返回值:一维张量
input:要索引的张量
mask:与input同形状的布尔类型张量

在这里插入图片描述

张量变换

torch.reshape(input, shape)

功能:变换张量形状
注意事项:当张量在内存中是连续时,新张量与input共享数据内存
input:要变换的张量
shape:新张量的形状

在这里插入图片描述

torch.transpose(input, dim0, dim1)

功能:交换张量的两个维度
input:要交换的张量
dim0:要交换的维度
dim1:要交换的维度

在这里插入图片描述

torch.squeeze(input, dim=None, out=None)

功能:压缩长度为1的维度(轴)
dim:若为None,移除所有长度为1的轴;若指定维度,当且仅当该轴长度为1时,可以被移除

在这里插入图片描述

torch.unsqueeze(input, dim, out=None)

功能:依据dim扩展维度
dim:扩展的维度

在这里插入图片描述

线性回归模型

在这里插入图片描述

# 首先我们得有训练样本X,Y, 这里我们随机生成
x = torch.rand(20, 1) * 10
y = 2 * x + (5 + torch.randn(20, 1))

# 构建线性回归函数的参数
w = torch.randn((1), requires_grad=True)
b = torch.zeros((1), requires_grad=True)   # 这俩都需要求梯度

# 设置学习率lr为0.1
lr = 0.1

for iteration in range(100):
    # 前向传播
    wx = torch.mul(w, x)
    y_pred = torch.add(wx, b)
 
    # 计算loss
    loss = (0.5 * (y-y_pred)**2).mean()
 
    # 反向传播
    loss.backward()
 
    # 更新参数
    b.data.sub_(lr * b.grad)    # 这种_的加法操作时从自身减,相当于-=
    w.data.sub_(lr * w.grad)

    # 梯度清零
    w.grad.data.zero_()
    b.grad.data.zero_()

print(w.data, b.data)

在这里插入图片描述

神经网络

softmax

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

softmax实现

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import torch
from torch import nn

# 确定随机数种子
torch.manual_seed(7)
# 自定义数据集
X = torch.rand((7, 2, 2))
print(X)
target = torch.randint(0, 3, (7,))
print(target)


# 自定义网络结构
class LinearNet(nn.Module):
    def __init__(self):
        super(LinearNet, self).__init__()
        # 定义一层全连接层
        self.dense = nn.Linear(4, 3)   # 4 = 2*2  3是target的类别数
        # 定义Softmax
        self.softmax = nn.Softmax(dim=1)

    def forward(self, x):
        y = self.dense(x.view((-1, 4)))   # view 类似于reshape()  -1 表示不确定 自动计算
        y = self.softmax(y)
        return y

net = LinearNet()

loss = nn.CrossEntropyLoss()  # 交叉熵损失函数

optimizer = torch.optim.SGD(net.parameters(), lr=0.1)  # 随机梯度下降法

for epoch in range(70):
    train_l = 0.0
    y_hat = net(X)
    l = loss(y_hat, target).sum()

    # 梯度清零
    optimizer.zero_grad()
    # 自动求导梯度
    l.backward()
    # 利用优化函数调整所有权重参数
    optimizer.step()

    train_l += l
    print('epoch %d, loss %.4f' % (epoch + 1, train_l))

自动求导

torch.autograd.backward(tensors, grad_tensors=None, retain_graph=None, create_graph=False)

功能:自动求取梯度
tensors:用于求导的张量,如 loss
retain_graph:保存计算图
create_graph:创建导数计算图,用于高阶求导
grad_tensors:多梯度权重

在这里插入图片描述

torch.autograd.grad(outputs, inputs, grad_outputs=None, retain_graph=None, create_graph=False)

功能:求取梯度
outputs:用于求导的张量,如 loss
inputs:需要梯度的张量
create_graph:创建导数计算图,用于高阶求导
retain_graph:保存计算图
grad_outputs:多梯度权重

在这里插入图片描述

autograd小贴士:
梯度不自动清零
依赖于叶子节点的节点,requires_grad默认为True
叶子节点不可执行in-place
autograd 包是 PyTorch 中所有神经网络的核心。
首先让我们简要地介绍它,然后我们将会去训练我们的第一个神经网络。该 autograd 软件包为 Tensors 上的所有操作提供自动微分。它是一个由运行定义的框架,这意味着以代码运行方式定义你的后向传播,并且每次迭代都可以不同。
我们从 tensor 和 gradients 来举一些例子。
torch.Tensor是包的核心类。如果将其属性.requires_grad设置为True,则会开始跟踪针对tensor的所有操作。完成计算后,你可以调用.backward()来自动计算所有梯度。该张量的梯度将累积到.grad属性中
要停止tensor历史记录的跟踪,你可以调用.detach(),它将其与计算历史记录分离,并防止将来的计算被跟踪。
要停止跟踪历史记录(和使用内存),你还可以将代码块使用with torch.no_grad():包装起来。在评估模型时,这是特别有用,因为模型在训练阶段具有requires_grad=True的可训练参数有利于调参,但在评估阶段我们不需要梯度。
还有一个类对于autograd实现非常重要那就是Function。Tensor和Function互相连接并构建一个非循环图,它保存整个完整的计算过程的历史信息。每个张量都有一个.grad_fn属性保存着创建了张量的Function的引用(如果用户自己创建张量,则grad_fn是None)。
如果你想计算导数,你可以调用Tensor.backward()。如果Tensor是标量(即它包含一个元素数据),则不需要指定任何参数backward(),但是如果它有更多元素,则需要指定一个gradient参数来指定张量的形状。

transforms方法

裁剪
a. transforms.CenterCrop
b. transforms.RandomCrop
c. transforms.RandomResizedCrop
d. transforms.FiveCrop
e. transforms.TenCrop

翻转和旋转
a. transforms.RandomHorizontalFlip
b. transforms.RandomVerticalFlip
c. transforms.RandomRotation

图像变换
a. transforms.Pad
b. transforms.ColorJitter
c. transforms.Grayscale
d. transforms.RandomGrayscale
e. transforms.RandomAffine
f. transforms.LinearTransformation
g. transforms.RandomErasing
h. transforms.Lambda
i. transforms.Resize
j. transforms.Totensor
k. transforms.Normalize

transforms的操作
a. transforms.RandomChoice
b. transforms.RandomApply
c. transforms.RandomOrder

迁移学习

迁移学习就是利用数据、任务或模型之间的相似性,将在旧的领域学习过或训练好的模型,应用于新的领域这样的一个过程。从这段定义里面,我们可以窥见迁移学习的关键点所在,即新的任务与旧的任务在数据、任务和模型之间的相似性。
本节我们介绍迁移学习中的一种常用技术:微调(fine tuning)。微调由以下4步构成。
在源数据集(如ImageNet数据集)上预训练一个神经网络模型,即源模型
创建一个新的神经网络模型,即目标模型。它复制了源模型上除了输出层外的所有模型设计及其参数。我们假设这些模型参数包含了源数据集上学习到的知识,且这些知识同样适用于目标数据集。我们还假设源模型的输出层跟源数据集的标签紧密相关,因此在目标模型中不予采用。
为目标模型添加一个输出大小为目标数据集类别个数的输出层,并随机初始化该层的模型参数
在目标数据集(如FashionMNIST数据集)上训练目标模型。我们将从头训练输出层,而其余层的参数都是基于源模型的参数微调得到的。

在这里插入图片描述
在这里插入图片描述

class SurfaceDefectResNet(torch.nn.Module):
    def __init__(self):
        super(SurfaceDefectResNet, self).__init__()
        # Downloading: "https://download.pytorch.org/models/resnet18-5c106cde.pth" to /home/admin/.cache/torch/hub/checkpoints/resnet18-5c106cde.pth
        # 加载模型 及其 所有参数
        self.cnn_layers = torchvision.models.resnet18(pretrained=True)	
        # 定义了一个变量 "num_ftrs",表示模型中全连接层(fc)的输入特征数。
        num_ftrs = self.cnn_layers.fc.in_features
        # 修改了模型中的全连接层,将输入特征数设置为 "num_ftrs",输出特征数设置为 10。
        self.cnn_layers.fc = torch.nn.Linear(num_ftrs, 10)

    def forward(self, x):
        # stack convolution layers
        out = self.cnn_layers(x)
        return out

net = SurfaceDefectResNet()

保存和加载模型

状态字典 state_dict

在PyTorch中,torch.nn.Module模型的可学习参数(即权重和偏差)包含在模型的参数中,(使用model.parameters()可以进行访问)。 state_dict是Python字典对象,它将每一层映射到其参数张量。注意,只有具有可学习参数的层(如卷积层,线性层等)的模型 才具有state_dict这一项。目标优化torch.optim也有state_dict属性,它包含有关优化器的状态信息,以及使用的超参数。
因为state_dict的对象是Python字典,所以它们可以很容易的保存、更新、修改和恢复,为PyTorch模型和优化器添加了大量模块。

import torch
from torch import nn, optim
# 定义模型
class TheModelClass(nn.Module):
    def __init__(self):
        super(TheModelClass, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

# 初始化模型
model = TheModelClass()

# 初始化优化器
optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

# 打印模型的状态字典
print("Model's state_dict:")
for param_tensor in model.state_dict():
    print(param_tensor, "\t", model.state_dict()[param_tensor].size())

# 打印优化器的状态字典
print("Optimizer's state_dict:")
for var_name in optimizer.state_dict():
    print(var_name, "\t", optimizer.state_dict()[var_name])

在这里插入图片描述

保存和加载推理模型state_dict

# 保存  
PATH = './download'
torch.save(model.state_dict(), PATH)

# 加载
model = TheModelClass()
model.load_state_dict(torch.load(PATH))
model.eval()

当保存好模型用来推断的时候,只需要保存模型学习到的参数,使用torch.save()函数来保存模型state_dict,它会给模型恢复提供最大的灵活性,这就是为什么要推荐它来保存的原因。
在 PyTorch 中最常见的模型保存使‘.pt’或者是‘.pth’作为模型文件扩展名
请记住,在运行推理之前,务必调用model.eval()去设置 dropout 和 batch normalization 层为评估模式。如果不这么做,可能导致 模型推断结果不一致。
注意:
load_state_dict()函数只接受字典对象,而不是保存对象的路径。这就意味着在你传给load_state_dict()函数之前,你必须反序列化 你保存的state_dict。例如,你无法通过 model.load_state_dict(PATH)来加载模型。

保存/加载完整模型

# 保存
torch.save(model, PATH)
# 加载
model = torch.load(PATH)
model.eval()

此部分保存/加载过程使用最直观的语法并涉及最少量的代码。以 Python pickle 模块的方式来保存模型。这种方法的缺点是序列化数据受 限于某种特殊的类而且需要确切的字典结构。这是因为pickle无法保存模型类本身。相反,它保存包含类的文件的路径,该文件在加载时使用。 因此,当在其他项目使用或者重构之后,您的代码可能会以各种方式中断。
在 PyTorch 中最常见的模型保存使用‘.pt’或者是‘.pth’作为模型文件扩展名。
请记住,在运行推理之前,务必调用model.eval()设置 dropout 和 batch normalization 层为评估模式。如果不这么做,可能导致模型推断结果不一致。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值