見出し画像

PyTorch深層学習⑫単純な画像分類2

前回は、単純な画像分類をMNISTデータセットを使って実装しました。今回は、この続きでニューラルネットワークに層を追加して効果を見る実験を行います。

前回に作成したJupyterノートブックの続きとして、いくつかのモデルの書き方のパターンを紹介します。

それでは、さっそく始めましょう。


前回のパターン

前回定義したモデルは、以下になります。

class ImageClassifier(nn.Module):
    
    def __init__(self):
        super().__init__()
        
        self.linear1 = nn.Linear(784, 128)
        self.linear2 = nn.Linear(128, 10)
        
    def forward(self, x):
        x = self.linear1(x)
        x = F.relu(x)
        x = self.linear2(x)
        return x

このモデルによる平均正解率は95.96%でした。

パターン1

一つ層を増やします。

class DeepImageClassifier1(nn.Module):
    
    def __init__(self):
        super().__init__()
        
        self.linear1 = nn.Linear(784, 128)
        self.linear2 = nn.Linear(128, 64)
        self.linear3 = nn.Linear(64, 10)
        
    def forward(self, x):
        x = self.linear1(x)
        x = F.relu(x)
        x = self.linear2(x)
        x = F.relu(x)
        x = self.linear3(x)
        return x


torch.manual_seed(123)
deep_model1 = DeepImageClassifier1()
deep_model1.to(device)

train_model(deep_model1, device)

平均正解率は96.39%となり、少し良くなりました。

エポック= 0 平均損失値= 0.70 平均正解率= 90.90%
エポック= 1 平均損失値= 0.30 平均正解率= 92.71%
エポック= 2 平均損失値= 0.25 平均正解率= 93.47%
エポック= 3 平均損失値= 0.22 平均正解率= 94.27%
エポック= 4 平均損失値= 0.19 平均正解率= 94.60%
エポック= 5 平均損失値= 0.17 平均正解率= 95.14%
エポック= 6 平均損失値= 0.16 平均正解率= 95.67%
エポック= 7 平均損失値= 0.14 平均正解率= 95.74%
エポック= 8 平均損失値= 0.13 平均正解率= 95.98%
エポック= 9 平均損失値= 0.12 平均正解率= 96.39%

以後、乱数シードは常に123に固定して平均正解率を比較しています。

パターン2

では、ちょっと書き方を変えてみます。層を別々に定義するのではなく、nn.Sequential を使ってリストのようにまとめました。

class DeepImageClassifier2(nn.Module):
    
    def __init__(self):
        super().__init__()
        
        self.network = nn.Sequential(
            nn.Linear(784, 128),
            nn.ReLU(),
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Linear(64, 10)
        )
        
    def forward(self, x):
        x = self.network(x)
        return x


torch.manual_seed(123)
deep_model2 = DeepImageClassifier2()
deep_model2.to(device)

train_model(deep_model2, device)

実装の仕方は異なりますが、中身は一緒なので結果も同じです。

エポック= 0 平均損失値= 0.70 平均正解率= 90.90%
エポック= 1 平均損失値= 0.30 平均正解率= 92.71%
エポック= 2 平均損失値= 0.25 平均正解率= 93.47%
エポック= 3 平均損失値= 0.22 平均正解率= 94.27%
エポック= 4 平均損失値= 0.19 平均正解率= 94.60%
エポック= 5 平均損失値= 0.17 平均正解率= 95.14%
エポック= 6 平均損失値= 0.16 平均正解率= 95.67%
エポック= 7 平均損失値= 0.14 平均正解率= 95.74%
エポック= 8 平均損失値= 0.13 平均正解率= 95.98%
エポック= 9 平均損失値= 0.12 平均正解率= 96.39%

パターン3

次のパターンでは、nn.Sequential をベースのクラスとして継承して使っています。よって親クラスの初期化を呼び出す際に、全ての層のリストを渡しています。

class DeepImageClassifier3(nn.Sequential):
    
    def __init__(self):
        super().__init__(
            nn.Linear(784, 128),
            nn.ReLU(),
            nn.Linear(128, 64),
            nn.ReLU(),
            nn.Linear(64, 10)
        )


torch.manual_seed(123)
deep_model3 = DeepImageClassifier3()
deep_model3.to(device)

train_model(deep_model3, device)

