二预训练模型预测(Datawhale组队学习)

Posted 卡拉比丘流形

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二预训练模型预测(Datawhale组队学习)相关的知识,希望对你有一定的参考价值。

文章目录


本篇文章主要讲述了如何用预训练好的图像分类模型完成单张图片的预测、视频文件的预测和实时摄像头画面预测。接下来让我们开始我们图像世界的探索之旅吧!

安装配置环境

以下部分为Linux版本特有的命令,Windows可以直接复制链接进行下载。

# !pip install numpy pandas matplotlib requests tqdm opencv-python pillow gc -i https://pypi.tuna.tsinghua.edu.cn/simple
!pip install numpy pandas matplotlib requests tqdm opencv-python pillow

# 下载安装Pytorch
!pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113

# 安装mmcv -full
!pip install mmcv-full -f https://download.openmmlab.com/mmcv/dist/cu113/torch1.10.0/index.html

# 安装文字字体
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/dataset/SimHei.ttf

下载 ImageNet 1000类别信息

!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/dataset/meta_data/imagenet_class_index.csv

创建目录

import os
# 存放测试图片
os.mkdir('test_img')

# 存放结果文件
os.mkdir('output')

下载测试文件
Linux下可以运行一下代码下载文件

# 下载测试图像文件 至 test_img 文件夹

!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/watermelon1.jpg -O test_img/watermelon1.jpg
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/banana1.jpg -O test_img/banana1.jpg
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/cat1.jpg -O test_img/cat1.jpg

# 哈士奇,来源:https://www.pexels.com/zh-cn/photo/2853130/
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/husky1.jpeg -O test_img/husky1.jpeg

# 猫狗,来源:https://unsplash.com/photos/ouo1hbizWwo
!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/cat_dog.jpg -O test_img/cat_dog.jpg

!wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/video_2.mp4 -O test_img/video_2.mp4

Windows下复制一下链接下载即可

# 下载测试图像文件 至 test_img 文件夹

https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/watermelon1.jpg
https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/banana1.jpg
https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/cat1.jpg
# 哈士奇,来源:https://www.pexels.com/zh-cn/photo/2853130/
https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/husky1.jpeg

# 猫狗,来源:https://unsplash.com/photos/ouo1hbizWwo
https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/cat_dog.jpg

https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/test/video_2.mp4

ImageNet预训练图像分类模型预测单张图像-英文

import os
import cv2
import pandas as pd
import numpy as np
import torch
import matplotlib.pyplot as plt
%matplotlib inline

# 有 GPU 就用 GPU,没有就用 CPU
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

载入预训练图像分类模型

我们这里使用pytorch自带的已经预训练好的resnet18模型

from torchvision import models
# 载入预训练图像分类模型
model = models.resnet18(pretrained=True) 
# model = models.resnet152(pretrained=True)
model = model.eval()
model = model.to(device)

图像预处理

from torchvision import transforms

# 测试集图像预处理-RCTN:缩放裁剪、转 Tensor、归一化
from torchvision import transforms

# 测试集图像预处理-RCTN:缩放裁剪、转 Tensor、归一化
test_transform = transforms.Compose([transforms.Resize(256),#缩放成256×256
                                     transforms.CenterCrop(224),#截出一个224×224
                                     transforms.ToTensor(),
                                     transforms.Normalize(
                                         mean=[0.485, 0.456, 0.406], 
                                         std=[0.229, 0.224, 0.225])#进行归一化,数值根据经验得到的
                                    ])

载入一张测试图像

img_path = 'test_img/cat_dog.jpg'
# 用 pillow 载入
from PIL import Image
img_pil = Image.open(img_path)
img_pil
np.array(img_pil).shape

(1560, 2340, 3)

这张图片是1560×2340像素的三通道图片

执行图像分类预测

input_img = test_transform(img_pil) # 预处理
input_img.shape

torch.Size([3, 224, 224])

input_img = input_img.unsqueeze(0).to(device)
input_img.shape

得到一张三通道224×224的图片,只有这个形式的照片可以传入模型进行训练

torch.Size([1, 3, 224, 224])

得到所有类别的 logit 预测分数

# 执行前向预测,得到所有类别的 logit 预测分数
pred_logits = model(input_img) 

将这1000个类别的预测分数通过softmax操作进行归一化,得到预测为每个类别的概率

import torch.nn.functional as F
pred_softmax = F.softmax(pred_logits, dim=1) # 对 logit 分数做 softmax 运算
pred_softmax.shape

预测结果分析

各类别置信度柱状图

