1.课程学习
本节课主要对于大白AI课程:https://mp.weixin.qq.com/s/STbdSoI7xLeHrNyLlw9GOg
《Pytorch推理及范式》课程中的第二节课进行学习。
2.作业题目
必做题:
(1) 把模型改为resnet18,加载相应的模型权重(Lesson2的物料包中有),跑一下0.jpg和1.jpg,看一下输出结果。
结果:
(2) 自己找2张其他图,用resnet18做下推理。
图片:
结果:
思考题:
(1) 以ResNet18为例,用time模块和for循环,对”./images/0.jpg”连续推理100次,统计时间开销。
CPU:
GPU:
(2) 在数据预处理和数据后处理的代码实现中,到处在用 numpy, opencv, torch 对数组做
相应变换,大家至少要把课程中出现的函数们给理解。
3.课程总结:
通过本节课的学习,熟悉了torch推理的三板斧,在以后的推理任务中,基本上都能套用这个流程,非常期待后续的课程,也希望大白老师有更多系列的课程。对于思考题中的问题(1),gpu推理速度比cpu慢的原因应该是gpu数据传输比cpu慢,gpu擅长的是矩阵运算,把推理次数增加到1000次就能看到两者推理速度的明显区别:
CPU:
GPU:
4.完整代码
import torch
import cv2
import numpy as np
import torchvision.models as models
import time
class ModelPipline(object):
def __init__(self):
# 进去模型的图片大小:为数据预处理和后处理做准备
self.inputs_size = (224, 224)
# CPU or CUDA:为数据预处理和模型加载做准备
self.device = torch.device('cpu')
# 载入模型结构和模型权重
self.model = self.get_model()
# 载入标签,数据后处理做准备
label_names = open('./lesson3/labels/imagenet_label.txt', 'r').readlines()
self.label_names = [line.strip('\n') for line in label_names]
def predict(self, image):
# 数据预处理
inputs = self.preprocess(image)
# 数据进网络
outputs = self.model(inputs)
# 数据后处理
results=self.postprocess(outputs)
return results
def get_model(self):
model = models.resnet18(num_classes=1000)
pretrained_state_dict = torch.load('./lesson2/weights/resnet18-5c106cde.pth', map_location=lambda storage, loc: storage)
model.load_state_dict(pretrained_state_dict, strict=True)
model.to(self.device)
model.eval()
return model
def preprocess(self, image):
# opencv默认读取的是BGR,需要转换为RGB,和训练时保持一致
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# resize成模型输入的大小,和训练时保持一致
image = cv2.resize(image, dsize=self.inputs_size)
# 归一化和标准化,和训练时保持一致
inputs = image / 255
inputs = (inputs - np.array([0.485, 0.456, 0.406])) / np.array([0.229, 0.224, 0.225])
## 以下是图像任务的通用处理
#(H, W, C) ——> (C, H, W)
inputs = inputs.transpose(2, 0, 1)
# (C, H, W) ——> (1, C, H, W)
inputs = inputs[np.newaxis, :, :, :]
#NumpyArray ——> Tensor
inputs = torch.from_numpy(inputs)
#dtype float32
inputs = inputs.type(torch.float32)
# 与self.model放在相同硬件上
inputs = inputs.to(self.device)
return inputs
def postprocess(self, outputs):
# 取softmax得到每个类别的置信度
outputs = torch.softmax(outputs, dim=1)
# 取最高置信度类别和分数
score, label_id = torch.max(outputs, dim=1)
# Tensor ——> float
score, label_id = score.item(), label_id.item()
# 查找标签名称
label_name = self.label_names[label_id]
return label_name, score
if __name__ == '__main__':
# 实例化整个推理类,主要开销在__init__中的载入模型部分
model_classify = ModelPipline()
# 读取第一张图
image = cv2.imread('./lesson3/images/0.jpg')
# 做推理
result = model_classify.predict(image)
print(result)
start = time.time()
for i in range(1000):
result = model_classify.predict(image)
end = time.time()
print("图片运行1000次耗时:", end - start)
print("推理一次平均耗时:", (end - start) / 1000)