これも、実装の仕方は異なりますが、中身は一緒なので結果も同じです。

エポック= 0 平均損失値= 0.70 平均正解率= 90.90%
エポック= 1 平均損失値= 0.30 平均正解率= 92.71%
エポック= 2 平均損失値= 0.25 平均正解率= 93.47%
エポック= 3 平均損失値= 0.22 平均正解率= 94.27%
エポック= 4 平均損失値= 0.19 平均正解率= 94.60%
エポック= 5 平均損失値= 0.17 平均正解率= 95.14%
エポック= 6 平均損失値= 0.16 平均正解率= 95.67%
エポック= 7 平均損失値= 0.14 平均正解率= 95.74%
エポック= 8 平均損失値= 0.13 平均正解率= 95.98%
エポック= 9 平均損失値= 0.12 平均正解率= 96.39%

パターン4

次のパターンは、nn.Sequential を直接作成する方法です。ここでは、モデルクラスの定義を別に行う必要がありません。

torch.manual_seed(123)

deep_model4 = nn.Sequential(
    nn.Linear(784, 128),
    nn.ReLU(),
    nn.Linear(128, 64),
    nn.ReLU(),
    nn.Linear(64, 10)
)

deep_model4.to(device)

train_model(deep_model4, device)

注意点としては、シード固定をモデルが生成される前に行なっていることです。モデル(この場合は、nn.Sequential)が生成されるときにパラメータの値がランダムに設定されるので、その前にシードを固定する必要があるからです。

ここでも結果は同じになります。

エポック= 0 平均損失値= 0.70 平均正解率= 90.90%
エポック= 1 平均損失値= 0.30 平均正解率= 92.71%
エポック= 2 平均損失値= 0.25 平均正解率= 93.47%
エポック= 3 平均損失値= 0.22 平均正解率= 94.27%
エポック= 4 平均損失値= 0.19 平均正解率= 94.60%
エポック= 5 平均損失値= 0.17 平均正解率= 95.14%
エポック= 6 平均損失値= 0.16 平均正解率= 95.67%
エポック= 7 平均損失値= 0.14 平均正解率= 95.74%
エポック= 8 平均損失値= 0.13 平均正解率= 95.98%
エポック= 9 平均損失値= 0.12 平均正解率= 96.39%

以上、モデルの定義・作成におけるいくつかのパターンを紹介しました。より複雑なモデルでは、上記のいくつかのパターンを組み合わせた定義の仕方を使うことがありますが、一つ一つ分解してみると大体どれかのパターンに当てはまります。

もちろん違いタイプの層(畳み込み層、再帰層、アテンション層)や様々な活性化関数など細かいバリエーションはたくさんありますが。

パターン5

層を増やして、4つにしました。

torch.manual_seed(123)

deep_model5 = nn.Sequential(
    nn.Linear(784, 128),
    nn.ReLU(),
    nn.Linear(128, 128),
    nn.ReLU(),
    nn.Linear(128, 64),
    nn.ReLU(),
    nn.Linear(64, 10)
)

deep_model5.to(device)

train_model(deep_model5, device)

平均正解率もちょっと良くなっています。

エポック= 0 平均損失値= 0.69 平均正解率= 90.64%
エポック= 1 平均損失値= 0.30 平均正解率= 92.70%
エポック= 2 平均損失値= 0.24 平均正解率= 93.59%
エポック= 3 平均損失値= 0.20 平均正解率= 94.54%
エポック= 4 平均損失値= 0.18 平均正解率= 95.19%
エポック= 5 平均損失値= 0.15 平均正解率= 95.44%
エポック= 6 平均損失値= 0.14 平均正解率= 95.91%
エポック= 7 平均損失値= 0.12 平均正解率= 96.09%
エポック= 8 平均損失値= 0.11 平均正解率= 96.60%
エポック= 9 平均損失値= 0.10 平均正解率= 96.63%

もちろん、層を増やせば必ず精度が上がるとは限りません。訓練用データに過剰適合してしまい、テストセットにおける評価(平均正解率)が悪くなる可能性があります。

また、層を増やすと訓練するのにより多くのエポックを必要とする傾向があるので10エポックでは足りないかもしれません。いろいろと実験してみることを勧めます。

次回予告

次回は、畳み込み層について解説します。

お楽しみに!

いいなと思ったら応援しよう!