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

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.lqws.cn/news/191755.html

相关文章:

  • 破壁焕新能:DeviceNET转EtherNet/IP网关赋能烟草智能制造跃迁
  • 通过Spring AI框架搭建mcp服务端说明
  • 动态内存管理
  • C++——红黑树
  • 22N60-ASEMI光伏逆变器专用22N60
  • N2语法 列挙、話題提出
  • ROS1: 使用rosbag的方式将点云topic保存为pcd文件
  • 软考 系统架构设计师系列知识点之杂项集萃(83)
  • H_Prj06 8088单板机的串口
  • Java下载文件(特殊字符编码处理)
  • 为什么说数列是特殊的函数
  • 2025主流智能体Agent终极指南:Manus、OpenManus、MetaGPT、AutoGPT与CrewAI深度横评
  • Day14
  • Java-IO流之压缩与解压缩流详解
  • 前端开发面试题总结-JavaScript篇(一)
  • SQLAlchemy 中的 func 函数使用指南
  • 手机号段数据库的作用
  • 传统的将自然语言转化为嵌入向量的核心机制是:,将离散的语言符号转化为连续的语义向量,其核心依赖“上下文决定语义”的假设和神经网络的特征提取能力。
  • SATA3.0接口PCB布局走线注意事项
  • 【各种主流消息队列(MQ)对比指南】
  • vue3:十五、管理员管理-页面搭建
  • CMake 为 Debug 版本的库或可执行文件添加 d 后缀
  • vue组件的data为什么是函数?
  • FPGA没有使用的IO悬空对漏电流有没有影响
  • 毫米波雷达基础理论(3D+4D)
  • 如何使用索引和条件批量更改Series数据
  • MajicTryOn(基于wanvideo的虚拟试穿项目)
  • C++.OpenGL (7/64)摄像机(Camera)
  • Dify工具插件开发和智能体开发全流程
  • GNSS终端授时方式-合集:PPS、B码、NTP、PTP、单站授时,共视授时