
馬とシマウマの判別器をつくってみた!
こんにちは!アイデミーの渡部です!
今回の「やってみた!」では、ディープラーニングで画像判別器を製作したいと思います!
(実は、1年半くらい前に、グラスの分類器を作ったことがあります。その時の精度は、80%ギリギリ行かなかったくらいでした。。前回の記事はこちら)
さて、今回のテーマですが、題名にもある通り、「馬」と「シマウマ」の判別器をつくってみた!というのをやります!巷で有名なお題として、kaggleの犬と猫の判別があるんですが、それと同じくらい似ている動物を分類できるのか試してみます!精度は、前回よりも高いものを作ります!分類器がシマシマをうまく判別できるかどうか楽しみです!
また、今回は久しぶりにPythonを触るということもあり、一旦、最後までやってみて、その後、精度を上げるための改善をしていこうと考えています。自分もこれから改めて機械学習の勉強をしようと思いますので、お手柔らかに見ていただけたらありがたいです!
目次[非表示]
- 1.実行環境
- 2.データ収集
- 3.データクレンジング
- 4.データをNumpy形式に変換
- 5.モデルの構築・学習・評価
- 6.任意の画像を分類&Grad-CAMを実装!
- 7.感想
実行環境
・Python3 3.6.3
・jupyter notebook 4.3.0
・MacOS Catalina バージョン10.15.7
・NumPy 1.16.2
データ収集
「データは石油」であると喩えられるほど重要であるデータですが、実際に、企業のプロジェクトなどでAIを使う際には何万、何十万といった膨大な量のデータが必要であると言われています。
ただ、個人でそこまでのデータ量を集めるのは困難であることが多いです。前回の私の挑戦の際もグラスそれぞれに対して400枚ほどしか集められませんでした。精度があまり上がらなかったのもデータ量の少なさが一つの要因であるとも考えられるので、今回は、1000枚ずつ画像を集めたいと思います。
さて、今回もflickrから画像データを収集します。flickrとは、写真の共有を目的としたコミュニティウェブサイトのことです。
画像データを一枚一枚ダウンロードするのは最初から画像を厳選できるものの、大量の画像を集めたい場合には効率が悪いです。そのため、今回は、flickrAPIを用いて、大量の馬、シマウマの画像を自動でフォルダに保存できるようにしたいと思います。これをスクレイピングといいます。
ソースコードは以下です。今回は、できるだけサーバーの負荷にならないように1回につきスクレイピングする枚数は500枚にしました。
データクレンジング
さて、「horse」と「zebra」のフォルダにそれぞれ集めた約1000枚の画像データから、質の悪いデータを手作業で消去していきます。主に、判断基準は自分が馬かシマウマか判別できるものとします。結構甘々で行きます。
削除後は以下のようになりました。前回の「グラスの判別」の時よりも質の良いデータが集まっていたおかげで、削除する枚数が少なくてすみました。結果がとても楽しみです!
horseフォルダ:1000枚→969枚
zebraフォルダ:1000枚→957枚
データをNumpy形式に変換
ここでは、画像データはそのままでは扱えないため、画像データを扱いやすいNumpy形式の64×64の3チャンネルに変換してから、学習用データと評価用データに割り振ります。比率は、前回と同じく7:3にしました。
モデルの構築・学習・評価
前回のモデルをベースに、以下のように構築しました。今回新たに追加したのは、学習曲線の可視化プログラムです。model.fitの引数にvalidation_dataを渡してあげることで実装ができます。
まずは、epoch100で試したところ、Test Accuracyは約0.97、Test Lossは約0.28となりました。ニューラルネットワークの学習においての目標は、出力と正解のラベルの差を意味する loss を最小化することにあります。
学習曲線をみてみましょう。epoch40くらいからtest_lossが上昇していき、train_lossと乖離していく様子が確認でき、過学習していると考えられます。ですので、epochを乖離が始まる直前の40に設定して、もう一度、学習させます。
改めて学習させると、以下のようになります。Test Accuracyの高さを維持しつつ、先ほどよりもTest Lossを低くすることに成功しています。先ほどの学習曲線のグラフの振り幅の大きさは気になりますが、十分な精度が出ているので、分類器はこれで一旦完成とします。
任意の画像を分類&Grad-CAMを実装!
分類器が出来上がったので、実際に任意の画像を読ませて、しっかり分類できるのか試して見ます。また、今回は、上記で作成したモデルに、Grad-CAMを実装します。Grad-CAMを実装すると、モデルが画像を分類をするために、画像のどこに注目しているのかわかるので、モデルの欠陥の発見や考察がしやすいです!(ここが個人的に1番好きです!)
また、任意の画像のパスを入力すると、保存したモデルから馬とシマウマのどちらか分類をしてくれるプログラムを作成しました。
testフォルダを用意して、その中にhorseフォルダとzebraフォルダを新たに作ります。それぞれ3枚ずつモデルのテストをしてみます!(この後、紹介する際にわかりやすいので、それぞれ番号を振っておきました。)
テスト1
まず、馬の1枚目の画像ですが、うまく分類することができました!
下記のコードブロックは、入力サンプル画像に対する予測値の出力です。分かりやすいように%表示にしました。
画像は、Grad-CAMによる、イメージのどの部分が分類に重要であるかを示したものです!色が濃いほど、分類に大きく影響しています。これを見てみると、馬全体に注目していて、特に頭部に最も大きく影響していることが分かります!
"Friendly Horse" by William Garrett is licensed under CC BY 2.0
テスト2
こちらの画像もうまく分類できていますね。下の画像では、馬の頭に注目していることが分かります。今回の馬のデータにはこのように白い模様が入っているものは例外的なので、テスト1とは違い、胴体部分には注目していないのかもしれません。ですが、模様のない頭部に注目して、正確に分類できています。
"Horse" by Itai Nathaniel is licensed under CC BY 2.0
テスト3
3枚目の画像は馬が2頭写っています。精度は、テスト1、2に比べると少しだけ下がりましたが、それでもうまく分類できています。それぞれ、胴体を中心に注目していますね!
"horses" by Barry Skeates is licensed under CC BY 2.0
テスト4
シマウマの1枚目の画像です。胴体の縞部分に注目しています!精度も文句なしです。
"Zebra" by snarglebarf is licensed under CC BY 2.0
テスト5
5枚目の画像です。こちらも複数頭写っている画像になります。他のテストに比べて、精度が少し下がってしまいましたが、正しく分類できています!
"Zebra" by [email protected] is licensed under CC BY 2.0
テスト6
最後の画像です。精度は文句なしです。こちらもシマウマの縞の部分に全体的に注目していることが分かります!Grad-CAMを実装し、いくつかの画像を確認してみましたが、分類器は、高い精度で馬とシマウマの判別できているようですね!
"Zebra" by Shazron is licensed under CC BY 2.0
感想
今回は精度の高い分類器を作ってみたいという思いで始めたのですが、それに関しては最終的に94%という高い精度を出すことができて良かったです!達成できた要因の一つとして、データの量を増やしたことが挙げられると考えます。前回に比べて6倍も多くの画像を使用したことは、モデルの精度を上げるのに役立ったに違いないと思うからです。
ただ、今回は馬とシマウマを判定するといういわゆる2値分類だったので、適当にやっても2分の1で当たってしまうので、分類器が単純に当てやすかったということも少なからずあったかと思います。
それでも、Grad-CAMを用いて、注目している箇所を可視化した際の、馬の胴体に大きな模様がある場合には、頭に注目していたことなど、分類器としての優秀を感じた場面もありました。
次回は、今回作成した分類器をWebアプリ化したいと思います!自分も初めての試みですが、python以外にHTMLやcssなどの言語を使う場面もあるはずなので、とても楽しみです!それでは、また次回!
最後までご覧いただきありがとうございました。
PythonやAIプログラミングを学ぶなら、オンライン制スクールのアイデミープレミアムプラン。
「機械学習・ディープラーニングに興味がある」
「AIをどのように活用するのだろう?」
「文系の私でもプログラミング学習を続けられるだろうか?」
少しでも気になることがございましたら、ぜひお気軽にAidemy Premium Planのオンライン無料相談会にお越しいただき、お悩みをお聞かせください!
このほかにも、Aidemy MagazineとTwitter(@AidemyMagazine)ではたくさんのAI活用事例をご紹介しています。どちらも要チェック!