提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- pytorch模型融合
- 一、思路
- 二、使用步骤
- 总结
pytorch模型融合
做论文基本上用不到,但是,打比赛的人肯定常用,那就是模型融合。采用不同方式训练的模型一般表现不同,为了综合各个模型之间的差异,拿到最好的结果,我们一般会对模型的输出结果进行融合,而其融合结果在性能表现上都会有不同的提升。下面直接上代码。
一、思路
其实思路很简单,就是把网络输出结果取均值,当然,也可以分别赋予不同的权重。假设你有三个 模型,分别为A,B,C,取均值就是各占三分之一,那么,你想2:2:6也行,自己设参数就好,我记得还有其他的模型融合方式。比如,投票表决,这个我没去写,思路很简单,其实,就是分别得到每个模型的当前预测样本的类别,然后,少数服从多数。下面我展示一下我之前做验证码识别的比赛的模型融合代码。
这个验证码识别是多标签多分类问题,就是每张图4个字母,我们要做到的是预测出每个字母的类别,(区分大小写),意味着62*4=248个类别。就是248多分类问题。
二、使用步骤
代码如下(示例):
import os
import cv2 as cv
import torch
from PIL import Image
import torch.nn as nn
import numpy as np
from torchvision import transforms
import csv
from tqdm import tqdm
from captcha_dataset import CaptchaDataTest, img_loader
# 这就是62类别
source = [str(i) for i in range(0, 10)]
source += [chr(i) for i in range(97, 97 + 26)]
source += [chr(i) for i in range(65, 65 + 26)]
alphabet = ''.join(source)
def predict():
这里是你自己的模型的路径,分别需要的输入图像的尺寸大小
model_paths = {
(160, 400): [
'../b7/best_model.pth',
],
(200, 440): [
'../b6/best_model.pth',
],
(220, 460): [
'../b5/best_model.pth',
],
}
test_dir = '测试集路径'
test_mean = [0.485, 0.456, 0.406]
test_std = [0.229, 0.224, 0.225]
print(torch.cuda.is_available())
model_dict = {}
for image_size, model_paths in model_paths.items():
models = []
for model_path in model_paths:
# 分别加载模型
model = torch.load(model_path)
if torch.cuda.is_available():
model = model.cuda()
model.eval()
models.append(model)
model_dict[image_size] = models
dataset = sorted(os.listdir(test_dir), key=lambda x: int(x[:-4]))
res = []
for i, name in enumerate(tqdm(dataset)):
path = os.path.join(test_dir, name)
img = img_loader(path)
scores = []
for image_size, models in model_dict.items():
transform = transforms.Compose([
transforms.Resize(image_size),
transforms.ToTensor(),
transforms.Normalize(
mean=test_mean,
std=test_std
)
])
image = transform(img)[None, ...]
image = image.cuda()
with torch.no_grad():
for model in models:
# 这里就是关键了,就是把当前的数据分别给模型。
outputs = model(image)
outputs = outputs.view(-1, 4, 62) # 1, 4, 62
outputs = nn.functional.softmax(outputs, dim=-1).cpu().numpy()
# 先用一个scores存起来,每张图对应3个outputs,下一张图的时候,又重新创建一个scores
scores.append(outputs)
# print(np.array(scores).max(axis=-1))
# 最重要的一步,就是,把这个scores,按照行做均值处理。
scores = np.mean(scores, axis=0)
scores = np.argmax(scores, axis=-1)
img_name = name[:-4]
pred = ''.join([alphabet[i] for i in scores[0]])
# print(img_name, pred)
res.append({'num': int(img_name), 'tag': pred})
header = ['num', 'tag']
os.makedirs('sub', exist_ok=True)
with open('../merge.csv', 'w', encoding='utf_8_sig') as f:
f_csv = csv.DictWriter(f, header)
f_csv.writeheader()
f_csv.writerows(res)
if __name__ == '__main__':
predict()
总结
这里如果采用权重融合的方式的话,就应该是分别设置不同的权重,在把它们和原始输出相乘,挨个加起来。在进行argmax操作。