当前位置: 首页 > ai >正文

python打卡44天

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms, models
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
import time
import os# 设置中文字体支持
plt.rcParams["font.family"] = ["SimHei"]
plt.rcParams['axes.unicode_minus'] = False# 检查GPU是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")# 数据预处理
train_transform = transforms.Compose([transforms.RandomCrop(32, padding=4),transforms.RandomHorizontalFlip(),transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2, hue=0.1),transforms.RandomRotation(15),transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])test_transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])# 加载CIFAR-10数据集
train_dataset = datasets.CIFAR10(root='./data',train=True,download=True,transform=train_transform
)test_dataset = datasets.CIFAR10(root='./data',train=False,transform=test_transform
)batch_size = 64
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)# 创建不同预训练模型的函数
def create_model(model_name, num_classes=10):"""创建并配置不同的预训练模型"""if model_name == "resnet18":model = models.resnet18(pretrained=True)# 修改第一层卷积以适应32x32输入model.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)# 移除第一个最大池化层model.maxpool = nn.Identity()# 修改最后的全连接层model.fc = nn.Linear(model.fc.in_features, num_classes)elif model_name == "efficientnet_b0":model = models.efficientnet_b0(pretrained=True)# 修改第一层卷积model.features[0][0] = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1, bias=False)# 修改分类器model.classifier[1] = nn.Linear(model.classifier[1].in_features, num_classes)elif model_name == "mobilenet_v3_small":model = models.mobilenet_v3_small(pretrained=True)# 修改第一层卷积model.features[0][0] = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1, bias=False)# 修改分类器model.classifier[3] = nn.Linear(model.classifier[3].in_features, num_classes)else:raise ValueError(f"未知模型: {model_name}")return model.to(device)# 模型训练函数
def train_model(model, model_name, train_loader, test_loader, epochs=15):"""训练模型并返回结果"""print(f"\n{'='*50}")print(f"开始训练 {model_name} 模型")print(f"{'='*50}")# 冻结除最后一层外的所有层for name, param in model.named_parameters():if "classifier" not in name and "fc" not in name:param.requires_grad = False# 优化器和损失函数optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)criterion = nn.CrossEntropyLoss()scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.5, patience=2)# 记录训练过程train_loss_history = []test_loss_history = []train_acc_history = []test_acc_history = []times = []start_time = time.time()for epoch in range(epochs):epoch_start = time.time()# 训练阶段model.train()running_loss = 0.0correct_train = 0total_train = 0for inputs, labels in train_loader:inputs, labels = inputs.to(device), labels.to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()_, predicted = outputs.max(1)total_train += labels.size(0)correct_train += predicted.eq(labels).sum().item()epoch_train_loss = running_loss / len(train_loader)epoch_train_acc = 100. * correct_train / total_traintrain_loss_history.append(epoch_train_loss)train_acc_history.append(epoch_train_acc)# 测试阶段model.eval()test_loss = 0.0correct_test = 0total_test = 0with torch.no_grad():for inputs, labels in test_loader:inputs, labels = inputs.to(device), labels.to(device)outputs = model(inputs)loss = criterion(outputs, labels)test_loss += loss.item()_, predicted = outputs.max(1)total_test += labels.size(0)correct_test += predicted.eq(labels).sum().item()epoch_test_loss = test_loss / len(test_loader)epoch_test_acc = 100. * correct_test / total_testtest_loss_history.append(epoch_test_loss)test_acc_history.append(epoch_test_acc)# 更新学习率scheduler.step(epoch_test_loss)epoch_time = time.time() - epoch_starttimes.append(epoch_time)print(f"Epoch {epoch+1}/{epochs} | "f"训练损失: {epoch_train_loss:.4f} | 训练准确率: {epoch_train_acc:.2f}% | "f"测试准确率: {epoch_test_acc:.2f}% | 时间: {epoch_time:.2f}s")total_time = time.time() - start_timeprint(f"训练完成! 最终测试准确率: {epoch_test_acc:.2f}% | 总时间: {total_time:.2f}s")return {"name": model_name,"train_loss": train_loss_history,"test_loss": test_loss_history,"train_acc": train_acc_history,"test_acc": test_acc_history,"times": times,"final_test_acc": epoch_test_acc,"total_time": total_time}# 比较不同模型
def compare_models(model_names, epochs=15):"""比较多个模型在CIFAR-10上的表现"""results = []for model_name in model_names:model = create_model(model_name)result = train_model(model, model_name, train_loader, test_loader, epochs)results.append(result)return results# 可视化比较结果
def visualize_comparison(results):"""可视化不同模型的比较结果"""plt.figure(figsize=(15, 10))# 准确率曲线plt.subplot(2, 2, 1)for result in results:plt.plot(result['test_acc'], label=result['name'])plt.xlabel('Epoch')plt.ylabel('测试准确率 (%)')plt.title('不同模型测试准确率比较')plt.legend()plt.grid(True)# 损失曲线plt.subplot(2, 2, 2)for result in results:plt.plot(result['test_loss'], label=result['name'])plt.xlabel('Epoch')plt.ylabel('测试损失')plt.title('不同模型测试损失比较')plt.legend()plt.grid(True)# 最终准确率比较plt.subplot(2, 2, 3)names = [r['name'] for r in results]accs = [r['final_test_acc'] for r in results]plt.bar(names, accs, color=['blue', 'green', 'orange'])plt.ylabel('最终测试准确率 (%)')plt.title('最终测试准确率比较')# 训练时间比较plt.subplot(2, 2, 4)times = [r['total_time'] for r in results]plt.bar(names, times, color=['blue', 'green', 'orange'])plt.ylabel('总训练时间 (秒)')plt.title('训练时间比较')plt.tight_layout()plt.savefig('model_comparison.png')plt.show()# 主函数
def main():# 要比较的模型model_names = ["resnet18", "efficientnet_b0", "mobilenet_v3_small"]# 训练并比较模型results = compare_models(model_names, epochs=15)# 打印最终结果print("\n模型比较结果:")for result in results:print(f"{result['name']}: 最终准确率 = {result['final_test_acc']:.2f}%, 训练时间 = {result['total_time']:.2f}秒")# 可视化比较visualize_comparison(results)if __name__ == "__main__":main()


