Deep Learning (CNN) による銀河形状分類(その2)

前回の記事の続き。

epochを重ねても訓練/テスト誤差が改善しないのはどうしてだろうか? この疑問に対して、色々と試した結果を以下にまとめている。

銀河イメージ

今回使用した、Galaxy10 DECals Datasetがどのようなデータかここで見てみたい。

# DataLoaderに格納されているイメージデータとラベルを表示
# 格納されているイメージデータは、正規化されている

import matplotlib.pyplot as plt

# 銀河形状名称(分類するクラス)
gala_classes = np.array(['Disturbed', 'Merging', 'Round Smooth', 'In-between RS', 'Cigar', 
             'Barred Spiral', 'Tight Spiral', 'Loose Spiral', 'Edge-on w/o Bulge', 'Edg-on w/t Bulge'])

n_img = 25  # 表示する画像数

gala_loader = DataLoader(train_dataset, batch_size=n_img, shuffle=True)
dataiter = iter(gala_loader)  # イタレータ
images, labels = next(dataiter)  # dataiter.next() はエラー

col = 5
row = (n_img + col -1)//col

plt.figure(figsize=(12,3*row))
for i in range(n_img):
    ax = plt.subplot(row, col, i+1)
    plt.imshow(np.transpose(images[i], (1, 2, 0)))  # チャネルを一番最後に変更
    ax.set_title(gala_classes[labels[i]])
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
plt.show()

前回、train_datasetとtest_datasetを得たCellの次において実行すると、次のようなイメージが得られる。

Galaxy_image

上記の形状のタイトルのデータセットの名称の通り、但し、表示のスペースの関係で一部略したが、各々の意味は次の通り。RS=Round Smooth、w/o=without、w/t=with。

人間でも中々識別出来ない。Galaxy Zooの活動に頭が下がる。

データに回転、左右反転を施す

銀河の傾きのバリエーションを増やすために、transformsでコメントアウトしていた2行を有効にした結果は、次の通り。

withRotate

まだ、訓練/テスト誤差はepochを重ねても横ばいのままで、改善は見られない。

学習率を変更

データに対し、更にランダムな切り抜き、ノイズ付加、情報損失等のデータ拡張を施すことも考えたが、その前に学習率を変更してみる。

次の通り、前回のコードの「訓練と評価関数群」の最初のセルを次の通り変更し、学習率を小さく設定。 そう言えば、情報源で上げたこの記事にも学習率は色々と試し、最終的に0.00001に決めたとの記載を思い出した。

# 損失関数の設定
criterion = nn.CrossEntropyLoss()

# 最適化手法を設定
optimizer = optim.Adam(model.parameters(), lr=0.00001)

LearningRate

今度は、epochを重ねると訓練/テスト誤差共に改善されていることが分かる。30回のエポックでは過学習の傾向も見られない。

30回のエポックに掛かった時間は2,786秒(46分26秒)であった。もうハーフやってみようか!

epoch60

60回のエポックに掛かった時間は5,574秒(92分54秒)であった。

epochが50数回を過ぎたあたりから、過学習の傾向が出始めているようにも見える。

VGG16のまとめ

VGG16の場合、学習率$lr$を$0.00001$とすることが、一番のポイントで、50回程度のエポックで損失値$0.02$程度であった。

次回は、モデルとしてResNetを使って試してみる。