D2C

内定者インターンを終えて—プログラミング未経験者がPyTorchで画像分類するまでにやったこと—

1. はじめに

<自己紹介>

19年4月よりビジネスエンジニアリング(BE)部DSチームに加わることになりました上野です。 大学院では生物学を専攻しており、発生学や病理学について研究していました 。在学中はマウスの飼育や解剖に追われる日々を過ごしており、当然機械学習のきの字も知りませんでした笑。 休日は読書や山登りをする普通の大学院生です。 私がD2Cを就職先に選んだのは、様々な顧客情報を持つインターネット広告企業だったからです。さらにいうと、ビッグデータやAI・機械学習などがバズワードとして扱われる中で、解析可能なビッグデータを自社に持ち、解析結果が事業に素早く展開できるD2Cは、バズワードをバズワードで終わらせない自力のある会社だと思ったからです。 加えて、職場の雰囲気の良さも決め手です!BE部は良い意味で研究室らしく、特に理系の人はすぐ馴染めると思います。 縁があってD2Cに入社となりましたが、自分は機械学習がなんたるかその基礎となる数学やプログラミングに対する知識までほぼありません。つまり素人です笑 やはり4月からいきなり仕事を始めるには不安が…と思っていたところ、BE部のDSチームから内定者アルバイトの誘いを受け、10月から約半年週1日のペースでインターンに参加しました! 本記事がプログラミング初心者や機械学習、特にPyTorchの入門記事として役立つと幸いです。

2. 環境構築とプログラミング入門

機械学習に取り組むに当たって、まずは解析環境を整えなければなりません。 情報系やプログラミングに取り組んできた人にはなんの苦労もないと思いますが、正直ここが一番面倒でした。 最初から心が折れそうでしたが、先輩社員が忙しい中であっても作業の手を止めて丁寧に説明をしてくれたのはとてもとても助かりました。

<環境構築>

やったこと
  • AWS EC2サーバーを立てる。
  • anacondaでPython・PyTorchを導入。jupyter notebook で解析。
AWS(Amazon Web Service) EC2 とは?
Amazon Elastic Compute Cloud (Amazon EC2) は、安全でサイズ変更可能なコンピューティング性能をクラウド内で提供するウェブサービスです。ウェブスケールのクラウドコンピューティングを開発者が簡単に利用できるよう設計されています。 公式ホームページより

