深層学習　画像認識3　モデル作成後

[Aidemy](https://aidemy.net/)　2020/11/10
#はじめに
　こんにちは、んがょぺです！バリバリの文系ですが、AIの可能性に興味を持ったのがきっかけで、AI特化型スクール「Aidemy」に通い、勉強しています。ここで得られた知識を皆さんと共有したいと思い、Qiitaでまとめています。以前のまとめ記事も多くの方に読んでいただけてとても嬉しいです。ありがとうございます！
　今回は、深層学習・画像認識の三つ目の投稿になります。どうぞよろしくお願いします。

＊本記事は「Aidemy」での学習内容を「自分の言葉で」まとめたものになります。表現の間違いや勘違いを含む可能性があります。ご了承ください。

今回学ぶこと
・Kerasの便利な機能
・モデルの精度を上げる手法について

#便利な機能
##学習過程の表示
・学習を進める中で、__精度がどのように変化したのかを視覚化する方法__がある。例えば変数「history」に「model.fit()」を格納したとすると、__「history.history['acc']」__で精度の変化を得ることができる。あとはこれを__「plt.plot()」__すれば可視化できる。

・また、前のChapterでは汎化精度の計算を__「model.evaluate(X_test,y_test)」__で行っていたが、「model.fit()」の引数に__「validation_data=(X_test,y_test)」__を追加することで、同様に__汎化精度を計算してくれる__。
・同様に、汎化精度の変化を取得するときは__「history.history['val_acc']」__で行い、可視化すると良い。

・コード![スクリーンショット 2020-11-09 16.39.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/6865a878-5afe-94ef-79b2-be27e002b530.png)


・結果![スクリーンショット 2020-11-09 16.39.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/e1669f65-d751-4b17-4a83-d54edadfa214.png)

##Early Stopping
・学習回数が多すぎても、一定のところを超えると精度が落ちていく。このような場合は__学習を早めに打ち切る__ことが大切である。このようなときに使えるのが__「Early Stopping」__である。
・Early Stoppingは、学習用、テスト用データとは別に検証用データを持っておき、学習ごとにそのデータの評価と学習データの評価の誤差をとり、誤差が広がってきたタイミングで学習をストップするというものである。
・コードとしては、まず__「es=EarlyStopping()」__としてインスタンスを作成する。あとはmodel.fit()の引数に__「callbacks=[es]」__というようにするだけでよい。
・インスタンスの引数としては__「monitor」__で何を評価の誤差として監視するかを指定し、__「patience」__でその監視している値が何エポック改善されなかったら学習を打ち切るかを指定、__「mode」__には「モデルの改善」は指定した値が「増加」したら改善なのか、「減少」したら改善なのかを、それぞれ__「'max'」「'min'」__で指定する。これを__「'auto'」__としたときは、自動で推測してくれる。

##モデル構造の出力
・モデルの構造を確認したいときは、これを__画像で出力する__手法がある。方法は__「plot_model(model, to_file='model.png')」__というようにするだけである。
・また、各層ごとに名前を設定したい場合は、__「model.add()」__で層を以下するときに、引数に__「name」__を加えれば良い。

・コード

・結果

#精度を上げる方法
##最適化
・__学習率は、学習が進むにつれて変化させる__ほうがうまく学習できることが多い。このことを__「学習率の最適化」__といい、__Adam、RMSprop、Adagrad__などが使われる。

##ドロップアウト
・これまでにも何度も出てきているが、過学習を防ぎ、精度を上げるのに使われる手法としては__ドロップアウト__が挙げられる。これは、ランダムでデータを除去することで汎化されやすくする手法である。

##ファインチューニング（転移学習）
・ファインチューニング__（転移学習）__は以前にも学習しているが、__他のモデルの一部を使用__して学習させる手法である。画像認識で言えば、最後の全結合層だけを変更し、畳み込み層はそのまま使用する。
・画像認識のモデルとしては、Kerasでは__「Xception、VGG16、VGG19、ResNet50、InceptionV3」__の5つの画像分類モデルを、__ImageNet__で学習した重みをダウンロードして使うことができる。以下では__VGG16__のモデルを作った例を記載する。

![スクリーンショット 2020-11-09 18.19.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/d28ebfa7-3eb2-9df1-de6f-fef8b4a5d91b.png)

・以上のコードについて、まずは__「input_tensor」__で入力の形を与える。これを定義したら、実際にVGGのモデルを作成する__。「VGG16()」__で作成することができる。引数としては、__「include_top」__で元のモデルの全結合層を使用するかをTrueorFalseで指定し、__「weights='imagenet'」__でimagenetで学習した重みを使用するように指定、__「input_tensor」__で先ほど定義した入力の形を記載する。

・ここまで行ったら、次は出力層（全結合層）付近のモデル__（top_model）__を別に作成していく。top_modelの入力層は、VGGモデル（畳み込み層）の出力を受け取るので、__「Flatten()」__とする。input_shapeは__「vgg16.output_shape[1:]」__とすることで、VGGモデルの出力の形（二次元）を取得できる。
・あとは普通のモデルと同様に層を追加すれば良い。出力層まで追加したら、次は__「入力はvgg16.input、出力はtop_modelにvggの出力を入れたもの」__とする最終的なモデルを作成する。

![スクリーンショット 2020-11-09 18.44.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/28743fd1-2f2b-3efc-290a-55ffdd49b1f8.png)

・以上で層の追加は終わりで、ここからはコンパイルと学習を行っていくが、その前に、__VGGモデル部分の重みは変更されないように設定しておく__。

![スクリーンショット 2020-11-09 18.44.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698700/986a5104-f83f-d6a1-572c-2a120dd83fb5.png)

・コンパイルと学習には特に変更点はない。一点だけ、転移学習を行うときは最適化関数は__「SGD」__にすると良い。

#まとめ
・学習の精度は__「history['acc']」__を__「plt.plot()」__することで可視化できる。
・model.evaluate()を使わずとも、model,fit()に__「validation_data」__を設定することでモデルの__汎化精度を計算__してくれる。
・EarlyStoppingを使う時は、インスタンスを作成してから、model.fit()の引数__「callbacks」__でそれを指定すれば良い。
・モデル構造を画像として可視化したい時は、__「plot_model(model,to_file)」__で行える。
・精度を上げる方法としては、最適化やドロップアウトがあるほか、__転移学習__を行うこともある。例えば画像認識だったら、畳み込み層は__VGG16__で転移させ、出力層付近のモデルは自分で実装して、結合することで全体のモデルを実装する。

今回は以上です。最後まで読んでいただき、ありがとうございました。