十类图片深度学习提升准确率(0.9317)

复制代码
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()
相关推荐
余俊晖2 小时前
一套针对金融领域多模态问答的自适应多层级RAG框架-VeritasFi
人工智能·金融·rag
码农阿树2 小时前
视频解析转换耗时—OpenCV优化摸索路
人工智能·opencv·音视频
伏小白白白3 小时前
【论文精度-2】求解车辆路径问题的神经组合优化算法:综合展望(Yubin Xiao,2025)
人工智能·算法·机器学习
应用市场3 小时前
OpenCV编程入门:从零开始的计算机视觉之旅
人工智能·opencv·计算机视觉
星域智链3 小时前
宠物智能用品:当毛孩子遇上 AI,是便利还是过度?
人工智能·科技·学习·宠物
taxunjishu4 小时前
DeviceNet 转 MODBUS TCP罗克韦尔 ControlLogix PLC 与上位机在汽车零部件涂装生产线漆膜厚度精准控制的通讯配置案例
人工智能·区块链·工业物联网·工业自动化·总线协议
说私域4 小时前
基于多模态AI技术的传统行业智能化升级路径研究——以开源AI大模型、AI智能名片与S2B2C商城小程序为例
人工智能·小程序·开源
囚生CY4 小时前
【速写】优化的深度与广度(Adam & Moun)
人工智能·python·算法
hqyjzsb4 小时前
2025年市场岗位能力重构与跨领域转型路径分析
c语言·人工智能·信息可视化·重构·媒体·改行学it·caie
爱学习的uu4 小时前
CURSOR最新使用指南及使用思路
人工智能·笔记·python·软件工程