Pytorch 微调预训练模型MobileNet_V2

Pytorch 微调预训练模型MobileNet_V2

在本文中,我们将介绍如何使用Pytorch进行微调预训练模型MobileNet_V2。MobileNet_V2是一种轻量级神经网络模型,适用于计算资源有限的情况下进行深度学习任务。通过微调预训练的MobileNet_V2模型,我们可以在特定的任务上获得更好的性能。

阅读更多:Pytorch 教程

1. 导入所需库和数据集

在开始之前,我们首先需要导入所需的库和数据集。Pytorch库是一个基于Torch的机器学习库,提供了丰富的工具和函数用于实现深度学习模型。此外,我们还需要下载和加载MobileNet_V2的预训练权重,以及一个相关的数据集用于微调。

以下是导入库和数据集的代码示例:

import torch
import torchvision
from torchvision import datasets, models, transforms

# 检查CUDA是否可用
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 数据预处理和增强
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 = 'path/to/dataset'
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']}
class_names = image_datasets['train'].classes

2. 加载预训练模型

接下来,我们需要加载预训练的MobileNet_V2模型,并且冻结它的所有层,以便在微调过程中不更新权重。这是因为MobileNet_V2的参数已经通过大规模的图像数据集进行了训练,具有良好的特征提取能力。

以下是加载预训练模型的代码示例:

# 加载预训练模型
model = models.mobilenet_v2(pretrained=True)
model.to(device)

# 冻结预训练模型的所有层
for param in model.parameters():
    param.requires_grad = False

# 更改最后一层全连接层的输出大小
num_ftrs = model.classifier[1].in_features
model.classifier[1] = torch.nn.Linear(num_ftrs, len(class_names))

# 将模型参数移到CUDA设备上(如果可用)
model = model.to(device)

在上述代码中,我们首先加载预训练的MobileNet_V2模型,然后将其迁移到所选的设备上(CPU或GPU)。然后,我们冻结了所有层的参数,以防止在微调过程中对其进行更新。最后,我们更改了该模型的最后一层全连接层的输出大小,以适应我们数据集中的类别数量。同样,我们还将模型参数移动到CUDA设备上(如果可用)。

3. 定义损失函数和优化器

为了进行微调,我们需要定义损失函数和优化器。在分类任务中,常用的损失函数是交叉熵损失函数。优化器的选择可以根据具体情况进行,常见的选择是随机梯度下降(SGD)或Adam优化器。

以下是定义损失函数和优化器的代码示例:

# 定义损失函数和优化器
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

在上述代码中,我们使用交叉熵损失函数作为分类任务的损失函数,并使用随机梯度下降(SGD)作为优化器。我们还设置了学习率为0.001和动量为0.9。

4. 微调模型

现在我们可以开始进行模型的微调了。我们需要迭代数据集中的所有样本,并根据模型的预测结果和真实标签来计算损失,并通过反向传播来更新模型的参数。

以下是微调模型的代码示例:

# 微调模型
num_epochs = 10
best_acc = 0.0

for epoch in range(num_epochs):
    # 训练阶段
    model.train()
    running_loss = 0.0
    running_corrects = 0

    for inputs, labels in dataloaders['train']:
        inputs = inputs.to(device)
        labels = labels.to(device)

        optimizer.zero_grad()

        # 前向传播
        with torch.set_grad_enabled(True):
            outputs = model(inputs)
            _, preds = torch.max(outputs, 1)
            loss = criterion(outputs, labels)

            # 反向传播和优化
            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['train'])
    epoch_acc = running_corrects.double() / len(image_datasets['train'])

    # 验证阶段
    model.eval()
    running_loss = 0.0
    running_corrects = 0

    for inputs, labels in dataloaders['val']:
        inputs = inputs.to(device)
        labels = labels.to(device)

        # 前向传播
        with torch.no_grad():
            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)

    epoch_loss_val = running_loss / len(image_datasets['val'])
    epoch_acc_val = running_corrects.double() / len(image_datasets['val'])

    # 输出训练过程中的损失和准确率
    print('Epoch [{}/{}], Loss: {:.4f}, Acc: {:.4f}, Val Loss: {:.4f}, Val Acc: {:.4f}'
          .format(epoch+1, num_epochs, epoch_loss, epoch_acc, epoch_loss_val, epoch_acc_val))

    # 保存在验证集上获得最佳准确率的模型
    if epoch_acc_val > best_acc:
        best_acc = epoch_acc_val
        best_model_wts = model.state_dict()

# 加载在验证集上获得最佳准确率的模型
model.load_state_dict(best_model_wts)

在上述代码中,我们首先设置了训练的总轮数(num_epochs)和最佳准确率(best_acc)。然后,我们使用两个嵌套的循环来进行训练和验证。在训练阶段,我们首先将模型设置为训练模式,然后对每个输入进行前向传播和反向传播以更新模型的参数。在验证阶段,我们将模型设置为评估模式,并计算验证集上的损失和准确率。我们还输出每个epoch的训练和验证过程中的损失和准确率,并保存在验证集上获得最佳准确率的模型参数。最后,我们加载在验证集上获得最佳准确率的模型参数,以便后续的预测和测试。

5. 模型预测和测试

在微调完模型后,我们可以使用该模型进行预测和测试了。首先,我们需要定义一个函数来使用训练好的模型对单个图像进行预测。

以下是定义预测函数的代码示例:

def predict_image(image_path, model):
    image = Image.open(image_path)
    image_tensor = data_transforms['val'](image).unsqueeze(0)
    image_tensor = image_tensor.to(device)

    with torch.no_grad():
        model.eval()
        outputs = model(image_tensor)

    _, preds = torch.max(outputs, 1)
    predicted_class = class_names[preds.item()]

    return predicted_class

在上述代码中,我们首先打开图像文件,然后将其转换为对应的张量并移动到所选的设备上。接下来,我们将模型设置为评估模式,并使用模型对图像进行预测。最后,我们通过输出的类别索引找到对应的类别名称,并返回预测结果。

除了单个图像的预测,我们还可以对整个测试集进行预测,并计算预测准确率。

以下是对测试集进行预测并计算准确率的代码示例:

correct = 0
total = 0
model.eval()

with torch.no_grad():
    for images, labels in dataloaders['val']:
        images = images.to(device)
        labels = labels.to(device)

        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

accuracy = correct / total
print('Accuracy on test set: {:.4f}'.format(accuracy))

在上述代码中,我们首先将模型设置为评估模式,并使用torch.no_grad()来关闭梯度计算。然后,我们对测试集的每个图像进行预测,并统计正确预测的数量。最后,我们计算预测准确率并输出在测试集上的准确率。

总结

本文介绍了如何使用Pytorch进行微调预训练模型MobileNet_V2。我们首先导入所需的库和数据集,然后加载预训练的MobileNet_V2模型,并冻结其所有层。接下来,我们定义了损失函数和优化器,并进行了模型的微调。最后,我们展示了如何使用训练好的模型进行预测和测试,并计算了在测试集上的准确率。通过本文的介绍,希望读者能够了解和掌握使用Pytorch进行预训练模型微调的方法。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程