pytorch
环境准备
# 我用的版本:python: 3.9.7, torch: v1.10.0, torchvision: 0.11.0
$ pip3 install torch,torchvision
张量(Tensor)
常数是 0 阶张量。
向量 vevtor 是 1 阶张量。
矩阵 matrix 是 2 阶张量。
三维形状的就是 3 阶张量。
创建张量
import torch
import numpy as np
t1 = torch.tensor((1, 2, 3))
print(t1) # tensor([1., 2., 3.])
# 用 api 创建,每个数值都是0-10的随机整数,形状是3*4
t2 = torch.randint(low=0, high=10, size=(3, 4))
print(t2)
# tensor([[7, 0, 4, 0],
# [3, 7, 5, 9],
# [6, 9, 5, 0]])
# 可以把 torch 的 Tensor 转换成 numpy 的 Array
print(t2.numpy())
# [[7 0 4 0]
# [3 7 5 9]
# [6 9 5 0]]
array1 = np.arange(12).reshape(3, 4)
print(array1)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# 可以把 numpy 的 Array 转换成 torch 的 Tensor
print(torch.tensor(array1))
# tensor([[ 0., 1., 2., 3.],
# [ 4., 5., 6., 7.],
# [ 8., 9., 10., 11.]])
常用API
import torch
x = [[[1, 2, 3]]]
t1 = torch.tensor(x)
print(t1)
# 查形状
print(t1.size())
# 可以指定查某一个维度
print(t1.size(0), t1.size(1), t1.size(2), t1.size(-1))
# 改变形状,在 numpy 里用的是 reshape,在 torch 里用的是 view
print(t1.view(3))
# -1 表示自动适配,下面这个等价于 t1.view(3, 1),因为总共是 3 个元素
print(t1.view(3, -1))
# 获取阶数
print(t1.dim())
# 矩阵转置,在 numpy 里用的是 T()
print(torch.tensor([[1, 2]]).t())
torch.max(input, dim)
在分类问题中,通常需要使用max()
函数对softmax
函数的输出值进行操作,求出预测值索引,然后与标签进行比对,计算准确率。
输入:
input
是softmax
函数输出的一个tensor
dim
是max
函数索引的维度0/1,0是每列的最大值,1是每行的最大值。
输出:
函数会返回两个tensor
,第0个tensor
是每行的最大值(不用关心这个值);第1个tensor
是每行最大值的索引,也就是预测的这组样本中每个样本最大概率的类别的索引,然后根据该索引即可取出对应的类别。
示例
训练
import torch
import torchvision
import torch.nn as nn
from model import LeNet
import torch.optim as optim
import torchvision.transforms as transforms
def main():
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
# 50000张训练图片
# 第一次使用时要将download设置为True才会自动去下载数据集
train_set = torchvision.datasets.CIFAR10(
root='./data',
train=True,
download=True,
transform=transform)
train_loader = torch.utils.data.DataLoader(train_set, batch_size=36, # 在机器内存允许范围内,batch_size设置的越大,训练效果越好
shuffle=True, num_workers=0)
# 10000张验证图片
# 第一次使用时要将download设置为True才会自动去下载数据集
val_set = torchvision.datasets.CIFAR10(root='./data', train=False,
download=True, transform=transform)
val_loader = torch.utils.data.DataLoader(val_set, batch_size=5000,
shuffle=False, num_workers=0)
val_data_iter = iter(val_loader)
val_image, val_label = val_data_iter.next()
# classes = ('plane', 'car', 'bird', 'cat',
# 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
net = LeNet()
# 进 CrossEntropyLoss 看说明可以看出它已经包含了 softmax
loss_function = nn.CrossEntropyLoss()
optimizer = optim.Adam(net.parameters(), lr=0.001)
# 对训练数据集迭代5轮
for epoch in range(5): # loop over the dataset multiple times
running_loss = 0.0
# 按批次遍历数据集
for step, data in enumerate(train_loader, start=0):
# get the inputs; data is a list of [inputs, labels]
inputs, labels = data
# zero the parameter gradients
optimizer.zero_grad()
# forward + backward + optimize
outputs = net(inputs) # 对定义的网络正向传播得到的输出
loss = loss_function(outputs, labels) # 对训练集的模型预测值和实际标签值计算损失函数
loss.backward() # 反向传播
optimizer.step() # 使用优化器的参数更新
# print statistics
running_loss += loss.item()
if step % 500 == 499: # print every 500 mini-batches
# 这个步骤只是打印输出,指定在这个代码块里面不要去计算误差损失梯度,在验证测试和预测的环节都需要带上这个函数
with torch.no_grad():
# 对 val_image 这一批样本做预测
outputs = net(val_image) # [batch, 10]
# 得到最有可能的类别
predict_y = torch.max(outputs, dim=1)[1]
# 与真实类别做比较,得到预测的正确率
accuracy = torch.eq(predict_y, val_label).sum().item() / val_label.size(0)
print('[%d, %5d] train_loss: %.3f test_accuracy: %.3f' %
(epoch + 1, step + 1, running_loss / 500, accuracy))
# 把参数清零,进入下个批次的训练
running_loss = 0.0
print('Finished Training')
# 保存模型
save_path = './Lenet.pth'
torch.save(net.state_dict(), save_path)
if __name__ == '__main__':
main()
预测
import torch
import torchvision.transforms as transforms
from PIL import Image
from model import LeNet
def main():
transform = transforms.Compose(
[transforms.Resize((32, 32)),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
classes = ('plane', 'car', 'bird', 'cat',
'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
net = LeNet()
# 加载模型权重文件
net.load_state_dict(torch.load('Lenet.pth'))
im = Image.open('1.jpg')
im = transform(im) # [C, H, W]
im = torch.unsqueeze(im, dim=0) # [N, C, H, W]
with torch.no_grad():
outputs = net(im)
predict = torch.max(outputs, dim=1)[1].data.numpy()
print(classes[int(predict)])
if __name__ == '__main__':
main()
Last updated
Was this helpful?