Re:ゼロから始めるML生活

どちらかといえばエミリア派です

EfficientNetを使ってみたメモ

f:id:nogawanogawa:20181029135436p:plain

普段あまり画像をデータを取り扱うことがないんですが、最近ちょっといじってたりします。

www.nogawanogawa.com

そんなことをやってるところに、何やらEfficientNetなどという代物があるということを見かけました。 更に調べてみると結構すごいやつということを知りました。 

qiita.com

というわけで、今回はそのEfficientNetについて勉強・触ってみたのでそのメモです。

元論文

元になった論文はこちら。 

arxiv.org

特徴

論文の詳細な解説はこちらの記事などで非常にわかりやすく書かれていますので、そちらを御覧ください。

qiita.com

EfficientNetの特徴をざっくりと紹介すると、

  • 画像認識においてのSoTA(2019年当時)
  • 一般にモデルを大きくすることで精度の向上を図るが、その際のネットワークの深さや広さ、解像度の適切な値に関してはわかっていないことが多かった
  • EfficientNetでは、これらの値について、Compound Coefficientと呼ばれる係数を導入することで最適なパラメータ数を決定し、それを用いることで小さなモデルで効率良く高い精度を達成する

というもののようです。

実際に使ってみた

今回もGPUが使いたいのでGoogle Colabを使ってやってみたいと思います。

基本的には前回のResNetとほぼコードは一緒です。 ネットワークサイズが大きくなってしまっている関係で、バッチサイズはResNetのときより小さくしています。

train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=8, shuffle=True) # もともと32
val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=8, shuffle=True) # もともと32

あとは、学習済みモデルはEfficientNetのb7を使用しています。 これは単純に論文上で一番精度が良いとされていたためで、それ以上の理由はありません。

from efficientnet_pytorch import EfficientNet

model_ft = EfficientNet.from_pretrained('efficientnet-b7')

num_ftrs = model_ft._fc.in_features # 最終層への入力の次元数
model_ft._fc = nn.Linear(num_ftrs, 35) #最終層の出力を35クラスに変更

実際に学習して、評価してみた結果がこちらです。 ちなみに5epochしか回していませんが、学習には30分かかりました。

              precision    recall  f1-score   support

           0       0.81      0.75      0.78        57
           1       0.82      0.79      0.80        67
           2       0.72      0.76      0.74        66
           3       0.89      0.95      0.92        61
           4       0.87      0.67      0.76        58
           5       0.88      0.83      0.85        70
           6       0.78      0.86      0.81        69
           7       0.93      0.91      0.92        56
           8       0.56      0.87      0.68        45
           9       0.82      0.79      0.80        62
          10       0.78      0.75      0.76        51
          11       0.95      0.83      0.89        66
          12       0.77      0.86      0.81       122
          13       0.87      0.88      0.88        69
          14       0.70      0.64      0.67        59
          15       0.85      0.75      0.80        60
          16       0.89      0.72      0.79        67
          17       0.83      0.91      0.87       133
          18       0.98      0.85      0.91        73
          19       0.57      0.96      0.71        54
          20       0.82      0.82      0.82        50
          21       0.98      0.95      0.97        60
          22       1.00      0.74      0.85        57
          23       0.98      0.79      0.87        62
          24       0.77      0.84      0.80        49
          25       0.90      0.90      0.90        58
          26       0.93      0.73      0.82        59
          27       0.95      0.97      0.96        58
          28       0.87      0.92      0.90        51
          29       0.80      0.91      0.85        57
          30       0.86      0.91      0.88        55
          31       0.72      0.90      0.80        59
          32       0.78      0.62      0.69        56
          33       0.89      0.82      0.85        50
          34       0.93      0.79      0.85        71

    accuracy                           0.83      2217
   macro avg       0.84      0.83      0.83      2217
weighted avg       0.84      0.83      0.83      2217

accuracyで言うと、ResNetのときより若干良くなりました。(0.82 -> 0.83)

期待したほど良くなってはいませんが、とりあえずやってみるだけなので、今回はこんなもんで良しとします。 多分、精度をあげようとした際にはもう少しちゃんとやらないといけないんでしょうが、ベースラインを作るというレベルならこれで十分かと。

書いたコード

一応、書いたコードはこちらです。 google colabのランタイムをGPUにすれば多分動くと思います。

参考文献

この記事を書くにあたって、下記の文献を参考にさせていただきました。

qiita.com

hampen2929.hatenablog.com

qiita.com

qiita.com

感想

最近は画像系もやってかないといけないなーと思って、やってみたって感じです。 やってみただけで使いこなせるわけではないので、いろいろ使いながら使い方を覚えていきたいと思います。