分析观察:

  1. 准确率:ResNet18表现最佳,这得益于其残差结构能有效训练深层网络。EfficientNet-B0紧随其后,其复合缩放方法在准确率和效率间取得了平衡。MobileNetV3-Small作为轻量级模型,准确率略低但仍在合理范围。

  2. 训练时间:MobileNetV3-Small训练最快,适合资源受限场景。ResNet18次之,EfficientNet-B0最慢,因其更复杂的结构。

  3. 收敛速度:ResNet18收敛最快,前5个epoch就达到80%+准确率,得益于预训练权重和残差连接。MobileNetV3-Small初期收敛慢但后期稳定上升。

  4. 过拟合:所有模型在训练后期都出现轻微过拟合(训练准确率>测试准确率),但ResNet18的泛化能力最好。@浙大疏锦行

http://www.xdnf.cn/news/12466.html

相关文章:

  • Linux 下的COW机制(copy-on-write)
  • python八股文算法:三数之和
  • 前端~三维地图(cesium)地图遮罩蒙层
  • 货运车辆在高速公路上发生故障,应如何设置警示标志?
  • 山洪径流过程及洪水淹没数值模拟
  • JDK21 虚拟线程原理剖析与性能深度解析
  • 力扣面试150题--克隆图
  • 2025年服装收银系统推荐:助力服装商家高效经营
  • SDC命令详解:使用set_min_capacitance命令进行约束
  • hbuildx运行uzapp项目初始化配置
  • gid1 gid2 profileOwner
  • 使用 XState 状态机打造英语单词学习界面(demo)
  • 深入Kubernetes源码阅读指南核心概念- /pkg/api
  • 使用qsort函数对字符串中的星期名称进行排序
  • 30.【新型数据架构】-区块链数据架构
  • Java并发编程实战 Day 13:Fork/Join框架与并行计算
  • 如何解决 远程 合并冲突
  • Docker容器运行一段时间后GPU无法使用报错Failed to initialize NVML: Unknown Error
  • AFNetworking `setSecurityPolicy:` 方法源码解析及最佳实践
  • 以太网原理图设计和PCB设计deepseek
  • 三十三、面向对象底层逻辑-SpringMVC九大组件之HandlerExceptionResolver接口设计
  • 张量的理解
  • Python如何去除图片干扰
  • pp-ocrv5的关键改进PPHGNetV2_B4
  • java 异步
  • 2025-适用于Windows11Version 24H2的05累积更新,适合基于x64的系统(KB5058411) 安装错误-0x800f0831
  • 第四章 信息系统管理-4.1 管理方法
  • 正式上线!在 Sui 主网上使用 Nautilus 构建防篡改预言机
  • MCP是什么
  • STM32实战:数字音频播放器开发指南