课程资源:
【小学生都会的Pytorch】九、运用你的模型做预测(1)_哔哩哔哩_bilibili
笔记:
pytorch进阶学习(四):使用不同分类模型进行数据训练(alexnet、resnet、vgg等)_好喜欢吃红柚子的博客-CSDN博客
目录
一、原理介绍
1. 加载模型与参数
2. 读取图片
3. 图片预处理
4. 把图片转换为tensor
5. 增加batch_size的维度
6. 模型验证
6.1 模型的初步输出
6.2 输出预测值概率最大的值和位置
6.3 把tensor转为numpy
6.4 预测类别
二、代码
1. 对单张图片做预测
2. 对整个文件夹图片做预测
模型在经过前面几节的训练之后,传入自己的数据进行预测,流程和训练时差不多。项目目录如下所示,pic为预测时取的照片。
一、原理介绍
1. 加载模型与参数
模型骨架使用resnet18进行训练,使用预训练好的权重文件“model_resnet18_100.pth”来进行参数的加载。
# 如果显卡可用,则用显卡进行训练
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")
'''
加载模型与参数
'''
# 加载模型
model = resnet18(pretrained=False, num_classes=5).to(device) # 43.6%
# 加载模型参数
if device == "cpu":
# 加载模型参数,权重文件传过来
model.load_state_dict(torch.load("model_resnet18_100.pth", map_location=torch.device('cpu')))
else:
model.load_state_dict(torch.load("model_resnet18_100.pth"))
2. 读取图片
我们要预测的是sunflower1这张图片。
img_path = './pic/sunflower1.jpg'
3. 图片预处理
Image.open打开图像,转换为RGB格式,padding_black进行图像的扩充
img = Image.open(img_path)#打开图片
img = img.convert('RGB')#转换为RGB 格式
# 扩充
img = padding_black(img)
4. 把图片转换为tensor
val_tf = transforms.Compose([
transforms.Resize(224),
transforms.ToTensor(),
transform_BZ # 标准化操作
])
# 图片转换为tensor
img_tensor = val_tf(img)
5. 增加batch_size的维度
如果直接把图片传入模型会发生以下报错:
原因:
模型接收的是四维输入,但是我们图片的输入只有3维,要求的4维输入的第一维为batch_size,我们训练好的模型中batch_size=64,但是一张图片没有这个维度,所以需要给这张传入的图片再增加一个通道。
- dim=0代表在第一个维度增加维度
# 增加batch_size维度
img_tensor = Variable(torch.unsqueeze(img_tensor, dim=0).float(), requires_grad=False).to(device)
6. 模型验证
6.1 模型的初步输出
模型进行输出后可以看到如下结果,tensor中有5个数。
model.eval()
# 不进行梯度更新
with torch.no_grad():
output_tensor = model(img_tensor)
print(output_tensor)
但是都不在0-1之间,不是我们需要的对每一个类的概率值,所以我们需要使用softmax进行归一化。使用softmax进行归一化。
# 将输出通过softmax变为概率值
output = torch.softmax(output_tensor,dim=1)
print(output)
可以看到进行softmax运算后,出现的结果使用的是科学计数法,5个数加起来为1.
6.2 输出预测值概率最大的值和位置
# 输出可能性最大的那位
pred_value, pred_index = torch.max(output, 1)
print(pred_value)
print(pred_index)
输出可以看到输出概率为1,即100%,位置下标为3,即第四类,sunflower类。
6.3 把tensor转为numpy
在上一步输出时的数据为tensor格式,所以我们需要把数字先转换为numpy,再进行后续标签下标到标签类的转换。
# 将数据从cuda转回cpu
pred_value = pred_value.detach().cpu().numpy()
pred_index = pred_index.detach().cpu().numpy()
print(pred_value)
print(pred_index)
打印结果可以看到已经成功转换到了numpy类,没有了tensor标志
6.4 预测类别
写出类别的中文列表,一定要与test训练集标签中的顺序对应起来。
classes = ["daisy", "dandelion", "rose", "sunflower", "tulip"]
print("预测类别为: ",classes[pred_index[0]]," 可能性为: ",pred_value[0]*100,"%")
打印输出可以看到预测正确,准确率高 。
二、代码
1. 对单张图片做预测
'''
功能:按着路径,导入单张图片做预测
作者: Leo在这
'''
from torchvision.models import resnet18
import torch
from PIL import Image
import torchvision.transforms as transforms
from torch.autograd import Variable
# 如果显卡可用,则用显卡进行训练
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")
'''
加载模型与参数
'''
# 加载模型
model = resnet18(weights=False, num_classes=5).to(device) # 43.6%
# 加载模型参数
if device == "cpu":
# 加载模型参数,权重文件传过来
model.load_state_dict(torch.load("model_resnet18_100.pth", map_location=torch.device('cpu')))
else:
model.load_state_dict(torch.load("model_resnet18_100.pth"))
'''
加载图片与格式转化
'''
img_path = './pic/sunflower1.jpg'
'''
图片进行预处理
'''
# 图片标准化
transform_BZ= transforms.Normalize(
mean=[0.5, 0.5, 0.5],# 取决于数据集
std=[0.5, 0.5, 0.5]
)
val_tf = transforms.Compose([
transforms.Resize(224),
transforms.ToTensor(),
transform_BZ # 标准化操作
])
def padding_black(img): # 如果尺寸太小可以扩充
w, h = img.size
scale = 224. / max(w, h)
img_fg = img.resize([int(x) for x in [w * scale, h * scale]])
size_fg = img_fg.size
size_bg = 224
img_bg = Image.new("RGB", (size_bg, size_bg))
img_bg.paste(img_fg, ((size_bg - size_fg[0]) // 2,
(size_bg - size_fg[1]) // 2))
img = img_bg
return img
# 打开图片,转换为RGB
img = Image.open(img_path)#打开图片
img = img.convert('RGB')#转换为RGB 格式
# 扩充
img = padding_black(img)
# print(type(img))
# 图片转换为tensor
img_tensor = val_tf(img)
# print(type(img_tensor))
# 增加batch_size维度
img_tensor = Variable(torch.unsqueeze(img_tensor, dim=0).float(), requires_grad=False).to(device)
'''
数据输入与模型输出转换
'''
model.eval()
# 不进行梯度更新
with torch.no_grad():
output_tensor = model(img_tensor)
print(output_tensor)
#
# 将输出通过softmax变为概率值
output = torch.softmax(output_tensor,dim=1)
print(output)
# 输出可能性最大的那位
pred_value, pred_index = torch.max(output, 1)
print(pred_value)
print(pred_index)
# 将数据从cuda转回cpu
pred_value = pred_value.detach().cpu().numpy()
pred_index = pred_index.detach().cpu().numpy()
print(pred_value)
print(pred_index)
# #
# 增加类别标签
classes = ["daisy", "dandelion", "rose", "sunflower", "tulip"]
print("预测类别为: ",classes[pred_index[0]]," 可能性为: ",pred_value[0]*100,"%")
2. 对整个文件夹图片做预测
对根目录为pic的文件夹做图片预测,步骤和单张图片预测差不多,使用for循环遍历文件。
'''
功能:导入文件夹做预测
作者:Leo在这
'''
from torchvision.models import resnet18
import torch
from PIL import Image
import torchvision.transforms as transforms
from torch.autograd import Variable
import os
# 如果显卡可用,则用显卡进行训练
device = "cuda" if torch.cuda.is_available() else "cpu"
print(f"Using {device} device")
'''
加载模型与参数
'''
# 加载模型
model = resnet18(pretrained=False, num_classes=5).to(device) # 43.6%
if device == "cpu":
# 加载模型参数
model.load_state_dict(torch.load("model_resnet18_100.pth", map_location=torch.device('cpu')))
else:
model.load_state_dict(torch.load("model_resnet18_100.pth"))
'''
加载图片与格式转化
'''
# 图片标准化
transform_BZ= transforms.Normalize(
mean=[0.5, 0.5, 0.5],# 取决于数据集
std=[0.5, 0.5, 0.5]
)
val_tf = transforms.Compose([##简单把图片压缩了变成Tensor模式
transforms.Resize(224),
transforms.ToTensor(),
transform_BZ#标准化操作
])
def padding_black(img): # 如果尺寸太小可以扩充
w, h = img.size
scale = 224. / max(w, h)
img_fg = img.resize([int(x) for x in [w * scale, h * scale]])
size_fg = img_fg.size
size_bg = 224
img_bg = Image.new("RGB", (size_bg, size_bg))
img_bg.paste(img_fg, ((size_bg - size_fg[0]) // 2,
(size_bg - size_fg[1]) // 2))
img = img_bg
return img
dir_loc = r"./pic"
model.eval()
with torch.no_grad():
for a,b,c in os.walk(dir_loc):
for filei in c:
full_path = os.path.join(a,filei)
# print(full_path)
# img_path = './pic/sunflower3.jpg'
img = Image.open(full_path)#打开图片
img = img.convert('RGB')#转换为RGB 格式
img = padding_black(img)
# print(type(img))
img_tensor = val_tf(img)
# print(type(img_tensor))
# 增加batch_size维度
img_tensor = Variable(torch.unsqueeze(img_tensor, dim=0).float(), requires_grad=False).to(device)
'''
数据输入与模型输出转换
'''
output_tensor = model(img_tensor)
# 将输出通过softmax变为概率值
output = torch.softmax(output_tensor,dim=1)
# 输出可能性最大的那位
pred_value, pred_index = torch.max(output, 1)
pred_value = pred_value.detach().cpu().numpy()
pred_index = pred_index.detach().cpu().numpy()
# 增加类别标签
classes = ["daisy", "dandelion", "rose", "sunflower", "tulip"]
print("预测类别为: ",classes[pred_index[0]]," 可能性为: ",pred_value[0]*100,"%")
结果如下所示: