pytorch深度学习和入门实战(七)模型集成训练

原理内容

为改善一项机器学习或深度学习的任务,首先想到的是从模型、数据、优化器等方面进行优化,使用方法比较方便。不过有时尽管如此,但效果还不是很理想,此时,我们可尝试一下其他方法,如模型集成、迁移学习、数据增强等优化方法。本文我们将介绍利用模型集成来提升任务的性能。

模型集成是提升分类器或预测系统效果的重要方法,目前在机器学习、深度学习国际比赛中时常能看到利用模型集成取得佳绩的事例。其在生产环境也是人们经常使用的方法。模型集成的原理比较简单,有点像多个盲人摸象,每个盲人只能摸到大象的一部分,但综合每人摸到的部分,就能形成一个比较完整、符合实际的图像。每个盲人就像单个模型,那如果集成这些模型犹如综合这些盲人各自摸到的部分,就能得到一个强于单个模型的模型。实际上模型集成也和我们通常说的集思广益、投票选举领导人等原理差不多,是1+1>2的有效方法。

当然,要是模型集成发挥效应,模型的多样性也是非常重要的,使用不同架构、甚至不同的学习方法是模型多样性的重要体现。如果只是改一下初始条件或调整几个参数,有时效果可能还不如单个模型。
具体使用时,除了要考虑各模型的差异性,还要考虑模型的性能。如果各模型性能差不多,可以取各模型预测结果的平均值;如果模型性能相差较大,模型集成后的性能可能还不及单个模型,相差较大时,可以采用加权平均的方法,其中权重可以采用SLSQP、Nelder-Mead、Powell、CG、BFGS等优化算法获取。
接下来,通过使用PyTorch来具体实现一个模型集成的实例,希望通过这个实例,使读者对模型集成有更进一步的理解。

代码

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import torch.backends.cudnn as cudnn
import numpy as np
import torchvision
from torchvision import datasets, models, transforms
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
from collections import Counter
from  torchsummary import summary

import  os
from tqdm import tqdm

#定义一些超参数
BATCHSIZE=15 # batchsize必须是testdata的整数倍
EPOCHES=10
LR=0.001

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# -------------------------------------------------------------------------------------------
#	模型定义
# -------------------------------------------------------------------------------------------
# mobilenet-v2模型
def mbnet():
	model = models.mobilenet_v2(pretrained=True)
	# 前面的参数保持不变
	for param in model.parameters():
		param.requires_grad = False

	fc = nn.Sequential(
		nn.Dropout(0.2),
		nn.Linear(1280, 3),
	)
	model.classifier = fc
	model = model.to(device)
	# print("[INFO] Model Layer:  ", summary(model, (3, 224, 224)))
	return model

# mnasnet模型
def mnasnet():
	model = models.MNASNet(alpha=1)
	# 前面的backbone保持不变
	for param in model.parameters():
		param.requires_grad = False

	fc = nn.Sequential(
		nn.Dropout(0.2),
		nn.Linear(1280, 3),
	)
	model.classifier = fc
	model = model.to(device)
	# print("[INFO] Model Layer:  ", summary(model, (3, 224, 224)))
	return model

#  resnet 18模型
def resnet18(fc_num=256, class_num=3):
	model = models.resnet18(pretrained=True)
	# 前面的backbone保持不变
	for param in model.parameters():
		param.requires_grad = True

	# 只是修改输出fc层,新加层是trainable
	fc_inputs = model.fc.in_features
	model.fc = nn.Sequential(
		nn.Linear(fc_inputs, fc_num),
		nn.ReLU(),
		nn.Dropout(0.4),
		nn.Linear(fc_num, class_num)
	)

	model = model.to(device)
	# print("[INFO] Model Layer:  ", summary(model, (3, 224, 224)))
	return model

#  resnet 152模型
def resnet152(fc_num=256, class_num=3, train_all =False):
	model = models.resnet152(pretrained=True)
	# 前面的backbone保持不变
	for param in model.parameters():
		param.requires_grad = False

	# 只是修改输出fc层,新加层是trainable
	fc_inputs = model.fc.in_features
	model.fc = nn.Sequential(
		nn.Linear(fc_inputs, fc_num),
		nn.ReLU(),
		nn.Dropout(0.4),
		nn.Linear(fc_num, class_num)
	)
	#  修改所有参数层
	if train_all:
		for param in model.parameters():
			param.requires_grad = True
		torch.load("./models/best_loss.pt")
	model = model.to(device)
	# print("[INFO] Model Layer:  ", summary(model, (3, 224, 224)))
	return model

# -------------------------------------------------------------------------------------------
#	数据加载
# -------------------------------------------------------------------------------------------
def data_process(batch_size=BATCHSIZE, dataset='./data'):
	image_transforms = {
		'train': transforms.Compose([
			transforms.RandomResizedCrop(size=256, scale=(0.8, 1.0)),
			transforms.RandomRotation(degrees=15),
			transforms.RandomHorizontalFlip(),
			transforms.CenterCrop(size=224),
			transforms.ToTensor(),
			transforms.Normalize([0.485, 0.456, 0.406],
								 [0.229, 0.224, 0.225])
		]),
		'valid': transforms.Compose([
			transforms.Resize(size=256),
			transforms.CenterCrop(size=224),
			transforms.ToTensor(),
			transforms.Normalize([0.485, 0.456, 0.406],
								 [0.229, 0.224, 0.225])
		])
	}

	train_directory = os.path.join(dataset, 'train')
	valid_directory = os.path.join(dataset, 'valid')

	data = {
		'train': datasets.ImageFolder(root=train_directory, transform=image_transforms['train']),
		'valid': datasets.ImageFolder(root=valid_directory, transform=image_transforms['valid'])
	}

	train_data_size = len(data['train'])
	valid_data_size = len(data['valid'])

	train_data = DataLoader(data['train'], batch_size=batch_size, shuffle=True)
	valid_data = DataLoader(data['valid'], batch_size=batch_size, shuffle=True)

	print("[INFO] Train data / Test data number: ", train_data_size, valid_data_size)
	return train_data, valid_data, train_data_size, valid_data_size


# -------------------------------------------------------------------------------------------
#	集成表决
# -------------------------------------------------------------------------------------------
def process(mlps, trainloader, testloader, valid_data_size):
	optimizer = torch.optim.Adam([{"params": mlp.parameters()} for mlp in mlps], lr=LR)
	loss_function = nn.CrossEntropyLoss()

	for ep in range(EPOCHES):
		print("Epoch: {}/{}".format(ep + 1, EPOCHES))
		print("[INFO] Begin to train")
		for img, label in tqdm(trainloader):
			img, label = img.to(device), label.to(device)
			optimizer.zero_grad()  # 10个网络清除梯度
			for mlp in mlps:
				mlp.train()
				out = mlp(img)
				loss = loss_function(out, label)
				loss.backward()  # 网络们获得梯度
			optimizer.step()

		pre = []
		vote_correct = 0
		mlps_correct = [0 for i in range(len(mlps))]

		print("[INFO] Begin to valid")
		for img, label in tqdm(testloader):
			img, label = img.to(device), label.to(device)
			for i, mlp in enumerate(mlps):
				mlp.eval()
				out = mlp(img)

				_, prediction = torch.max(out, 1)  # 按行取最大值
				pre_num = prediction.cpu().numpy()
				mlps_correct[i] += (pre_num == label.cpu().numpy()).sum()

				pre.append(pre_num)
			arr = np.array(pre)
			pre.clear()
			result = [Counter(arr[:, i]).most_common(1)[0][0] for i in range(BATCHSIZE)]
			vote_correct += (result == label.cpu().numpy()).sum()
		print("epoch:" + str(ep) + "集成模型的正确率" + str(vote_correct / valid_data_size))

		for idx, coreect in enumerate(mlps_correct):
			print("模型" + str(idx) + "的正确率为:" + str(coreect / valid_data_size))

if __name__ == '__main__':
	mlps = [mbnet(),  resnet152(),  mnasnet()]
	train_data, valid_data, train_data_size, valid_data_size = data_process()
	process(mlps=mlps, trainloader=train_data , testloader=valid_data, valid_data_size=valid_data_size)

效果:
在这里插入图片描述
模型准确性整体上还是有了较大提升。

  • 15
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论
### 回答1: 《PyTorch深度学习入门实战》是一本以PyTorch为工具,介绍深度学习基础知识和实践的书籍。在本书中,作者通过简洁易懂的语言,结合实际案例,帮助读者理解深度学习的基本概念和原理,并教授如何使用PyTorch库来实现各种深度学习模型。 本书内容主要分为两部分,第一部分是深度学习的基础知识,包括神经网络、卷积神经网络、循环神经网络等;第二部分是深度学习的实践技巧,包括数据预处理、模型训练模型优化等。通过这两部分的学习,读者可以逐步掌握深度学习的基本原理和实践技巧。 此外,本书还特别注重实战,为读者提供了大量的代码实例和实战案例。这些实例和案例不仅包括经典的深度学习任务,如图像分类、目标检测和语言生成等,还包括一些实际应用,如机器翻译、垃圾邮件识别等。通过这些实例和案例的学习,读者可以更好地理解深度学习的实际应用和解决实际问题的能力。 总的来说,本书以PyTorch为工具,以深度学习基础知识和实际案例为主线,通过深入浅出的讲解,帮助读者入门深度学习,并掌握使用PyTorch来实现深度学习模型的能力。无论是对于初学者还是有一定经验的开发者来说,《PyTorch深度学习入门实战》都是一本很好的学习资料。 ### 回答2: 《PyTorch深度学习入门实战》是一本介绍PyTorch深度学习库的教程图书。PyTorch是一种在机器学习领域广泛使用的开源深度学习库,它以动态图和静态图的混合方式,提供了灵活、高效的工具来构建和训练神经网络模型。 该书的目的是帮助读者快速入门PyTorch,并通过实战案例实践所学的知识。书中提供了丰富的示例代码和实验,从基础概念开始,逐步引导读者理解和掌握PyTorch的核心功能和应用。 在第一部分中,书籍详细介绍了PyTorch的安装和配置,包括如何创建和管理虚拟环境,以及如何使用pip安装PyTorch及其相关库。 第二部分主要介绍了PyTorch张量(Tensor)的基本操作和运算。这是深度学习中的基础,掌握好张量的操作对于后续的模型构建和训练非常重要。本书中通过大量的示例代码和实验,让读者逐步熟悉张量的创建、索引、切片以及各种元素级别的运算操作。 第三部分是关于PyTorch神经网络模块(nn)的详细介绍,包括如何使用nn.Module构建网络模型,以及如何使用nn.functional模块定义前向传播方法。同时也介绍了常用的损失函数和优化器,在训练模型时如何选择和使用它们。 第四部分是实战篇,书中通过几个典型的深度学习任务案例,如图像分类、目标检测和自然语言处理等,示范了如何使用PyTorch构建和训练神经网络模型。每个案例都包括了详细的代码解析和实验结果展示,读者可以通过这些案例学习和掌握如何在实际项目中应用PyTorch进行深度学习。 总之,《PyTorch深度学习入门实战》是一本非常实用的教程图书,适合对PyTorch感兴趣的初学者和有一定基础的开发者阅读。通过阅读本书,读者可以系统性地学习和掌握PyTorch深度学习框架,为深度学习实战应用提供基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI扩展坞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值