PyTorch 作为深度学习非常重要的框架之一,在科研和开发领域有着非常广泛的使用,是我们学习和研究 LLM 必备的工具之一。
本文主要介绍三个 PyTorch 的实战案例,方便大家快速了解和体验 PyTorch。
一、PyTorch 简介
PyTorch 是一个开源的 Python 深度学习框架,它具有灵活、高效、易于学习等优点,被广泛应用于计算机视觉、自然语言处理、语音识别等领域。
PyTorch 提供了丰富的工具和函数库,它的核心是一个张量计算库,支持在 GPU 或 CPU 上进行张量计算,并且具有自动求导、动态图、模型保存和加载等功能。
以上2段内容由飞书智能伙伴生成,并稍作修改:)
PyTorch 特性如下:
-
动态计算图:使用的计算图是动态的,Define By Run,随时调整模型的结构和大小,更容易调试和设计神经网络,设计新模型更加友好。而像TensorFlow的计算图是静态的,往往不会在训练的过程中做太多的调整。
-
直观的API设计:接口更加Pythonic,接近Python语言的风格
-
强大的GPU加速训练:和NV的CUDA GPU结合的非常好,可以并行的进行计算
-
丰富的预训练模型和工具:如 torchvision 和 torchtext
-
活跃的社区:PyTorch 有完善的文档,B站上也有不少优秀的学习视频
二、PyTorch 训练流程图
PyTorch 常见的训练流程,通常包含以下步骤:
-
数据源:准备和提供数据
-
数据处理:转化为PyTorch支持的Tensor,用于并行处理
-
模型训练:将未训练的模型,训练成我们需要的模型,如支持分类、回归、文本生成等,必须支持分布式并行训练,否则效率不高
-
模型生产化部署:支持将模型部署到服务器上,提供相应的服务(如torch.jit,ONNX)
三、PyTorch 代码训练套路
先掌握基本套路,再根据具体场景,迭代优化(以下为示意代码)。
1、导入必要的库:
import torch
import torch.nn as nn
import torch.optim as optim
2、定义数据集:
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
3、定义模型(网络结构):
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 定义网络结构
def forward(self, x):
# 定义前向传播
return x
model = Net
4、定义损失函数和优化器:
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model,parameters(), lr=0.001)
5、模型训练:
for epoch in range(num_epochs):
for inputs, labels in dataloader:
# 将梯度归零
optimizer.zero_grad()
# 前向传播
outputs = model(inputs)
# 计算损失
loss = criterion(outputs, labels)
# 反向传播
loss.backward()
# 更新权重
optimizer.setp()
6、验证/评估模型:
model.eval() # 将模型设置为评估模式
with torch_no_grad():
for inputs, labels in validation_dataloader:
outputs = model(inputs)
# 计算验证损失、、准确性等指标
...
model.train() # 将模型设置回训练模式
7、保存和加载模型:
# 保存模型
torch.save(model.state_dict(), 'model.pth')
# 加载模型
model.load_stat_dict(torch.load('model.pth'))
8、预测/推理:
with torch_no_grad():
predictions = model(new_data)
四、PyTorch 实战1:目标检测
0、实战场景
基于 PyTorch 来做目标检测任务实战,基于 ResNet50 模型。
1、数据准备
采用 CoCo 数据集:
数据集样例:
2、代码实战
import torch
import torchvision
from torchvision.models.detection import fasterrcnn_resnet50_fpn
from torchvision.transforms import functional as F
from PIL import Image, ImageDraw
import matplotlib.pyplot as plt
model = fasterrcnn_resnet50_fpn(pretrained=True)
model.eval()
#
image = Image.open('pic_dog_bike_car.jpg')
image = image.resize((800, 600))
image_tensor = F.to_tensor(image)
with torch.no_grad():
prediction = model([image_tensor])
labels = prediction[0]['labels']
scores = prediction[0]['scores']
boxes = prediction[0]['boxes']
COCO_CLASSES = [
'N/A', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'N/A',
'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse',
'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'N/A', 'backpack',
'umbrella', 'N/A', 'N/A', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis',
'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard',
'surfboard', 'tennis racket', 'bottle', 'N/A', 'wine glass', 'cup', 'fork', 'knife',
'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog',
'pizza', 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed', 'N/A', 'dining table', 'N/A',
'N/A', 'toilet', 'N/A', 'tv', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone',
'microwave', 'oven', 'toaster', 'sink', 'refrigerator', 'N/A', 'book',
'clock', 'vase', 'scissors', 'teddy bear', 'hair drier', 'toothbrush']
# 筛选分数大于0.8的预测
threshold = 0.8
labels = labels[scores > threshold]
boxes = boxes[scores > threshold].cpu().numpy()
scores = scores[scores > threshold].cpu().numpy()
# 使用PIL在图像上绘制边界框
draw = ImageDraw.Draw(image)
for box, label, score in zip(boxes, labels, scores):
class_name = COCO_CLASSES[label.item()]
draw.rectangle(box, outline='red', width=3)
draw.text((box[0], box[1]), text=f'{class_name} {score:.2f}', fill='blue')
plt.imshow(image)
plt.axis('off')
plt.show()
3、推理效果
以如下这张图片作为目标检测用例:
将上面的测试图片,保存为pic_dog_bike_car.jpg
文件,和代码(pytorch_prediction_on_action.py
)放在同一目录,安装好相应的库,即可直接运行。
识别的效果如下:
代码中设置的阈值是 0.8(threshold = 0.8
),所以只识别出了狗和自行车,你可以自行调整阈值,还能识别出更多实体。
五、PyTorch 实战2:图像分类
0、实战场景
基于 CNN(卷积神经网络)来做图像分类实战,采用的是 ResNet-18 模型。
一个典型的 CNN(卷积神经网络)通常包含如下部分:
-
输入层
-
卷积层 + 池化
-
全连接层
-
Softmax 激活,分类输出
RestNet-18模型图如下:
1、数据准备
使用 CIFAR10 数据集,可以通过代码自动从 PyTorch 官方下载。
该数据集中包含 10 种常见物体,常用于图像分类问题的教学。
2、代码实战
# 1. 导入所需要的库
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
# 2. 下载CIFAR-10数据集
# 设置图像预处理: 图像增强 + 转换为张量 + 标准化
transform = transforms.Compose(
[transforms.RandomHorizontalFlip(),
transforms.RandomCrop(32, padding=4),
transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
# 下载训练集和测试集
trainset = torchvision.datasets.CIFAR10(root='CIFAR10', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=64,
shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='CIFAR10', train=False,
download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=64,
shuffle=False, num_workers=2)
# 3. 使用ResNet-18作为预训练网络
# 下载预训练的ResNet-18模型
resnet18 = torchvision.models.resnet18(pretrained=True)
# 由于CIFAR-10有10个类,我们需要调整ResNet的最后一个全连接层
num_classes = 10
resnet18.fc = nn.Linear(resnet18.fc.in_features, num_classes)
if __name__ == '__main__':
# 4. 微调预训练的CNN网络
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(resnet18.parameters(), lr=0.001, momentum=0.9)
# 迁移到 GPU上(优先使用GPU)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print("Device:", device)
resnet18.to(device)
# 训练网络
for epoch in range(10): # 就演示训练10个epochs
running_loss = 0.0
for i, data in enumerate(trainloader, 0):
# 获取输入数据
inputs, labels = data[0].to(device), data[1].to(device)
# 清零参数梯度
optimizer.zero_grad()
# 前向 + 反向 + 优化
outputs = resnet18(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 200 == 199: # 每200批次打印一次
print('[%d, %5d] loss: %.3f' %
(epoch + 1, i + 1, running_loss / 200))
running_loss = 0.0
print('Training Finished')
# 5. 测试网络性能
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data[0].to(device), data[1].to(device)
outputs = resnet18(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Accuracy of the network on the 10000 test images: %d %%' % (
100 * correct / total))
3、推理效果
将代码保存为CNN_ResNet_CIFAR10.py
,运行效果如下:
C:\Users\Lenovo\anaconda3\envs\pytorch211\python.exe CNN_ResNet_CIFAR10.py
Device: cuda:0
[1, 200] loss: 1.607
[1, 400] loss: 1.153
[1, 600] loss: 1.050
[2, 200] loss: 0.863
[2, 400] loss: 0.847
[2, 600] loss: 0.829
[3, 200] loss: 0.742
[3, 400] loss: 0.730
[3, 600] loss: 0.725
[4, 200] loss: 0.660
[4, 400] loss: 0.646
[4, 600] loss: 0.649
[5, 200] loss: 0.601
[5, 400] loss: 0.597
[5, 600] loss: 0.593
[6, 200] loss: 0.560
[6, 400] loss: 0.553
[6, 600] loss: 0.568
[7, 200] loss: 0.528
[7, 400] loss: 0.524
[7, 600] loss: 0.538
[8, 200] loss: 0.494
[8, 400] loss: 0.497
[8, 600] loss: 0.497
[9, 200] loss: 0.466
[9, 400] loss: 0.483
[9, 600] loss: 0.480
[10, 200] loss: 0.451
[10, 400] loss: 0.444
[10, 600] loss: 0.437
Training Finished
Accuracy of the network on the 10000 test images: 79 %
在1万个测试图像集上识别的准确率是 79%,还是不错的。你还可以更改其它模型,看看准确率。
六、PyTorch 实战3:时序预测
0、实战场景
基于 RNN(循环神经网络)来做时序预测任务实战,假设我们有某App过去两年每天的用户注册人数,如何根据历史数据,预测后续一段时间的用户注册数。
RNN(循环神经网络)特性:
-
记忆功能
-
每个序列循环处理
-
捕捉序列模式和依赖关系
-
适于文本和时序
1、数据准备
暂时无法在飞书文档外展示此内容
以上就是App的注册数据,其中一大部分数据作为训练集,一小部分数据作为测试集:
2、代码实战
import numpy as np
import pandas as pd
import torch
import torch.nn as nn
import torch.optim as optim
from torch.autograd import Variable
# 1、导入数据
df_app = pd.read_csv('AppRNN.csv', index_col='Date', parse_dates=['Date']) #导入数据
# 按照2020年10月1日为界拆分数据集
Train = df_app[:'2020-09-30'].iloc[:,0:1].values #训练集
Test = df_app['2020-10-01':].iloc[:,0:1].values #测试集
from sklearn.preprocessing import MinMaxScaler #导入归一化缩放器
Scaler = MinMaxScaler(feature_range=(0,1)) #创建缩放器
Train = Scaler.fit_transform(Train) #拟合缩放器并对训练集进行归一化
# 对测试数据进行归一化处理
Test = Scaler.transform(Test)
# 创建一个函数,将数据集转化为时间序列格式
def sliding_windows(data, seq_length):
x = []
y = []
for i in range(len(data)-seq_length):
_x = data[i:(i+seq_length)]
_y = data[i+seq_length]
x.append(_x)
y.append(_y)
return np.array(x),np.array(y)
# 设定窗口大小
seq_length = 4
x_train, y_train = sliding_windows(Train, seq_length)
# 使用滑动窗口为测试数据创建特征和标签
x_test, y_test = sliding_windows(Test, seq_length)
# 将数据转化为torch张量
trainX = Variable(torch.Tensor(np.array(x_train)))
trainY = Variable(torch.Tensor(np.array(y_train)))
# 将数据转化为torch张量
testX = Variable(torch.Tensor(np.array(x_test)))
testY = Variable(torch.Tensor(np.array(y_test)))
# 2、模型构建
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(RNN, self).__init__()
self.hidden_size = hidden_size
# RNN层
self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)
# 全连接层,用于输出
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x):
# 初始化隐状态
h0 = Variable(torch.zeros(num_layers, x.size(0), self.hidden_size))
# 前向传播RNN
out, _ = self.rnn(x, h0)
# 解码RNN的最后一个隐藏层的输出
out = self.fc(out[:, -1, :])
return out
# 设置模型参数
input_size = 1
hidden_size = 64
num_layers = 1
output_size = 1
# 3、模型训练
# 创建模型
rnn = RNN(input_size, hidden_size, num_layers, output_size)
# 定义损失函数和优化器
criterion = torch.nn.MSELoss() # 均方误差
optimizer = torch.optim.Adam(rnn.parameters(), lr=0.01) # Adam优化器
# 训练模型
num_epochs = 100
for epoch in range(num_epochs):
outputs = rnn(trainX)
optimizer.zero_grad()
# 计算损失
loss = criterion(outputs, trainY)
loss.backward()
optimizer.step()
if epoch % 10 == 0:
print("Epoch: %d, loss: %1.5f" % (epoch, loss.item()))
# 4、使用训练好的模型在测试集上进行预测
rnn.eval() # 设置模型为评估模式
test_outputs = rnn(testX)
# 将预测结果逆归一化
test_outputs = test_outputs.data.numpy()
test_outputs = Scaler.inverse_transform(test_outputs) # 逆归一化
# 真实测试标签逆归一化
y_test_actual = Scaler.inverse_transform(y_test)
# 输出预测和真实结果
for i in range(len(y_test)):
print(f"Date: {df_app['2020-10-01':].index[i+seq_length]}, Actual Activation: {y_test_actual[i][0]}, Predicted Activation: {test_outputs[i][0]}")
# 5、绘制预测图
# 定义绘图函数
def plot_predictions(test,predicted):
plt.plot(test, color='red',label='Real Count') #真值
plt.plot(predicted, color='blue',label='Predicted Count') #预测值
plt.title('Flower App Activation Prediction') #图题
plt.xlabel('Time') #X轴时间
plt.ylabel('Flower App Activation Count') #Y轴激活数
plt.legend() #图例
plt.show() #绘图
plot_predictions(y_test_actual,test_outputs) #绘图
3、推理效果
C:\Users\Lenovo\anaconda3\envs\pytorch211\python.exe RNN_TimeSeries.py
Epoch: 0, loss: 0.29158
Epoch: 10, loss: 0.04519
Epoch: 20, loss: 0.00904
Epoch: 30, loss: 0.00238
Epoch: 40, loss: 0.00139
Epoch: 50, loss: 0.00118
Epoch: 60, loss: 0.00059
Epoch: 70, loss: 0.00054
Epoch: 80, loss: 0.00052
Epoch: 90, loss: 0.00049
Date: 2020-10-05 00:00:00, Actual Activation: 923.0, Predicted Activation: 887.109130859375
Date: 2020-10-06 00:00:00, Actual Activation: 919.0000000000001, Predicted Activation: 893.6192626953125
Date: 2020-10-07 00:00:00, Actual Activation: 915.0, Predicted Activation: 899.8789672851562
...
用图表展示如下:
红色是真实数据,蓝色是预测后的数据,看起来趋势还是对的。
我们还可以进一步评估模型:
1、评估 MES 损失值:
import math #导入数学函数
from sklearn.metrics import mean_squared_error
def return_rmse(test,predicted): #定义均方损失函数
rmse = math.sqrt(mean_squared_error(test, predicted)) #均方损失
print("MSE损失值:{}".format(rmse))
return_rmse(y_test_actual, test_outputs)
# 输出:MSE损失值:23.273510243141594
2、评估 R2 值:
from sklearn.metrics import r2_score
r2 = r2_score(y_test_actual, test_outputs)
print(f"R2 Score: {r2}")
# 输出:R2 Score: 0.714642047663375
七、总结
总的来说,PyTorch 确实功能强大,也很灵活。当下用 PyTorch 的人也越来越多,特别是科研领域。想进一步深入学习,建议多看看一些优秀的教程,包括书籍和视频。
参考内容:黄佳老师的《AI应用实战课》
标签:实战,loss,torch,PyTorch,应用,test,import,size From: https://www.cnblogs.com/bingohuang/p/18543150