基于pytorch 的vgg16进行遥感影像分类,并引入注意力机制,并绘制训练结果和测试结果图
时间: 2024-05-08 07:20:56 浏览: 164
VGG卷积神经网络图像分类训练Pytorch代码 使用Cifar100数据集
5星 · 资源好评率100%
好的,这是一个比较复杂的任务,需要涉及到一些深度学习和pytorch的知识。我将尽力解释清楚。
首先,我们需要了解一下VGG16网络。VGG16是一个深度卷积神经网络,它由16个卷积层和3个全连接层组成。它的主要特点是卷积层都使用了3x3的小卷积核,这样可以减少模型的参数数量,同时也可以增加非线性变换的能力。在我们的遥感影像分类任务中,我们可以利用VGG16网络提取图像的特征,然后再进行分类。
接下来,我们需要引入注意力机制。注意力机制常用于图像分类、目标检测等任务中。它可以使模型关注到图像中的重要部分,从而提高分类的准确率。在pytorch中,我们可以使用自定义的注意力层来实现注意力机制。
下面是代码实现的主要步骤:
1. 安装pytorch和相关的库。
2. 准备数据集。我们可以使用遥感影像分类数据集,例如UC Merced Land Use Dataset等。将数据集分为训练集和测试集,并进行数据增强操作,例如旋转、翻转、缩放等。
3. 定义模型。我们可以利用预训练的VGG16网络来提取特征,然后再引入自定义的注意力层。注意力层可以通过对卷积层的输出进行加权平均来实现。最后,加一个全连接层进行分类。
4. 定义损失函数和优化器。我们可以使用交叉熵损失函数和Adam优化器。
5. 训练模型。使用训练集进行模型训练,同时记录训练过程中的损失值和准确率。
6. 测试模型。使用测试集进行模型测试,计算测试集的准确率。
7. 绘制训练结果和测试结果图。可以使用matplotlib库进行绘图,绘制训练过程中的损失值和准确率曲线,以及测试结果的混淆矩阵。
下面是示例代码:
```python
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.transforms as transforms
from torchvision.datasets import ImageFolder
from torch.utils.data import DataLoader
import matplotlib.pyplot as plt
import numpy as np
# 定义自定义的注意力层
class AttentionLayer(nn.Module):
def __init__(self, in_channels, out_channels):
super(AttentionLayer, self).__init__()
self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
x = self.conv(x)
x = self.sigmoid(x)
return x
# 定义模型
class VGG16_Attention(nn.Module):
def __init__(self, num_classes=10):
super(VGG16_Attention, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(128, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(256, 512, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
)
self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
self.attention1 = AttentionLayer(512, 1)
self.attention2 = AttentionLayer(512, 1)
self.attention3 = AttentionLayer(512, 1)
self.attention4 = AttentionLayer(512, 1)
self.classifier = nn.Sequential(
nn.Linear(512*7*7, 4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096, num_classes),
)
def forward(self, x):
x = self.features(x)
x1 = x[:, :, 14:21, 14:21] # 提取第一层注意力区域
x2 = x[:, :, 7:14, 7:14] # 提取第二层注意力区域
x3 = x[:, :, 3:10, 3:10] # 提取第三层注意力区域
x4 = x[:, :, :7, :7] # 提取第四层注意力区域
a1 = self.attention1(x1) # 计算第一层注意力权重
a2 = self.attention2(x2) # 计算第二层注意力权重
a3 = self.attention3(x3) # 计算第三层注意力权重
a4 = self.attention4(x4) # 计算第四层注意力权重
x1 = x1 * a1 # 加权平均
x2 = x2 * a2
x3 = x3 * a3
x4 = x4 * a4
x = torch.cat([x1, x2, x3, x4, x], dim=1) # 拼接
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.classifier(x)
return x
# 定义数据增强操作
transform_train = transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
transform_test = 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_dataset = ImageFolder('train', transform=transform_train)
test_dataset = ImageFolder('test', transform=transform_test)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
# 定义模型、损失函数和优化器
model = VGG16_Attention(num_classes=10)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练模型
train_losses, train_accs = [], []
for epoch in range(10):
model.train()
train_loss, train_acc = 0, 0
for images, labels in train_loader:
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
train_loss += loss.item()
train_acc += (outputs.argmax(dim=1) == labels).sum().item()
train_loss /= len(train_loader)
train_acc /= len(train_dataset)
train_losses.append(train_loss)
train_accs.append(train_acc)
print(f'Epoch {epoch+1}, train loss: {train_loss:.4f}, train acc: {train_acc:.4f}')
# 测试模型
model.eval()
test_acc = 0
conf_matrix = np.zeros((10, 10))
with torch.no_grad():
for images, labels in test_loader:
outputs = model(images)
test_acc += (outputs.argmax(dim=1) == labels).sum().item()
for i, j in zip(labels, outputs.argmax(dim=1)):
conf_matrix[i][j] += 1
test_acc /= len(test_dataset)
print(f'Test acc: {test_acc:.4f}')
print('Confusion matrix:')
print(conf_matrix)
# 绘制训练结果图和测试结果图
plt.figure()
plt.plot(train_losses)
plt.xlabel('Epoch')
plt.ylabel('Train loss')
plt.savefig('train_loss.png')
plt.figure()
plt.plot(train_accs)
plt.xlabel('Epoch')
plt.ylabel('Train acc')
plt.savefig('train_acc.png')
plt.figure()
plt.imshow(conf_matrix, cmap='Blues')
plt.colorbar()
plt.xticks(range(10))
plt.yticks(range(10))
plt.xlabel('Predicted label')
plt.ylabel('True label')
plt.savefig('conf_matrix.png')
```
在运行完上述代码后,可以得到训练结果和测试结果的图像,它们分别是train_loss.png、train_acc.png和conf_matrix.png。其中train_loss.png和train_acc.png分别表示训练过程中的损失值和准确率曲线,conf_matrix.png表示测试结果的混淆矩阵。
阅读全文