Pytorchは、クラシックモデルLeNet-5に基づいてMNISTデータセットで手書き数字をトレーニングします

LeNet-5の紹介

LeNet-5公式ウェブサイトリンク
畳み込みニューラルネットワークは、特別な多層ニューラルネットワークです。他のほとんどすべてのニューラルネットワークと同様に、それらはバックプロパゲーションアルゴリズムのバージョンを使用してトレーニングされます。それらの違いはアーキテクチャです。
畳み込みニューラルネットワークは、最小限の前処理でピクセル画像から直接視覚パターンを認識するように設計されています。
それらは、大きな変動性のあるパターン(手書き文字など)を認識でき、歪みや単純な幾何学的変換に対して堅牢です。
LeNet-5は、手書きおよび機械印刷された文字認識用に設計されています。
ここに画像の説明を挿入
C1層は6つの畳み込みカーネル(6種類の局所特徴が抽出される)を持つ畳み込み層であり、カーネルサイズは5 * 5です
。S2層はプーリング層であり、ダウンサンプリング(面積:2 * 2)はネットワークを縮小しますトレーニングパラメータとモデル。過剰適合の程度。
C3レイヤーは2番目の畳み込みレイヤーで、16個の畳み込みカーネルを使用します。カーネルサイズ:5 * 5で特徴を抽出します
。S4レイヤーもプーリングレイヤー、面積:2 * 2
C5レイヤーは最後の畳み込みレイヤー、畳み込みカーネルサイズ:5 * 5畳み込みカーネルタイプ:120
最後に、完全に接続されたレイヤーを使用して、C5の120の特徴を分類し、最後に0〜9の確率を出力します。

LeNet-5が強力な理由は、当時の環境でのMNISTデータの認識率が99%に向上したためです。次のテストは、MNISTデータを使用して実行されます。

データセットを準備する

PytorchにはMNISTデータセットが含まれているため、ここで直接使用できます。DataLoaderを直接使用してデータを読み取ります。
トレーニングデータセット

train_loader = torch.utils.data.DataLoader(
        datasets.MNIST('data', train=True, download=True, 
                       transform=transforms.Compose([
                           transforms.ToTensor(),
                           transforms.Normalize((0.1307,), (0.3081,))
                       ])),
        batch_size=BATCH_SIZE, shuffle=True)

テストデータセット

test_loader = torch.utils.data.DataLoader(
        datasets.MNIST('data', train=False, transform=transforms.Compose([
                           transforms.ToTensor(),
                           transforms.Normalize((0.1307,), (0.3081,))
                       ])),
        batch_size=BATCH_SIZE, shuffle=True)

ネットワークを定義する

注:公式チュートリアルで定義されているネットワークには、32X32アクセスイメージが必要です。MNISTデータの画像サイズは28X28であるため、ここでは画像のサイズを変更しませんが、最初の線形レイヤーの入力フィーチャのサイズを変更します。

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        # 1 input image channel, 6 output channels, 5x5 square convolution
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # an affine operation: y = Wx + b
        self.fc1 = nn.Linear(16 * 4 * 4, 120)  # 4*4 from image dimension
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # If the size is a square, you can specify with a single number
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        # x = F.relu(self.conv2(x))

        x = torch.flatten(x, 1) # flatten all dimensions except the batch dimension
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        x = F.log_softmax(x, dim=1) # 计算log(softmax(x))
        return x

トレーニングとテスト

ここではCPUトレーニングを使用しており、GPUを使用した場合の速度が速くなります。

#定义超参数
BATCH_SIZE=512 
EPOCHS=20 # 总共训练批次
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") # 让torch判断是否使用GPU,建议使用GPU环境

#声明一个网络
model = Net()
#采用Adam优化器
optimizer = optim.Adam(model.parameters())


#开始训练
for epoch in range(1, EPOCHS + 1):
    # 训练
    model.train()
    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)
        optimizer.zero_grad()
        output = model(data)
        loss = F.nll_loss(output, target)
        loss.backward()
        optimizer.step()
        if(batch_idx+1)%30 == 0:
            print('Train Epoch: {
    
    } [{
    
    }/{
    
    } ({
    
    :.0f}%)]\tLoss: {
    
    :.6f}'.format(
                epoch, batch_idx * len(data), len(train_loader.dataset),
                100. * batch_idx / len(train_loader), loss.item()))

    # 测试
    model.eval()
    test_loss = 0
    correct = 0
    with torch.no_grad():
        for data, target in test_loader:
            data, target = data.to(device), target.to(device)
            output = model(data)
            test_loss += F.nll_loss(output, target, reduction='sum').item() # 将一批的损失相加
            pred = output.max(1, keepdim=True)[1] # 找到概率最大的下标
            correct += pred.eq(target.view_as(pred)).sum().item()

    test_loss /= len(test_loader.dataset)
    print('\nTest set: Average loss: {
    
    :.4f}, Accuracy: {
    
    }/{
    
    } ({
    
    :.0f}%)\n'.format(
        test_loss, correct, len(test_loader.dataset),
        100. * correct / len(test_loader.dataset)))

トレーニング結果
トレインエポック:1 [14848/60000(25%)]ロス:0.796161
トレインエポック:1 [30208/60000(50%)]ロス:0.382039
トレインエポック:1 [45568/60000(75%)]ロス:0.258347

テストセット:平均損失:0.2065、精度:9400/10000(94%)