plt.figure(figsize=(8,4))

x = range(1000)
y = pred_softmax.cpu().detach().numpy()[0]

ax = plt.bar(x, y, alpha=0.5, width=0.3, color='yellow', edgecolor='red', lw=3)
plt.ylim([0, 1.0]) # y轴取值范围
# plt.bar_label(ax, fmt='%.2f', fontsize=15) # 置信度数值

plt.xlabel('Class', fontsize=20)
plt.ylabel('Confidence', fontsize=20)
plt.tick_params(labelsize=16) # 坐标文字大小
plt.title(img_path, fontsize=25)

plt.show()

取置信度最大的 n 个结果

n = 10
top_n = torch.topk(pred_softmax, n)
top_n

torch.return_types.topk( values=tensor([[0.3733, 0.2683, 0.0451,
0.0413, 0.0227, 0.0198, 0.0183, 0.0171, 0.0152,
0.0118]], grad_fn=), indices=tensor([[282, 281, 285, 231, 249, 287, 283, 852, 291, 232]]))

# 解析出类别
pred_ids = top_n[1].cpu().detach().numpy().squeeze()
pred_ids

array([282, 281, 285, 231, 249, 287, 283, 852, 291, 232], dtype=int64)

# 解析出置信度
confs = top_n[0].cpu().detach().numpy().squeeze()
confs

array([0.3732724 , 0.2683452 , 0.0450662 , 0.04129088, 0.02274127,
0.0197675 , 0.01831976, 0.01714958, 0.01518197, 0.0118369 ],
dtype=float32)

载入ImageNet 1000图像分类标签
ImageNet 1000类别中文释义:https://github.com/ningbonb/imagenet_classes_chinese

df = pd.read_csv('imagenet_class_index.csv')
df


将表格信息转换为键值对的形式

idx_to_labels = 
for idx, row in df.iterrows():
    idx_to_labels[row['ID']] = [row['wordnet'], row['class']]#形成ID:[wordnet,class]的键值对
idx_to_labels


图像分类结果写在原图上

# 用 opencv 载入原图
img_bgr = cv2.imread(img_path)
for i in range(n):
    class_name = idx_to_labels[pred_ids[i]][1] # 获取类别名称
    confidence = confs[i] * 100 # 获取置信度
    text = ':<15 :>.4f'.format(class_name, confidence)
    print(text)
    
    # !图片,添加的文字,左上角坐标,字体,字号,bgr颜色,线宽
    img_bgr = cv2.putText(img_bgr, text, (25, 50 + 40 * i), cv2.FONT_HERSHEY_SIMPLEX, 1.25, (0, 0, 255), 3)

# 保存图像
cv2.imwrite('output/img_pred.jpg', img_bgr)

# 载入预测结果图像
img_pred = Image.open('output/img_pred.jpg')
img_pred


图像和柱状图一起显示

fig = plt.figure(figsize=(18,8))

# 绘制左图-预测图
ax1 = plt.subplot(1,2,1)
ax1.imshow(img_pred)
ax1.axis('off')#关闭所有坐标轴线、刻度标记和标签

# 绘制右图-柱状图
ax2 = plt.subplot(1,2,2)
x = df['ID']
y = pred_softmax.cpu().detach().numpy()[0]
ax2.bar(x, y, alpha=0.5, width=0.3, color='yellow', edgecolor='red', lw=3)

plt.ylim([0, 1.0]) # y轴取值范围
plt.title(' Classification'.format(img_path), fontsize=30)
plt.xlabel('Class', fontsize=20)
plt.ylabel('Confidence', fontsize=20)
ax2.tick_params(labelsize=16) # 坐标文字大小

plt.tight_layout()
fig.savefig('output/预测图+柱状图.jpg')


预测结果表格输出

pred_df = pd.DataFrame() # 预测结果表格
for i in range(n):
    class_name = idx_to_labels[pred_ids[i]][1] # 获取类别名称
    label_idx = int(pred_ids[i]) # 获取类别号
    wordnet = idx_to_labels[pred_ids[i]][0] # 获取 WordNet
    confidence = confs[i] * 100 # 获取置信度
    pred_df = pred_df.append('Class':class_name, 'Class_ID':label_idx, 'Confidence(%)':confidence, 'WordNet':wordnet, ignore_index=True) # 预测结果表格添加一行
display(pred_df) # 展示预测结果表格

ImageNet预训练图像分类模型预测单张图像-中文

