記事ディレクトリ
1. ResNet モデルの構築
PyTorch フレームワークを使用して、ResNet-18 モデルの簡易バージョンを実装します。私たちの目標は、CIFAR-10 データセットで分類タスクを実行できるモデルを構築することです。
1.1 前提条件
pip install torch torchvision
1.2 残りのブロックの構築
まず、残差ブロックを実装しましょう。これは前章で紹介した内容です。
import torch
import torch.nn as nn
class ResidualBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride=1):
super(ResidualBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1)
self.bn1 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU(inplace=True)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1)
self.bn2 = nn.BatchNorm2d(out_channels)
self.shortcut = nn.Sequential()
if stride != 1 or in_channels != out_channels:
self.shortcut = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride),
nn.BatchNorm2d(out_channels)
)
1.3 ResNet-18 の構築
次に、残差ブロックを使用して完全な ResNet-18 モデルを構築します。
class ResNet18(nn.Module):
def __init__(self, num_classes=10):
super(ResNet18, self).__init__()
self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.layer1 = self._make_layer(64, 64, 2)
self.layer2 = self._make_layer(64, 128, 2, stride=2)
self.layer3 = self._make_layer(128, 256, 2, stride=2)
self.layer4 = self._make_layer(256, 512, 2, stride=2)
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(512, num_classes)
def _make_layer(self, in_channels, out_channels, blocks, stride=1):
layers = []
layers.append(ResidualBlock(in_channels, out_channels, stride))
for _ in range(1, blocks):
layers.append(ResidualBlock(out_channels, out_channels))
return nn.Sequential(*layers)
def forward(self, x):
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
x = self.layer4(x)
x = self.avgpool(x)
x = torch.flatten(x, 1)
x = self.fc(x)
return x
上記のコードは、CIFAR-10 分類タスクの ResNet-18 モデルを定義します。ResidualBlock
このモデルでは、前に定義したクラスを使用し、_make_layer
関数を使用して複数の残差ブロックをスタックします。
1.4 モデルのテスト
次に、このモデルをテストして、その構造が正しいことを確認します。
# 创建一个模拟输入
x = torch.randn(64, 3, 32, 32)
# 实例化模型
model = ResNet18(num_classes=10)
# 前向传播
output = model(x)
# 输出形状应为(64, 10),因为我们有64个样本和10个类别
print(output.shape) # 输出:torch.Size([64, 10])
2. トレーニングと評価
ResNet-18 モデルの構築に成功したら、次のステップはモデルをトレーニングして評価することです。このセクションでは、CIFAR-10 データセットでこれら 2 つのステップを完了する方法を紹介します。
2.1 データの前処理とロード
まず、データを準備する必要があります。PyTorch のtorchvision
ライブラリを使用すると、CIFAR-10 データセットを非常に簡単にダウンロードして前処理できます。
import torch
import torchvision
import torchvision.transforms as transforms
# 数据预处理
transform = transforms.Compose([
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
])
# 加载数据集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True)
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=128, shuffle=False)
2.2 モデルのトレーニング
モデルをトレーニングするには、通常、損失関数とオプティマイザーを指定し、順伝播、損失の計算、逆伝播、パラメーターの更新を繰り返し実行する必要があります。
import torch.optim as optim
# 实例化模型并移至GPU
model = ResNet18(num_classes=10).cuda()
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)
# 训练模型
for epoch in range(10): # 运行10个周期
for i, data in enumerate(trainloader, 0):
inputs, labels = data
inputs, labels = inputs.cuda(), labels.cuda()
# 清零梯度缓存
optimizer.zero_grad()
# 前向传播,计算损失,反向传播
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
# 更新参数
optimizer.step()
2.3 モデルの評価
トレーニングが完了したら、モデルのパフォーマンスを評価する必要があります。これは通常、テスト セット上のモデルの精度を計算することによって行われます。
# 切换模型为评估模式
model.eval()
correct = 0
total = 0
with torch.no_grad():
for data in testloader:
images, labels = data
images, labels = images.cuda(), labels.cuda()
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {
100 * correct / total}%')
参照
理論的な内容: https://blog.csdn.net/magicyangjay111/article/details/132553872