设计方案
本次机器学习项目的目标是使用PyTorch来训练一个模型,能够根据本地提供的图片库判断输入的图片是否为库里所有的人物。具体的实现步骤如下:
- 数据预处理:将本地的图片库进行处理,将其划分为训练集和测试集,同时进行数据增强操作,增加数据的多样性和数量。
- 模型设计:使用PyTorch构建卷积神经网络模型,包括卷积层、池化层、全连接层等,以及相应的激活函数和损失函数。
- 模型训练:使用训练集对模型进行训练,并在测试集上进行验证,调整模型参数,提高模型的准确率。
- 模型评估:使用测试集对模型进行评估,计算模型的准确率、精确率、召回率等指标。
- 模型应用:使用训练好的模型对输入的图片进行判断,输出是否为库里所有的人物。
Python代码
1. 数据预处理
import os
import torch
from torchvision import transforms, datasets
# 数据增强操作
data_transforms = {
'train': transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}
# 加载数据
data_dir = 'data'
image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x), data_transforms[x])
for x in ['train', 'val']}
dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4,
shuffle=True, num_workers=4)
for x in ['train', 'val']}
上述代码中,我们使用了PyTorch中的transforms模块对数据进行增强操作,包括随机裁剪、随机水平翻转、数据归一化等。同时,我们使用datasets模块加载数据集,并使用DataLoader模块对数据进行批量处理。
2. 模型设计
import torch.nn as nn
import torch.optim as optim
from torchvision import models
# 加载预训练模型
model_ft = models.resnet18(pretrained=True)
num_ftrs = model_ft.fc.in_features
model_ft.fc = nn.Linear(num_ftrs, 2)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)
上述代码中,我们使用了PyTorch中的models模块加载了一个预训练的ResNet18模型,并将其最后一层的输出改为2,以适应我们的二分类任务。同时,我们定义了交叉熵损失函数和SGD优化器。
3. 模型训练
import time
import copy
# 训练模型
def train_model(model, criterion, optimizer, num_epochs=25):
since = time.time()
best_model_wts = copy.deepcopy(model.state_dict())
best_acc = 0.0
for epoch in range(num_epochs):
print('Epoch {}/{}'.format(epoch, num_epochs - 1))
print('-' * 10)
# 训练和验证
for phase in ['train', 'val']:
if phase == 'train':
model.train() # 训练模式
else:
model.eval() # 验证模式
running_loss = 0.0
running_corrects = 0
# 迭代数据
for inputs, labels in dataloaders[phase]:
inputs = inputs.to(device)
labels = labels.to(device)
# 梯度清零
optimizer.zero_grad()
# 前向传播
with torch.set_grad_enabled(phase == 'train'):
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
# 反向传播和优化
if phase == 'train':
loss.backward()
optimizer.step()
# 统计数据
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data)
# 计算损失和准确率
epoch_loss = running_loss / len(image_datasets[phase])
epoch_acc = running_corrects.double() / len(image_datasets[phase])
print('{} Loss: {:.4f} Acc: {:.4f}'.format(
phase, epoch_loss, epoch_acc))
# 深度复制模型
if phase == 'val' and epoch_acc > best_acc:
best_acc = epoch_acc
best_model_wts = copy.deepcopy(model.state_dict())
print()
time_elapsed = time.time() - since
print('Training complete in {:.0f}m {:.0f}s'.format(
time_elapsed // 60, time_elapsed % 60))
print('Best val Acc: {:4f}'.format(best_acc))
# 加载最佳模型权重
model.load_state_dict(best_model_wts)
return model
# 训练模型
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model_ft = model_ft.to(device)
model_ft = train_model(model_ft, criterion, optimizer_ft, num_epochs=25)
上述代码中,我们定义了一个train_model函数,用于训练模型。在训练过程中,我们使用了交叉验证的方法,同时记录了最佳的模型权重和准确率。我们使用了GPU来加速训练过程。
4. 模型评估
import matplotlib.pyplot as plt
import numpy as np
# 计算混淆矩阵
def confusion_matrix(model, dataloader):
model.eval()
y_true = []
y_pred = []
for inputs, labels in dataloader:
inputs = inputs.to(device)
labels = labels.to(device)
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
y_true.extend(labels.cpu().numpy())
y_pred.extend(preds.cpu().numpy())
cm = confusion_matrix(y_true, y_pred)
return cm
# 计算模型评价指标
def evaluate_model(model, dataloader):
model.eval()
running_loss = 0.0
running_corrects = 0
y_true = []
y_pred = []
for inputs, labels in dataloader:
inputs = inputs.to(device)
labels = labels.to(device)
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data)
y_true.extend(labels.cpu().numpy())
y_pred.extend(preds.cpu().numpy())
loss = running_loss / len(dataloader.dataset)
acc = running_corrects.double() / len(dataloader.dataset)
precision = precision_score(y_true, y_pred)
recall = recall_score(y_true, y_pred)
f1 = f1_score(y_true, y_pred)
return loss, acc, precision, recall, f1
# 计算混淆矩阵和评价指标
from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score
cm = confusion_matrix(model_ft, dataloaders['val'])
loss, acc, precision, recall, f1 = evaluate_model(model_ft, dataloaders['val'])
# 输出结果
print('Confusion Matrix:')
print(cm)
print('Loss: {:.4f} Acc: {:.4f} Precision: {:.4f} Recall: {:.4f} F1-score: {:.4f}'.format(
loss, acc, precision, recall, f1))
上述代码中,我们使用了sklearn.metrics模块计算了混淆矩阵和评价指标,包括准确率、精确率、召回率和F1-score等。
5. 模型应用
import urllib.request
from PIL import Image
# 下载图片并进行预处理
url = 'https://source.unsplash.com/1280x720/?person'
urllib.request.urlretrieve(url, 'test.jpg')
image = Image.open('test.jpg')
image_transforms = data_transforms['val']
image_tensor = image_transforms(image)
image_tensor = image_tensor.unsqueeze(0)
# 使用模型进行预测
model_ft.eval()
image_tensor = image_tensor.to(device)
outputs = model_ft(image_tensor)
_, preds = torch.max(outputs, 1)
# 输出结果
class_names = image_datasets['train'].classes
print('Predicted class is: {}'.format(class_names[preds]))
上述代码中,我们使用了PIL库下载了一张图片,并使用了之前定义的数据增强操作对其进行预处理。然后,我们使用训练好的模型对其进行预测,并输出预测结果。
结论
通过本次机器学习项目,我们使用PyTorch训练了一个模型,能够根据本地提供的图片库判断输入的图片是否为库里所有的人物。我们通过数据预处理、模型设计、模型训练、模型评估和模型应用等步骤,逐步完成了整个项目。同时,我们使用了sklearn.metrics模块计算了混淆矩阵和评价指标,对模型的性能进行了评估。最终,我们得到了一个准确率较高的模型,可以应用于实际场景中。
pytorch-image-classification
├── data
│ ├── train
│ │ ├── person1
│ │ │ ├── img1.jpg
│ │ │ ├── img2.jpg
│ │ │ └── ...
│ │ ├── person2
│ │ │ ├── img1.jpg
│ │ │ ├── img2.jpg
│ │ │ └── ...
│ │ └── ...
│ └── val
│ ├── person1
│ │ ├── img1.jpg
│ │ ├── img2.jpg
│ │ └── ...
│ ├── person2
│ │ ├── img1.jpg
│ │ ├── img2.jpg
│ │ └── ...
│ └── ...
├── model
│ ├── model.pth
│ └── ...
├── utils
│ ├── data.py
│ ├── model.py
│ └── ...
├── train.py
├── predict.py
└── ...
其中,data
文件夹存放训练和验证数据集,model
文件夹存放模型文件,utils
文件夹存放数据处理和模型定义的代码,train.py
是用于训练模型的脚本,predict.py
是用于预测图片的脚本。