## 设置matplotlib中文字体
# windows操作系统
import matplotlib as plt
plt.rcParams['font.sans-serif']=['SimHei']  # 用来正常显示中文标签 
plt.rcParams['axes.unicode_minus']=False  # 用来正常显示负号
# Mac操作系统,参考 https://www.ngui.cc/51cto/show-727683.html
# 下载 simhei.ttf 字体文件
# !wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/dataset/SimHei.ttf
# # Linux操作系统,例如 云GPU平台:https://featurize.cn/?s=d7ce99f842414bfcaea5662a97581bd1
# # 如果遇到 SSL 相关报错,重新运行本代码块即可
# !wget https://zihao-openmmlab.obs.cn-east-3.myhuaweicloud.com/20220716-mmclassification/dataset/SimHei.ttf -O /environment/miniconda3/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/SimHei.ttf
# !rm -rf /home/featurize/.cache/matplotlib
# import matplotlib
# matplotlib.rc("font",family='SimHei') # 中文字体

## 导入pillow中文字体
from PIL import ImageFont, ImageDraw
# 导入中文字体,指定字号
font = ImageFont.truetype('SimHei.ttf', 32)

## 导入工具包
import os
import cv2
from PIL import Image, ImageFont, ImageDraw

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

import torch
from torchvision import models
import torch.nn.functional as F
from torchvision import transforms

# 有 GPU 就用 GPU,没有就用 CPU
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
print('device', device)

预训练图像分类模型

# 载入预训练图像分类模型
model = models.resnet18(pretrained=True) 
# model = models.resnet152(pretrained=True)
model = model.eval()
model = model.to(device)

载入ImageNet 1000图像分类中文标签

df = pd.read_csv('imagenet_class_index.csv')
idx_to_labels = 
for idx, row in df.iterrows():
    idx_to_labels[row['ID']] = [row['wordnet'], row['Chinese']]

图像预处理

# 测试集图像预处理-RCTN:缩放裁剪、转 Tensor、归一化
test_transform = transforms.Compose([transforms.Resize(256),
                                     transforms.CenterCrop(224),
                                     transforms.ToTensor(),
                                     transforms.Normalize(
                                         mean=[0.485, 0.456, 0.406], 
                                         std=[0.229, 0.224, 0.225])
                                    ])

载入一张测试图像

# img_path = 'test_img/banana1.jpg'
# img_path = 'test_img/husky1.jpeg'
# img_path = 'test_img/watermelon1.jpg'
img_path = 'test_img/cat_dog.jpg'
img_pil = Image.open(img_path) # 用 pillow 载入
img_pil

执行图像分类预测

input_img = test_transform(img_pil).unsqueeze(0).to(device) # 预处理
pred_logits = model(input_img) # 执行前向预测,得到所有类别的 logit 预测分数
pred_softmax = F.softmax(pred_logits, dim=1) # 对 logit 分数做 softmax 运算

预测结果分析

各类别置信度柱状图

plt.figure(figsize=(8,4))
x = range(1000)
y = pred_softmax.cpu().detach().numpy()[0]

ax = plt.bar(x, y, alpha=0.5, width=0.3, color='yellow', edgecolor='red', lw=3)
plt.ylim([0, 1.0]) # y轴取值范围
# plt.bar_label(ax, fmt='%.2f', fontsize=15) # 置信度数值

plt.title(img_path, fontsize=30)
plt.xlabel('类别', fontsize=20)
plt.ylabel('置信度', fontsize=20)
plt.tick_params(labelsize=16) # 坐标文字大小

plt.show()

取置信度最大的 n 个结果

n = 10
top_n = torch.topk(pred_softmax, n) # 取置信度最大的 n 个结果
pred_ids = top_n[1].cpu().detach().numpy().squeeze() # 解析出类别
confs = top_n[0].cpu().detach().numpy().squeeze() # 解析出置信度

图像分类结果写在原图上

draw = ImageDraw.Draw(img_pil)
for i in range(n):
    class_name = idx_to_labels[pred_ids[i]][1] # 获取类别名称
    confidence = confs[i] * 100 # 获取置信度
    text = ':<15 :>.4f'.format(class_name, confidence)
    print(text以上是关于二预训练模型预测(Datawhale组队学习)的主要内容,如果未能解决你的问题,请参考以下文章

吃瓜教程——datawhale10月组队学习

Datawhale九月组队学习--情感分析--Task04

吃瓜教程——datawhale10月组队学习

吃瓜教程——datawhale10月组队学习

吃瓜教程——datawhale10月组队学习

Datawhale九月组队学习--情感分析--Task01