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

python打卡day43

用于图像分类的标志性乐器的数据集

import os
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms, models
from PIL import Image
from pytorch_grad_cam import GradCAM
from pytorch_grad_cam.utils.image import show_cam_on_image
# 1. 数据准备
class MusicInstrumentDataset(Dataset):def __init__(self, root_dir, csv_file, transform=None):self.root_dir = root_dirself.data = pd.read_csv(csv_file)self.transform = transformself.classes = self.data['class'].unique().tolist()self.total_images = sum(self.data['image_count'])self.image_paths = []self.labels = []for _, row in self.data.iterrows():class_dir = os.path.join(self.root_dir, row['class'])files = [f for f in os.listdir(class_dir) if f.endswith('.jpg')]files.sort(key=lambda x: int(x.split('.')[0]))self.image_paths.extend([os.path.join(class_dir, f) for f in files])self.labels.extend([self.classes.index(row['class'])] * len(files))def __len__(self):return len(self.image_paths)def __getitem__(self, idx):image = Image.open(self.image_paths[idx]).convert('RGB')label = self.labels[idx]if self.transform:image = self.transform(image)return image, label
# 2. 数据预处理
transform = transforms.Compose([transforms.RandomHorizontalFlip(),transforms.RandomRotation(15),transforms.ColorJitter(brightness=0.2, contrast=0.2, saturation=0.2),  # 新增颜色扰动transforms.RandomResizedCrop(224, scale=(0.8, 1.0)),  # 随机裁剪缩放transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
# 3. 创建数据集和数据加载器
dataset = MusicInstrumentDataset(root_dir="d:\\python打卡\\day43\\music_instruments",csv_file="d:\\python打卡\\day43\\music_instruments\\dataset_stats.csv",transform=transform
)train_size = int(0.8 * len(dataset))
test_size = len(dataset) - train_size
generator = torch.Generator().manual_seed(42)
train_dataset, test_dataset = torch.utils.data.random_split(dataset, [train_size, test_size],generator=generator
)train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
# 4. 定义CNN模型
class MusicInstrumentCNN(nn.Module):def __init__(self, num_classes=10):super(MusicInstrumentCNN, self).__init__()# 特征提取self.features = nn.Sequential(nn.Conv2d(3, 32, kernel_size=3, padding=1),nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),nn.Conv2d(32, 64, kernel_size=3, padding=1), nn.ReLU(inplace=True),nn.MaxPool2d(kernel_size=2, stride=2),)# 分类器self.classifier = nn.Sequential(nn.Linear(64 * 56 * 56, 128),nn.ReLU(inplace=True),nn.Dropout(0.5), nn.Linear(128, num_classes))def forward(self, x):# 特征提取x = self.features(x)# 展平特征图x = torch.flatten(x, 1)# 分类x = self.classifier(x)return x
# 5. 训练模型
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = MusicInstrumentCNN(num_classes=10).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.0005, weight_decay=1e-4)def train_model(model, train_loader, test_loader, criterion, optimizer, device, num_epochs):# 初始化记录变量train_losses = []test_losses = []train_accs = []test_accs = []batch_losses = []# 创建学习率调度器scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=2, factor=0.5)for epoch in range(num_epochs):model.train()running_loss = 0.0correct = 0total = 0# 训练阶段for batch_idx, (images, labels) in enumerate(train_loader):images, labels = images.to(device), labels.to(device)optimizer.zero_grad()outputs = model(images)loss = criterion(outputs, labels)loss.backward()optimizer.step()# 记录每个batch的损失batch_loss = loss.item()batch_losses.append(batch_loss)running_loss += batch_loss# 计算准确率_, predicted = torch.max(outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()# 每50个batch打印一次信息if (batch_idx + 1) % 50 == 0:print(f'Epoch [{epoch+1}/{num_epochs}], Batch [{batch_idx+1}/{len(train_loader)}], 'f'Batch Loss: {batch_loss:.4f}, Avg Loss: {running_loss/(batch_idx+1):.4f}')# 计算epoch指标epoch_loss = running_loss / len(train_loader)epoch_acc = 100 * correct / totaltrain_losses.append(epoch_loss)train_accs.append(epoch_acc)# 测试阶段model.eval()test_loss = 0.0test_correct = 0test_total = 0with torch.no_grad():for images, labels in test_loader:images, labels = images.to(device), labels.to(device)outputs = model(images)loss = criterion(outputs, labels)test_loss += loss.item()_, predicted = torch.max(outputs.data, 1)test_total += labels.size(0)test_correct += (predicted == labels).sum().item()test_epoch_loss = test_loss / len(test_loader)test_epoch_acc = 100 * test_correct / test_totaltest_losses.append(test_epoch_loss)test_accs.append(test_epoch_acc)# 更新学习率scheduler.step(test_epoch_loss)print(f'Epoch {epoch+1}/{num_epochs} - 'f'Train Loss: {epoch_loss:.4f}, Train Acc: {epoch_acc:.2f}%, 'f'Test Loss: {test_epoch_loss:.4f}, Test Acc: {test_epoch_acc:.2f}%')# 绘制训练曲线plt.figure(figsize=(12, 5))# 损失曲线plt.subplot(1, 2, 1)plt.plot(train_losses, label='Train Loss')plt.plot(test_losses, label='Test Loss')plt.xlabel('Epoch')plt.ylabel('Loss')plt.title('Training and Test Loss')plt.legend()# 准确率曲线plt.subplot(1, 2, 2)plt.plot(train_accs, label='Train Accuracy')plt.plot(test_accs, label='Test Accuracy')plt.xlabel('Epoch')plt.ylabel('Accuracy (%)')plt.title('Training and Test Accuracy')plt.legend()plt.tight_layout()plt.show()return test_accs[-1]num_epochs = 30
print("开始训练模型...")
final_acc = train_model(model, train_loader, test_loader, criterion, optimizer, device, num_epochs)
print(f"训练完成! 最终测试准确率: {final_acc:.2f}%")

开始训练模型...
Epoch 1/30 - Train Loss: 2.9460, Train Acc: 13.37%, Test Loss: 2.2104, Test Acc: 25.14%
Epoch 2/30 - Train Loss: 2.1367, Train Acc: 22.65%, Test Loss: 2.0500, Test Acc: 27.90%
Epoch 3/30 - Train Loss: 1.9983, Train Acc: 29.64%, Test Loss: 1.9392, Test Acc: 28.45%
Epoch 4/30 - Train Loss: 1.9475, Train Acc: 30.89%, Test Loss: 1.8508, Test Acc: 40.88%
Epoch 5/30 - Train Loss: 1.8551, Train Acc: 33.31%, Test Loss: 1.7993, Test Acc: 42.27%
Epoch 6/30 - Train Loss: 1.7731, Train Acc: 37.88%, Test Loss: 1.7242, Test Acc: 41.16%
Epoch 7/30 - Train Loss: 1.7001, Train Acc: 39.20%, Test Loss: 1.6823, Test Acc: 46.13%
Epoch 8/30 - Train Loss: 1.6640, Train Acc: 39.27%, Test Loss: 1.6702, Test Acc: 47.51%
Epoch 9/30 - Train Loss: 1.6542, Train Acc: 42.66%, Test Loss: 1.6524, Test Acc: 45.03%
Epoch 10/30 - Train Loss: 1.6106, Train Acc: 43.84%, Test Loss: 1.5587, Test Acc: 50.28%
Epoch 11/30 - Train Loss: 1.5937, Train Acc: 44.11%, Test Loss: 1.5993, Test Acc: 45.86%
Epoch 12/30 - Train Loss: 1.5644, Train Acc: 44.04%, Test Loss: 1.5558, Test Acc: 48.62%
Epoch 13/30 - Train Loss: 1.5326, Train Acc: 46.12%, Test Loss: 1.5794, Test Acc: 49.17%
Epoch 14/30 - Train Loss: 1.5449, Train Acc: 47.16%, Test Loss: 1.5342, Test Acc: 51.38%
Epoch 15/30 - Train Loss: 1.4615, Train Acc: 47.16%, Test Loss: 1.5037, Test Acc: 51.66%
Epoch 16/30 - Train Loss: 1.4308, Train Acc: 49.31%, Test Loss: 1.5152, Test Acc: 49.45%
Epoch 17/30 - Train Loss: 1.4268, Train Acc: 48.13%, Test Loss: 1.5076, Test Acc: 49.72%
Epoch 18/30 - Train Loss: 1.4646, Train Acc: 48.06%, Test Loss: 1.4967, Test Acc: 52.21%
Epoch 19/30 - Train Loss: 1.3818, Train Acc: 51.32%, Test Loss: 1.5149, Test Acc: 48.90%
Epoch 20/30 - Train Loss: 1.3524, Train Acc: 52.29%, Test Loss: 1.4570, Test Acc: 51.10%
Epoch 21/30 - Train Loss: 1.3269, Train Acc: 52.22%, Test Loss: 1.4431, Test Acc: 51.38%
Epoch 22/30 - Train Loss: 1.3648, Train Acc: 52.08%, Test Loss: 1.4540, Test Acc: 53.87%
Epoch 23/30 - Train Loss: 1.3316, Train Acc: 53.39%, Test Loss: 1.5655, Test Acc: 52.49%
Epoch 24/30 - Train Loss: 1.3121, Train Acc: 54.09%, Test Loss: 1.4549, Test Acc: 51.66%
Epoch 25/30 - Train Loss: 1.2702, Train Acc: 56.51%, Test Loss: 1.4119, Test Acc: 54.14%
Epoch 26/30 - Train Loss: 1.2295, Train Acc: 56.44%, Test Loss: 1.4718, Test Acc: 53.87%
Epoch 27/30 - Train Loss: 1.2020, Train Acc: 57.20%, Test Loss: 1.4213, Test Acc: 56.35%
Epoch 28/30 - Train Loss: 1.2028, Train Acc: 58.59%, Test Loss: 1.4769, Test Acc: 55.80%
Epoch 29/30 - Train Loss: 1.1816, Train Acc: 57.41%, Test Loss: 1.4514, Test Acc: 54.14%
Epoch 30/30 - Train Loss: 1.1956, Train Acc: 58.73%, Test Loss: 1.4667, Test Acc: 53.59%

训练完成! 最终测试准确率: 53.59%

# 6. Grad-CAM可视化
target_layer = model.features[-2]  # 选择最后一个卷积层
cam = GradCAM(model=model, target_layers=[target_layer])# 选择一个测试图像进行可视化
images, labels = next(iter(test_loader))
input_tensor = images[0:1].to(device)# 生成CAM
grayscale_cam = cam(input_tensor=input_tensor, targets=None)# 可视化
rgb_img = images[0].permute(1, 2, 0).cpu().numpy()
rgb_img = (rgb_img - rgb_img.min()) / (rgb_img.max() - rgb_img.min())  # 归一化
visualization = show_cam_on_image(rgb_img, grayscale_cam[0], use_rgb=True)plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.title("Original Image")
plt.imshow(rgb_img)
plt.axis('off')

(-0.5, 223.5, 223.5, -0.5)

plt.subplot(1, 2, 2)
plt.title("Grad-CAM")
plt.imshow(visualization)
plt.axis('off')
plt.show()

 

@浙大疏锦行

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

相关文章:

  • 【Python序列化】TypeError: Object of type xxx is not JSON serializable问题的解决方案
  • 分词算法BBPE详解和Qwen的应用
  • day 40 python打卡
  • Spring框架学习day6--事务管理
  • 【ISAQB大纲解读】信息隐藏指的是什么
  • 基于Qt的app开发的过渡期
  • PH热榜 | 2025-06-01
  • Flex弹性布局
  • langGraph多Agent
  • 【C语言入门级教学】冒泡排序和指针数组
  • ShardingSphere 分片策略深度解析
  • 导入典籍数据
  • 《仿盒马》app开发技术分享-- 购物车业务逻辑完善(端云一体)
  • java 多线程
  • 基于贝叶斯优化神经网络的光伏功率预测综述
  • Java JVM 内存模型详解
  • LeetCode 付费题157. 用 Read4 读取 N 个字符解题思路
  • deep forest安装及使用教程
  • 强大的PDF编辑工具,操作方便 ,长久使用
  • 第1天:认识RNN及RNN初步实验(预测下一个数字)
  • 【C盘瘦身】Docker安装目录占用C盘过大,一键移动给C盘瘦身
  • 大数据-275 Spark MLib - 基础介绍 机器学习算法 集成学习 随机森林 Bagging Boosting
  • 8、电解电容—数据手册解读
  • Unity使用Lua框架和C#框架开发游戏的区别
  • 2022年上半年软件设计师下午试题
  • 6月2日星期一今日早报简报微语报早读
  • 知识图谱系列(5):表示学习
  • 内网应用如何实现外网访问?无公网IP本地端口网址服务提供互联网连接
  • HCIP:MPLS LDP的原理和配置
  • Go开发简历优化指南