from torchvision import transforms, datasets import matplotlib.pyplot as plt from model import * import torch import torch.nn as nn import os, sys import numpy as np import scikitplot as skplt from sklearn.metrics import accuracy_score, f1_score, recall_score, precision_score root = sys.path[0] # 获取项目根目录 # 设置数据集的预处理方式 transform = transforms.Compose([ transforms.Resize((224, 224)), # 调整大小为224x224 transforms.ToTensor(), # 转换为张量 transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # 标准化 ]) # 加载数据 训练集 验证集 测试集 train_data = datasets.ImageFolder(os.path.join(root, 'data', 'train'), transform) test_data = datasets.ImageFolder(os.path.join(root, 'data', 'test'), transform) val_data = datasets.ImageFolder(os.path.join(root, 'data', 'val'), transform) print('类别:', train_data.classes) # 查看类别 # 构造批量数据 batch_size = 8 train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, shuffle=True) test_loader = torch.utils.data.DataLoader(test_dat
时间: 2025-08-25 16:15:41 AIGC 浏览: 18
<think>好的,用户提供了一段Python代码,看起来是关于使用PyTorch进行图像分类任务的。他们可能在处理数据加载、模型定义以及训练流程时遇到了问题,或者想进一步优化他们的代码。首先,我需要仔细分析用户提供的代码片段,看看哪里可能存在问题或者可以改进的地方。
首先,代码中导入了必要的库,包括torchvision的transforms和datasets,matplotlib用于绘图,以及自定义的model模块。然后设置了数据预处理流程,包括调整大小、转换为张量和标准化。接下来加载了训练集、测试集和验证集,并打印了类别。然后创建了DataLoader实例,batch_size设为8,但测试集的DataLoader部分代码不完整,最后一行被截断了,应该是test_data而不是test_dat,这可能导致运行时错误。用户可能在运行时遇到了NameError,因为test_dat未定义。
接下来,用户可能希望了解如何定义模型、训练循环、评估指标,比如准确率、F1分数等,以及如何绘制混淆矩阵和ROC曲线。代码中提到了使用scikitplot和sklearn的指标,但实际代码中可能没有实现这些部分,需要补充。
此外,用户可能在模型训练过程中遇到了问题,比如过拟合、训练速度慢,或者不知道如何正确使用自定义的模型。需要检查他们的模型定义是否正确,是否使用了预训练模型,以及优化器和损失函数的选择是否合适。可能还需要考虑数据增强的部分,现有的预处理只有Resize、ToTensor和标准化,可能缺乏数据增强步骤,比如随机裁剪、水平翻转等,这有助于提高模型的泛化能力。另外,数据加载部分是否正确设置了路径?检查os.path.join(root,'data', 'train')等路径是否正确,确保数据集存放正确。
在评估部分,用户可能想了解如何计算更多的指标,如召回率、精确率,以及如何生成混淆矩阵和ROC曲线。现有的代码导入了相关库,但还没有实际应用的代码,需要补充这部分内容。
最后,用户可能想了解如何保存和加载训练好的模型,以及进行推理测试。
基于这些分析,我需要提供一个完整的解决方案,包括修正代码错误,补充模型训练、评估的代码,解释每一步的作用,并给出相关的问题建议,帮助用户进一步理解和改进他们的项目。</think>代码片段存在不完整问题(`test_loader`部分被截断),同时缺少模型训练和评估的关键代码。以下是完整的PyTorch图像分类实现方案:
```python
from torchvision import transforms, datasets
import matplotlib.pyplot as plt
from model import *
import torch
import torch.nn as nn
import os, sys
import numpy as np
from torch.utils.data import DataLoader
import scikitplot as skplt
from sklearn.metrics import accuracy_score, f1_score, recall_score, precision_score
# 初始化配置
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
root = sys.path[0]
num_classes = 2 # 根据实际类别数修改
# 数据预处理增强
train_transform = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
val_transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
# 数据集加载
train_data = datasets.ImageFolder(os.path.join(root, 'data', 'train'), train_transform)
test_data = datasets.ImageFolder(os.path.join(root, 'data', 'test'), val_transform)
val_data = datasets.ImageFolder(os.path.join(root, 'data', 'val'), val_transform)
# 数据加载器
batch_size = 32
train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True, num_workers=4)
val_loader = DataLoader(val_data, batch_size=batch_size, shuffle=False)
test_loader = DataLoader(test_data, batch_size=batch_size, shuffle=False)
# 模型初始化
model = resnet18(pretrained=True)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, num_classes)
model = model.to(device)
# 训练配置
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=7, gamma=0.1)
# 训练函数
def train_model(model, num_epochs=25):
best_acc = 0.0
for epoch in range(num_epochs):
model.train()
running_loss = 0.0
for inputs, labels in train_loader:
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item() * inputs.size(0)
epoch_loss = running_loss / len(train_data)
val_acc = evaluate(model, val_loader)
print(f'Epoch {epoch+1}/{num_epochs}')
print(f'Train Loss: {epoch_loss:.4f} Val Acc: {val_acc:.4f}')
if val_acc > best_acc:
best_acc = val_acc
torch.save(model.state_dict(), 'best_model.pth')
scheduler.step()
return model
# 评估函数
def evaluate(model, loader):
model.eval()
correct = 0
total = 0
with torch.no_grad():
for inputs, labels in loader:
inputs = inputs.to(device)
labels = labels.to(device)
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
total += labels.size(0)
correct += (preds == labels).sum().item()
return correct / total
# 指标计算
def calculate_metrics(model, loader):
y_true = []
y_pred = []
y_proba = []
model.eval()
with torch.no_grad():
for inputs, labels in loader:
inputs = inputs.to(device)
outputs = model(inputs)
probabilities = torch.nn.functional.softmax(outputs, dim=1)
_, preds = torch.max(outputs, 1)
y_true.extend(labels.cpu().numpy())
y_pred.extend(preds.cpu().numpy())
y_proba.extend(probabilities.cpu().numpy())
print(f'Accuracy: {accuracy_score(y_true, y_pred):.4f}')
print(f'Precision: {precision_score(y_true, y_pred, average="macro"):.4f}')
print(f'Recall: {recall_score(y_true, y_pred, average="macro"):.4f}')
print(f'F1 Score: {f1_score(y_true, y_pred, average="macro"):.4f}')
# 绘制混淆矩阵
skplt.metrics.plot_confusion_matrix(y_true, y_pred, normalize=True)
plt.show()
# 绘制ROC曲线(适用于二分类)
if num_classes == 2:
skplt.metrics.plot_roc(y_true, y_proba)
plt.show()
# 主程序
if __name__ == "__main__":
trained_model = train_model(model, num_epochs=25)
print("Testing performance:")
calculate_metrics(trained_model, test_loader)
```
代码关键点解释:
1. 数据增强:训练集使用随机裁剪和翻转,验证/测试集使用中心裁剪
2. 迁移学习:使用预训练的ResNet18模型,替换最后的全连接层
3. 学习率调度:使用StepLR进行学习率衰减
4. 模型保存:保存验证集表现最好的模型
5. 评估指标:计算准确率、精确率、召回率、F1值,绘制混淆矩阵和ROC曲线
阅读全文
相关推荐


















