pytorch面试复习

本文详细介绍了如何在PyTorch中使用torch.Tensor()和torch.tensor()创建张量,包括它们之间的区别,以及基本操作如形状、数学运算和形状变换。此外,还讲解了微调预训练模型的方法,以及如何构建和训练一个简单的神经网络模型。
摘要由CSDN通过智能技术生成

1. 处理张量

1.1. torch.Tensor()和torch.tensor()

  1. 相同点:
    生成新的张量
>>> a = torch.Tensor([1,2])
>>> a
tensor([1., 2.])
>>> a = torch.tensor([1,2])
>>> a
tensor([1, 2])
  1. 不同点
  • torch.Tensor()是python类,是torch.FloatTensor()的别名,生成float类型的张量;
  • torch.tensor()仅仅是python的函数,函数原型是torch.tensor(data, dtype=None, device=None, requires_grad=False),其中data可以是scalar,list,tuple,numpy array等等。torch.tensor会从data中的数据部分进行拷贝(而不是引用),根据原始数据类型生成相应的 torch.LongTensor、torch.FloatTensor和torch.DoubleTensor。比如:
>>> a = torch.tensor([1,2])
>>> a.type()
'torch.LongTensor'

>>> a = torch.tensor([1.,2.])
>>> a.type()
'torch.FloatTensor'

>>> a = np.zeros(2,dtype=np.float64)
>>> a = torch.tensor(a)
>>> a.type()
'torch.DoubleTensor'

1.2. 基本操作

# 创建一个3x3的随机张量
tensor = torch.rand(3, 3)
print("随机张量:", tensor)

# 获取张量的形状
print("张量形状:", tensor.shape)

# 获取张量的数据类型
print("张量数据类型:", tensor.dtype)

# 张量的加法操作
tensor_sum = tensor + tensor
print("张量相加:", tensor_sum)

# 张量的索引操作
print("张量索引:", tensor[0, 0])

1.3. 数学运算

# 创建两个张量
tensor1 = torch.tensor([[1, 2], [3, 4]])
tensor2 = torch.tensor([[5, 6], [7, 8]])

# 加法
addition = torch.add(tensor1, tensor2)

# 矩阵乘法
matrix_product = torch.matmul(tensor1, tensor2)

# 元素-wise 乘法
elementwise_product = torch.mul(tensor1, tensor2)

1.4. 形状操作

  1. 改变形状
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
reshaped_tensor = tensor.view(3, 2)
reshaped_tensor2 = tensor.reshape(3, 2)
>>> tensor([[1, 2],
        [3, 4],
        [5, 6]])
  1. squeeze() 和 unsqueeze()
    squeeze()方法用于删除大小为1的维度,而unsqueeze()方法用于在指定位置插入大小为1的维度。
tensor = torch.tensor([[1, 2, 3]])
# 使用squeeze删除维度
squeezed_tensor = tensor.squeeze()
# 使用unsqueeze插入维度
unsqueeze_tensor = tensor.unsqueeze(0)
  • 在多维张量的不同位置插入大小为1的维度
# 创建一个大小为(2, 3)的张量
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
# 在索引0处插入一个大小为1的维度
unsqueeze_dim0 = tensor.unsqueeze(0)
# 在索引1处插入一个大小为1的维度
unsqueeze_dim1 = tensor.unsqueeze(1)
# 在索引2处插入一个大小为1的维度
unsqueeze_dim2 = tensor.unsqueeze(2)
# 在负索引位置插入一个大小为1的维度
unsqueeze_tensor = tensor.unsqueeze(-1)

结果:

  • unsqueeze_dim0 的形状是 (1, 2, 3),在原始张量的最外层添加了一个维度。
  • unsqueeze_dim1 的形状是 (2, 1, 3),在原始张量的第二个维度(行)上添加了一个维度。
  • unsqueeze_dim2 的形状是 (2, 3, 1),在原始张量的最内层(列)添加了一个维度。
  • unsqueeze_tensor 的形状是 (2, 3, 1),它在原始张量的最内层添加了一个维度。
    unsqueeze() 方法在指定位置插入大小为1的维度,这在处理需要扩展维度的情况下非常有用。
  1. permute(),transpose(),t()
    permute()方法用于重新排列张量的维度顺序,而transpose()方法用于交换张量的两个维度。