つまり非常に簡単にクラウドサーバーを立てられるサービスです。機械学習において演算速度に関わる、CPUやGPUの性能を簡単に変更できます。 今回は、p2.xlargeあるいはp3.2xlargeをインスタンスとして選択しました。 jupyter notebook とは?
The Jupyter Notebook is an open-source web application that allows you to create and share documents that contain live code, equations, visualizations and narrative text. Uses include: data cleaning and transformation, numerical simulation, statistical modeling, data visualization, machine learning, and much more. 公式ホームページより
この公式ホームページの文言通り、ノートブックと呼ばれるファイルにプログラムや説明の文章、実行結果などをまとめて管理できる、データ分析用のツールです。「ジュパイター ノートブック」または「ジュピター ノートブック」と読みます。 インストールは、Anacondaという開発環境のパッケージを利用すると、Jupyter Notebookと共に、データ分析やグラフ描画など、Pythonでよく利用されるライブラリをまとめてインストールできるので便利です。
(https://qiita.com/mzmiyabi/items/b1677e66474933d9a6fc)

<Python & SQL入門>

やったこと(自習)
  • Python
    • みんなのPythonを読む
      Pythonの入門書として有名です。プログラミング初心者にも非常にわかりやすく、この本から勉強を始めたおかげでスムーズにPythonに親しむことができました。¥3,000くらい。
    • SOLOLEARN Pythonコースを受講(無料)
      穴埋め&選択で簡単にPythonの基礎を学べます。アプリ版もあり、スキマ時間で手軽に勉強できます。
    • Python Exercises, Practice, Solutionを解く Pythonの文字列、リスト、辞書、クラス、正規表現等のトピック毎の問題が豊富に揃っています。各トピックの基礎固めには最適です。ちなみにNumpyやPandasの問題もあります。
  • SQL
    • D2C社内の実データで演習
      簡単な集計作業でしたがレコード数が多いため、検索クエリ等の工夫を必要とされ実用的な学びが得られました。
    • SQLZOOで演習
      SQLのチュートリアル問題がたくさん用意されており、ブラウザだけでSQL問題を解きながら学ぶことができます。

3. PyTorch入門

ここに到達するまでに約1か月かかり、いよいよ機械学習できる!と思っていましたが「PyTorchで実装することになるので勉強しといて」と言われ、新しいライブライリついて勉強し始めました。チュートリアルや情報ブログが英語で書かれているものが多く、英語を真面目に勉強してこなかったことをとても後悔しました…。学生の皆さんは英語を真面目に勉強しておくことをオススメします。 PyTorchとは? ディープラーニングを実装する際にはディープラーニング用のライブラリを使用するのが一般的です。ライブラリとしてはCaffe、TensorFlow、Keras、Chainerなどが有名です。
PyTorchはこれらのライブラリよりも後発で、最近生まれたディープラーニング用ライブラリです。特徴として以下があげられます。
  • Chainerからフォークされて作られている。思想はChainerを引き継いでいる
  • GPUでの計算も楽に行える
  • Define by Run
  • コミュニティが活発で、後発にもかかわらず急速に発達
  • 最新の論文実装によく用いられる
    特に論文を手元で実装して実験したい人にお勧めのライブラリです。インストールはこちからから

<公式ドキュメントによるPyTorch入門>

やったこと 公式ホームページにあるチュートリアルがとても優れているのでこれで勉強を始めました。案内がありますが、 60-minute blitz コースから始めると良いです。

<pretrain modelを用いた画像分類>

やったこと
  • PyTorch torchvisionに用意されたモデル用いて、データセットCIFAR-10の画像分類を行う
    • 学習済みモデルはPyTorchの画像向けパッケージとなるtorchvisionでサポートされており、これらのモデルをファインチューニングして学習を行いました。
    • ファインチューニングでは、ニューラルネットを学習するために、別の問題、別のデータセットで学習済みのモデルのパラメータをコピーして、それを新しいニューラルネットのパラメータの初期値として使います。典型的なケースとして、一般物体認識のデータセットであるImageNetで学習したネットワークを物体検出やSemantic Segmentationといった別の問題に使用するといった例があります。 一般的にDeep Learningでは大量の学習データが必要とされていますが、あらかじめ(大量のデータで)学習したモデルを初期値として使いファインチューニングすることで、実際に解きたい問題に関するデータの量が不十分でも十分な性能を達成できる場合があります。また、学習にかかる時間を短縮する効果もあります。つまり、リソースや経験の少ない初心者には打って付けの学習方法になります。 torchvisionで最初から扱えるモデルは以下 参考
  • VGG
  • ResNet
  • SqueezeNet
  • DenseNet
  • Inception v3
  • PyTorchのpretrainモデルを使う場合のサポートpackageを使う
    この分野はものすごいスピードで他の高精度モデルや、仕組みの違う学習済みモデルが出てきているので、PyTorchのpretrainモデルを使う場合のサポートpackageを使うと良さそうです。
    今回は(https://github.com/creafz/PyTorch-cnn-finetune) を使用しました。インストールはpipで簡単にできます。
このpachageで簡単に以下のモデルが追加で使えるようになります。
  • ResNeXt
  • NASNet-A Large
  • NASNet-A Mobile
  • Inception-ResNet v2
  • Dual Path Networks
  • Inception v4
  • Xception
  • Squeeze-and-Excitation Networks
  • PNASNet-5-Large
  • PolyNet
個々のモデルの精度については以下の通りです。 imagenetでの精度比較表 参考
ModelVersionAcc@1Acc@5
PNASNet-5-LargeOur porting82.73695.992
NASNet-A-LargeOur porting82.56696.086
SENet154Our porting81.30495.498
PolyNetOur porting81.00295.624
SE-ResNeXt101_32x4dOur porting80.23695.028
InceptionResNetV2Our porting80.1795.234
InceptionV4Our porting80.06294.926
DualPathNet107_5kOur porting79.74694.684
ResNeXt101_64x4dTorch779.694.7
DualPathNet131Our porting79.43294.574
DualPathNet92_5kOur porting79.494.62
DualPathNet98Our porting79.22494.488
SE-ResNeXt50_32x4dOur porting79.07694.434
XceptionKeras7994.5
ResNeXt101_64x4dOur porting78.95694.252
XceptionOur porting78.88894.292
ResNeXt101_32x4dTorch778.894.4
SE-ResNet152Our porting78.65894.374
ResNet152PyTorch78.42894.11
SE-ResNet101Our porting78.39694.258
SE-ResNet101Caffe78.2594.28
ResNeXt101_32x4dOur porting78.18893.886
FBResNet152Torch777.8493.84
SE-ResNet50Our porting77.63693.752
DenseNet161PyTorch77.5693.798
ResNet101PyTorch77.43893.672
FBResNet152Our porting77.38693.594
InceptionV3PyTorch77.29493.454
DenseNet201PyTorch77.15293.548
DualPathNet68b_5kOur porting77.03493.59
CaffeResnet101Our porting76.292.766
DenseNet169PyTorch76.02692.992
ResNet50PyTorch76.00292.98
DualPathNet68Our porting75.86892.774
DenseNet121PyTorch74.64692.136
VGG19_BNPyTorch74.26692.066
NASNet-A-MobileOur porting74.0891.74
ResNet34PyTorch73.55491.456
BNInceptionOur porting73.52491.562
VGG16_BNPyTorch73.51891.608
VGG19PyTorch72.0890.822
VGG16PyTorch71.63690.354
VGG13_BNPyTorch71.50890.494
VGG11_BNPyTorch70.45289.818
ResNet18PyTorch70.14289.274
VGG13PyTorch69.66289.264
VGG11PyTorch68.9788.746
SqueezeNet1_1PyTorch58.2580.8
SqueezeNet1_0PyTorch58.10880.428
AlexnetPyTorch56.43279.194

4. RICAPを用いた画像分類

やったこと 今回のインターンの仕上げとして、以下の2つを目標に検討を行いました。
  1. Data Augmentation の一つであるRICAP導入による汎化性能向上
  2. 新たなoptimizer、AdaBoundによる学習速度および精度の向上
これらに取り組んだ理由として、画像分類の評価には巨大かつラベル間の違いが明瞭なデータセットが長年用いられており、実際のタスクに応用可能とは言い難い点があげられるからです。実際、SOTAな精度を誇るモデルのいくつかはCIFARやImagenetなどのデータセットに overfit してる危険性も指摘されています。

arXiv2018 Do CIFAR-10 Classifiers Generalize to CIFAR-10?

<検討したこと>

さっそく具体的な手法の説明に入ります。自分なりに解釈した内容を示しますが、初心者ゆえ間違っている部分も多々あると思いますので参考程度に。
元論文はリンクで紹介していますので、そちらを読んで頂けると幸いです。 RICAP 2018年にarXivに投稿された論文「Data Augmentation using Random Image Cropping and Patching for Deep CNNs」において、CNNの新しいdata augmentation手法として提唱された RICAP (Random Image Cropping And Patching)を試してみました。
シンプルな手法ですがCIFAR-10でSOTAなエラー率2.19%を達成しています。

手法について少し詳しく見ていきましょう。
Modified from Data Augmentation using Random Image Cropping and Patching for Deep CNNs まず、学習セットから4つの画像をランダムに選択します。

次に各画像からクロップするサイズを求めるために、以下の式のようにして上図の(w,h)をベータ分布 $Beta(β,β)$ からランダムに決定します。 $$\begin{array} { l l } { w = \operatorname { round } \left( w ^ { \prime } I _ { x } \right) , } & { h = \operatorname { round } \left( h ^ { \prime } I _ { y } \right) } \ { w ^ { \prime } \sim \operatorname { Beta } ( \beta , \beta ) , } & { h ^ { \prime } \sim \operatorname { Beta } ( \beta , \beta ) } \end{array}$$ $I _ { x }, I _ { y }$ はそれぞれオリジナルの学習画像の幅と高さ。$β$ はハイパーパラメータです。 ベータ分布 $Beta(β,β)$ は、ベータの値によって以下のように分布が変化します。(つまり値が小さくなるほど画像の端に近い場所が選ばれるようになります) ベータ分布 $Beta(β,β), β=[0.1, 0.3, 0.6, 1.0]$ CIFAR-10では$β=0.3$が最適とされており、この記事でも$β=0.3$としています。

また、4つの画像のサイズ $(w _ { k }, h _ { k })$ は $(w,h)$ から自動的に求まります。 $$(w_1,h_1)=(w,h),\hspace{5pt} (w_2,h_2)=(I_x-w,h),\hspace{5pt}$$
$$(w_3,h_3)=(w,I_y-h),\hspace{5pt}(w_4,h_4)=(I_x-w,I_y-h) $$ そして、各画像のどの部分をクロップするか決定するために、クロップする画像領域の左上の位置 $(x _ { k }, y _ { k })$ を以下の式のように一様分布からランダムに求めます。 $${x_k \sim U(0,I_x-w_k),\hspace{5pt} y_k \sim U(0,I_y-h_k) }$$ 最後に、生成した画像のラベルを求めます。各画像のラベルをそれぞれが生成画像に対して占める面積の割合で混ぜ合わせたものが生成画像のラベルになります。 $${c = \sum_{k\in{1,2,3,4}} W_k c_k \hspace{5pt} \text{for} \hspace{5pt} W_k = \frac{w_k h_k}{I_x I_y} }$$ AdaBound

深層学習で主に用いられているoptimizer(SGD, Adam)に加え、 ICLR 2019に採択された「ADAPTIVE GRADIENT METHODS WITH DYNAMIC BOUND OF LEARNING RATE」において提唱された、AdaBoundについても検討を行いました。
こちらの記事に非常に良くまとまっていますが、これも自分なりに解釈したものを。

(勾配法について復習したい方はこのあたり1, 2が参考になると思います) AdaBoundとは、Adamの学習初期の学習の速さとSGDの汎化能力を組み合わせたような最適化手法学習前半はAdamのように動き、学習後半からはSGDのように動くもの
を目指して提案された手法です 勾配クリッピング(勾配爆発を防ぐために、勾配が閾値を超えないようにする手法)のアイデアを応用して使うので、Adamの学習率をクリッピングしたものがAdaBound だと考えれます。学習率は $n_l(t)$ を下限、 $n_u(t)$ を上限としてい以下のように定義されます。 $$\eta_{l}(t)=0.1-\frac{0.1}{(1-\beta_2)t+1},\;\eta_{u}(t)=0.1+\frac{0.1}{(1-\beta_2)t}$$

<方法>

モデル
画像分類を行うにあたりニューラルネットワークモデルである、resnet34、nasnetmobileを使用しました。それぞれ、論文掲載時点でCIFAR10等の画像分類タスクでSOTAなスコアを記録したモデルになります。 各モデルの概要
resnet34
arXiv(2015) Residual Network(ResNet)という名のとおり、残差を用いたニューラルネットワーク。ネットワークを深くすると精度が悪化する問題に対して、ネットワークが残差関数を学習するよう再構成したモデルです。
nasnetmobile
arXiv(2016) 「Neural Architecture Search with Reinforcement Learning」で提唱されているNeural Architecture Searchを用いて、ニューラルネットワークの最適な設計を強化学習で行った結果作成されたネットワークの軽量版です。 Dataset
分類を行う画像データセットとしてkaggle dataset上で公開されているFlowers Recognitionを使用しました。本データセットは4326枚の画像で構成され、chamomile、 tulip、 rose、 sunflower、 dandelion の5種類の花の画像が約800枚ずつ含まれています。また画像の大きさはさまざまで、約 320×240 pixelsとなっています。以下にResizeした画像を示します。
学習条件
モデルの学習は3つのoptimizer、RICAPの有り無し全6パターンについて検討しました。 Epoch : 200 Date Augmentation: PyTorchのtorchvision.transforms に含まれるメソッドを使用しました。
  • Resize : [224 x 224]
  • RandomHorizontalFlip
  • Normalize
  • RICAP(上述した内容を実装)あり or なし

Loss : Cross Entorpy

Optimizer : SGD、adamはutils.pyに自作した関数を用いて学習率(lr)を段階的に減少させました。
  • SGD (momentum=0.9, weight_decay=1e-4)
  • Adam
ModelSGDAdamlr 0 ~ 59lr 60 ~ 119lr 120 ~ 179lr 180 ~ 200
resnet340.10.020.0040.0008
resnet340.010.0050.00250.0008
nasnetmobile0.10.020.0040.0008
nasnetmobile0.010.0050.00250.0008
  • AdaBound : 論文に記載されたPyTorchでの実装をそのまま使用しました (lr = 0.0001, final_lr = 0.1)。

<結果>

上段が通常、下段がRICAPした画像で学習した結果になります。また、optimizerは左からSGD、Adam、AdaBoundです。

実験の結果、

– RICAPを用いることでModel, Optimizerによらず過学習が抑えられ、精度が上昇する – AdaBounについては精度の上昇にはつながらなったものの、学習早期に高い精度を獲得できる ことがわかりました。 resnet34 accuracy
loss
nasnetmobile
accuracy
loss
以下で今回の検証において最も精度の高かった nasnetmobile の confusion matrix を比較しました。
RICAPなしRICAPあり
test accuracy : 77 %test accuracy : 93%
グラフから tulip – rose 間で誤分類が多いことがわかります (花の形状が似ているからでしょうか?)。この傾向はRICAPによる精度上昇においても変化せず、RICAPはデータセット全体に対する識別力を上げたと考えられます。

<考察>

RICAPの導入により精度・汎化性能ともに上昇しているため、非常に有用なテクニックであることが明らかになりました。また今回は比較できませんでしたが、random crop, random erasingmixup など他の Data Argumentation 手法と比較して、画像データを失うことなく、画像をパッチした境界面以外不自然な画像でない点が優れていると感じました。 AdaBoundについては学習の速さが際立ち、モデル検討段階での試行錯誤に適している気がします。一方で今回は掲載していませんが、vgg16モデルにおいてadamとともに全く学習しないケースもあり(乱数シードに大きく左右されました)、モデルによって得手不得手があるようです。

5. まとめと感想

インターンの成果としてやってきたことをまとめる中で、改めて知識・経験不足を感じました。一方で、インターンをはじめたころの「なにがわからないのかわからない」状態から「これこれを勉強する必要があるな」と思えるようになったのは大きな成果だと思います。また、当初記事にする予定だったより高度な論文実装などやり残したことも多いので、入社してからも引き続きスキルアップして、本ブログの記事として紹介することでリベンジしようと思います! 最後にインターン期間中、先輩方のサポートによって充実した時間を過ごせました。改めて感謝します。 長くなりましたが、最後まで読んで頂きありがとうございます。


関連タグ