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
import torchvision.transforms as transforms
import torchvision.models as models
from torch.utils.data import DataLoader
from collections import Counter
from torch.optim.lr_scheduler import CosineAnnealingLR, LinearLR, SequentialLR
# 超参数设置
BATCH_SIZE = 128
EPOCHES = 100
LR = 0.001
WARMUP_EPOCHS = 5
# 启用cudnn加速
cudnn.benchmark = True
# 改进的数据增强
transform_train = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(p=0.5),
transforms.RandomRotation(15),
transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.247, 0.243, 0.261)),
])
transform_test = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.247, 0.243, 0.261))
])
# 更精确的模型修改函数
def modify_model_for_cifar10(model, model_name):
# 修改第一层卷积以适应32x32输入
if hasattr(model, 'conv1'):
if isinstance(model.conv1, nn.Conv2d):
# 对于ResNet等模型
model.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)
# 修改分类器层
if model_name == 'resnet34':
model.fc = nn.Linear(model.fc.in_features, 10)
elif model_name == 'efficientnet_b3':
model.classifier = nn.Linear(model.classifier[1].in_features, 10)
elif model_name == 'densenet121':
model.classifier = nn.Linear(model.classifier.in_features, 10)
elif model_name == 'mobilenet_v3_large':
# MobileNetV3的特殊处理
model.classifier = nn.Sequential(
nn.Linear(model.classifier[0].in_features, 1280),
nn.Hardswish(inplace=True),
nn.Dropout(p=0.2, inplace=True),
nn.Linear(1280, 10),
)
elif model_name == 'vgg19_bn':
model.classifier = nn.Sequential(
nn.Linear(512 * 1 * 1, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 10),
)
return model
def get_models(device):
"""获取多个预训练模型"""
model_names = [
'resnet34',
'efficientnet_b3',
'densenet121',
]
models_list = []
for name in model_names:
try:
# 使用新的weights API
if name == 'resnet34':
weights = models.ResNet34_Weights.IMAGENET1K_V1
model = models.resnet34(weights=weights)
elif name == 'efficientnet_b3':
weights = models.EfficientNet_B3_Weights.IMAGENET1K_V1
model = models.efficientnet_b3(weights=weights)
elif name == 'densenet121':
weights = models.DenseNet121_Weights.IMAGENET1K_V1
model = models.densenet121(weights=weights)
model = modify_model_for_cifar10(model, name)
model = model.to(device)
models_list.append(model)
print(f"成功加载模型: {name}")
except Exception as e:
print(f"加载模型 {name} 失败: {e}")
return models_list
def train_ensemble(models, train_loader, test_loader, device, epochs=100):
"""训练集成模型"""
# 为每个模型创建优化器和学习率调度器
optimizers = []
schedulers = []
for model in models:
# 使用AdamW优化器,权重衰减防止过拟合
optimizer = optim.AdamW(model.parameters(), lr=LR, weight_decay=1e-4)
# 学习率调度:预热 + 余弦退火
warmup_scheduler = LinearLR(optimizer, start_factor=0.1, total_iters=WARMUP_EPOCHS)
cosine_scheduler = CosineAnnealingLR(optimizer, T_max=epochs - WARMUP_EPOCHS)
scheduler = SequentialLR(optimizer,
schedulers=[warmup_scheduler, cosine_scheduler],
milestones=[WARMUP_EPOCHS])
optimizers.append(optimizer)
schedulers.append(scheduler)
# 使用标签平滑的交叉熵损失
criterion = nn.CrossEntropyLoss(label_smoothing=0.1)
best_accuracy = 0.0
for epoch in range(epochs):
print(f"\nEpoch {epoch + 1}/{epochs}")
# 训练阶段
for model in models:
model.train()
train_loss = 0.0
train_correct = 0
train_total = 0
for batch_idx, (data, target) in enumerate(train_loader):
data, target = data.to(device), target.to(device)
batch_size = data.size(0)
train_total += batch_size
# 为每个模型单独计算损失和梯度
batch_loss = 0
for model, optimizer in zip(models, optimizers):
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
batch_loss += loss.item()
# 统计训练准确率(使用最后一个模型的预测)
if model == models[-1]:
_, predicted = torch.max(output, 1)
train_correct += (predicted == target).sum().item()
train_loss += batch_loss / len(models) * batch_size
if batch_idx % 100 == 0:
print(f'训练进度: {batch_idx}/{len(train_loader)}, 当前批次损失: {batch_loss / len(models):.4f}')
# 更新学习率
for scheduler in schedulers:
scheduler.step()
# 评估阶段
current_accuracy = evaluate_ensemble(models, test_loader, device, epoch)
# 保存最佳模型
if current_accuracy > best_accuracy:
best_accuracy = current_accuracy
for i, model in enumerate(models):
torch.save(model.state_dict(), f'best_model_{i}.pth')
print(f"新的最佳准确率: {best_accuracy:.4f}")
# 打印训练统计
print(f"训练损失: {train_loss / train_total:.4f}, 训练准确率: {train_correct / train_total:.4f}")
print(f"\n训练完成! 最佳准确率: {best_accuracy:.4f}")
return best_accuracy
def evaluate_ensemble(models, test_loader, device, epoch=None):
"""评估集成模型性能"""
models_correct = [0] * len(models)
ensemble_correct = 0
total = 0
# 可以根据验证集性能调整权重(这里使用等权重)
model_weights = [1.0] * len(models)
with torch.no_grad():
for data, target in test_loader:
data, target = data.to(device), target.to(device)
batch_size = data.size(0)
total += batch_size
# 收集所有模型的预测概率
all_probs = []
for i, model in enumerate(models):
model.eval()
output = model(data)
probs = F.softmax(output, dim=1)
all_probs.append(probs * model_weights[i])
# 单个模型准确率
_, predicted = torch.max(output, 1)
models_correct[i] += (predicted == target).sum().item()
# 加权集成预测
ensemble_probs = sum(all_probs)
_, ensemble_predicted = torch.max(ensemble_probs, 1)
ensemble_correct += (ensemble_predicted == target).sum().item()
# 打印结果
ensemble_accuracy = ensemble_correct / total
if epoch is not None:
print(f"Epoch {epoch + 1} 评估结果:")
else:
print("最终评估结果:")
print(f"集成模型准确率: {ensemble_accuracy:.4f}")
for i, correct in enumerate(models_correct):
print(f"模型 {i + 1} 准确率: {correct / total:.4f}")
print("-" * 50)
return ensemble_accuracy
def main():
# 设置设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"使用设备: {device}")
# 数据准备
print('==> 准备数据..')
# 下载数据集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train)
trainloader = DataLoader(trainset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2, pin_memory=True)
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test)
testloader = DataLoader(testset, batch_size=100, shuffle=False, num_workers=2, pin_memory=True)
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
print(f'类别: {classes}')
# 模型初始化
print('==> 构建模型..')
mlps = get_models(device)
if len(mlps) == 0:
print("错误: 没有成功加载任何模型!")
return
print(f"成功加载 {len(mlps)} 个模型进行集成学习")
# 显示模型参数数量
for i, model in enumerate(mlps):
total_params = sum(p.numel() for p in model.parameters())
print(f"模型 {i + 1} 参数数量: {total_params:,}")
# 训练集成模型
best_accuracy = train_ensemble(mlps, trainloader, testloader, device, EPOCHES)
print(f"\n训练完成! 最终最佳准确率: {best_accuracy:.4f}")
if __name__ == '__main__':
main()
十类图片深度学习提升准确率(0.9317)
诸葛箫声2025-10-17 23:01
相关推荐
余俊晖2 小时前
一套针对金融领域多模态问答的自适应多层级RAG框架-VeritasFi码农阿树2 小时前
视频解析转换耗时—OpenCV优化摸索路伏小白白白3 小时前
【论文精度-2】求解车辆路径问题的神经组合优化算法:综合展望(Yubin Xiao,2025)应用市场3 小时前
OpenCV编程入门:从零开始的计算机视觉之旅星域智链3 小时前
宠物智能用品:当毛孩子遇上 AI,是便利还是过度?taxunjishu4 小时前
DeviceNet 转 MODBUS TCP罗克韦尔 ControlLogix PLC 与上位机在汽车零部件涂装生产线漆膜厚度精准控制的通讯配置案例说私域4 小时前
基于多模态AI技术的传统行业智能化升级路径研究——以开源AI大模型、AI智能名片与S2B2C商城小程序为例囚生CY4 小时前
【速写】优化的深度与广度(Adam & Moun)hqyjzsb4 小时前
2025年市场岗位能力重构与跨领域转型路径分析爱学习的uu4 小时前
CURSOR最新使用指南及使用思路