tensor = torch.randn(2, 3, 4)
# 使用permute重新排列维度顺序
permuted_tensor = tensor.permute(1, 2, 0)
# permute(1, 2, 0) 将其重新排列为 (3, 4, 2)

# 使用transpose交换维度
transposed_tensor = tensor.transpose(0, 1)

# 使用t转置张量
transposed_tensor = tensor.t()

  • .t() 属性仅适用于二维张量(矩阵),用于交换矩阵的维度。
  • 对于二维张量,.t() 是 transpose(0, 1) 的快捷方式,即交换第一维和第二维。
  1. 索引和切片
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])

# 索引
print("索引结果:", tensor[0, 1])  # 获取第一行第二列的元素

# 切片
print("切片结果:", tensor[:, 1])  # 获取第二列的所有元素

2. 微调 fine-tuning

在加载了预训练模型参数之后,需要finetuning模型,可以使用不同的方式finetune:

  1. 局部微调:
    加载了模型参数后,只想调节最后几层,其它层不训练,也就是不进行梯度计算,pytorch提供的requires_grad使得对训练的控制变得非常简单。
model = torchvision.models.resnet18(pretrained=True)
for param in model.parameters():
    param.requires_grad = False

# 仅解冻最后的几层用于微调
for param in model.layer4.parameters():
    param.requires_grad = True

# 替换最后的全连接层,因为原始模型的最后一层是针对原始数据集的类别
# 假设我们有一个新的数据集,有10个类别
num_ftrs = model.fc.in_features
model.fc = torch.nn.Linear(num_ftrs, 10)  # 替换为新的全连接层,适应新的数据集
 
# 定义损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

  1. 全局微调
    对全局微调时,只不过我们希望改换过的层和其他层的学习速率不一样,这时候把其它层和新层在optimizer中单独赋予不同的学习速率。
model = torchvision.models.resnet18(pretrained=True)
for param in model.parameters():
    param.requires_grad = False
    
# 替换最后的全连接层,因为原始模型的最后一层是针对原始数据集的类别
# 假设我们有一个新的数据集,有10个类别
num_ftrs = model.fc.in_features
model.fc = torch.nn.Linear(num_ftrs, 10)  # 替换为新的全连接层,适应新的数据集

optimizer = optim.SGD(model.fc.parameters(), lr=1e-2, momentum=0.9)

3. 创建一个简单的神经网络模型

import torch
import torch.nn as nn

# 定义一个简单的全连接神经网络模型
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(10, 5)  # 输入维度为10,输出维度为5
        self.fc2 = nn.Linear(5, 2)   # 输入维度为5,输出维度为2
    
    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = self.fc2(x)
        return x

# 创建一个模型实例
model = SimpleNN()
print(model)
  • super() 是一个内置函数,用于调用父类的方法。在 Python 中,当你创建一个子类并且想要调用父类的方法时,可以使用 super() 函数。
  • 在这个例子中,super(SimpleNN, self).__init__() 的作用是调用 SimpleNN 类的父类(通常是 nn.Module)的构造函数 __init__() 方法。通过这种方式,你可以确保在创建 SimpleNN 实例时,同时也会执行其父类的初始化操作,以确保所有必要的设置都已经完成。

4. 训练一个简单的神经网络模型

import torch
import torch.nn as nn
import torch.optim as optim

# 创建数据集
X_train = torch.rand(100, 10)  # 100个样本,每个样本10个特征
y_train = torch.randint(0, 2, (100,))  # 二分类标签,0或1

# 定义模型、损失函数和优化器
model = SimpleNN()
criterion = nn.CrossEntropyLoss()  # 交叉熵损失函数
optimizer = optim.SGD(model.parameters(), lr=0.01)  # 随机梯度下降优化器

# 训练模型
num_epochs = 10
for epoch in range(num_epochs):
    optimizer.zero_grad()  # 梯度清零
    outputs = model(X_train)  # 模型前向传播
    loss = criterion(outputs, y_train)  # 计算损失
    loss.backward()  # 反向传播
    optimizer.step()  # 更新参数
    
    print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值