トレインエポック:2 [14848/60000(25%)]ロス:0.203479
トレインエポック:2 [30208/60000(50%)]ロス:0.107671
トレインエポック:2 [45568/60000(75%)]ロス:0.143290

テストセット:平均損失:0.1203、精度:9635/10000(96%)

トレインエポック:3 [14848/60000(25%)]ロス:0.130832
トレインエポック:3 [30208/60000(50%)]ロス:0.093064
トレインエポック:3 [45568/60000(75%)]ロス:0.097940

テストセット:平均損失:0.0878、精度:9731/10000(97%)

列車エポック:4 [14848/60000(25%)]損失:0.079764
列車エポック:4 [30208/60000(50%)]損失:0.092091
列車エポック:4 [45568/60000(75%)]損失:0.083679

テストセット:平均損失:0.0798、精度:9744/10000(97%)

列車エポック:5 [14848/60000(25%)]損失:0.081892
列車エポック:5 [30208/60000(50%)]損失:0.083289
列車エポック:5 [45568/60000(75%)]損失:0.068377

テストセット:平均損失:0.0642、精度:9789/10000(98%)

列車エポック:6 [14848/60000(25%)]損失:0.066107
列車エポック:6 [30208/60000(50%)]損失:0.089498
列車エポック:6 [45568/60000(75%)]損失:0.042199

テストセット:平均損失:0.0565、精度:9812/10000(98%)

列車エポック:7 [14848/60000(25%)]損失:0.043734
列車エポック:7 [30208/60000(50%)]損失:0.078332
列車エポック:7 [45568/60000(75%)]損失:0.054749

テストセット:平均損失:0.0545、精度:9827/10000(98%)

列車エポック:8 [14848/60000(25%)]損失:0.039079
列車エポック:8 [30208/60000(50%)]損失:0.057117
列車エポック:8 [45568/60000(75%)]損失:0.062051

テストセット:平均損失:0.0497、精度:9841/10000(98%)

列車エポック:9 [14848/60000(25%)]損失:0.087467
列車エポック:9 [30208/60000(50%)]損失:0.055735
列車エポック:9 [45568/60000(75%)]損失:0.030613

テストセット:平均損失:0.0450、精度:9853/10000(99%)

トレインエポック:10 [14848/60000(25%)]ロス:0.053619
トレインエポック:10 [30208/60000(50%)]ロス:0.048457
トレインエポック:10 [45568/60000(75%)]ロス:0.050112

テストセット:平均損失:0.0461、精度:9851/10000(99%)

列車エポック:11 [14848/60000(25%)]損失:0.026218
列車エポック:11 [30208/60000(50%)]損失:0.044744
列車エポック:11 [45568/60000(75%)]損失:0.044205

テストセット:平均損失:0.0429、精度:9860/1000(99%)

列車エポック:12 [14848/60000(25%)]損失:0.038024
列車エポック:12 [30208/60000(50%)]損失:0.032498
列車エポック:12 [45568/60000(75%)]損失:0.047964

テストセット:平均損失:0.0445、精度:9848/10000(98%)

列車エポック:13 [14848/60000(25%)]損失:0.027184
列車エポック:13 [30208/60000(50%)]損失:0.015675
列車エポック:13 [45568/60000(75%)]損失:0.021164

テストセット:平均損失:0.0434、精度:9858/10000(99%)

列車エポック:14 [14848/60000(25%)]損失:0.010554
列車エポック:14 [30208/60000(50%)]損失:0.050443
列車エポック:14 [45568/60000(75%)]損失:0.018514

テストセット:平均損失:0.0406、精度:9868/10000(99%)

列車エポック:15 [14848/60000(25%)]損失:0.019876
列車エポック:15 [30208/60000(50%)]損失:0.028926
列車エポック:15 [45568/60000(75%)]損失:0.062516

テストセット:平均損失:0.0361、精度:9882/10000(99%)

列車エポック:16 [14848/60000(25%)]損失:0.009616
列車エポック:16 [30208/60000(50%)]損失:0.017137
列車エポック:16 [45568/60000(75%)]損失:0.034604

テストセット:平均損失:0.0346、精度:9881/10000(99%)

列車エポック:17 [14848/60000(25%)]損失:0.014641
列車エポック:17 [30208/60000(50%)]損失:0.034391
列車エポック:17 [45568/60000(75%)]損失:0.006974

テストセット:平均損失:0.0362、精度:9873/10000(99%)

列車エポック:18 [14848/60000(25%)]損失:0.014653
列車エポック:18 [30208/60000(50%)]損失:0.023054
列車エポック:18 [45568/60000(75%)]損失:0.008639

テストセット:平均損失:0.0369、精度:9880/1000(99%)

列車エポック:19 [14848/60000(25%)]損失:0.026135
列車エポック:19 [30208/60000(50%)]損失:0.028519
列車エポック:19 [45568/60000(75%)]損失:0.023374

テストセット:平均損失:0.0428、精度:9867/10000(99%)

列車エポック:20 [14848/60000(25%)]損失:0.012330
列車エポック:20 [30208/60000(50%)]損失:0.023574
列車エポック:20 [45568/60000(75%)]損失:0.030578

テストセット:平均損失:0.0480、精度:9852/10000(99%)

正解率99%

おすすめ

転載: blog.csdn.net/weixin_44901043/article/details/124022669