Keras,Flask,Colabでかわいい判定機を作った

今回はあるイベントのLTで発表することも兼ねて、 とりあえずなんでもいいから使ってみたことのないものを使ってみまくろうというスタンスで色々やってみました。  

今回(ほぼ)初めて使ってみたもの

 

  • CNN
    • 画像認識のディープラーニングのアルゴリズム
  • Flask
  • Pyhonのサーバーサイドのフレームワーク
  • Pillow
    • 画像処理ライブラリ
  • flickrAPI
    • 画像検索サイトFlickrのAPI
  • convnet-drawer
    • Kerasのコードでモデル図を生成
  • Google Colaboratory
    • googleが提供する無料GPUサーバー環境
  • Chart.js
    • グラフを描画するjsフレームワーク
  • Dropzone.js
    • ファイルアップロードのためのjQueryプラグイン
  • flask-dropzone
    • Dropzone.jsのflask用のツール

概要

ということで、Udemyのこの講座を参考にして、実装し、色々工夫してみました。
今回作るものは、「かわいい判定機」です。
最初に4種類のかわいい動物の画像を学習させて、 その後、何かの動物の画像をアップロードし、判定してもらいます。  

データ収集(FlickrAPI,urllib)

Flickrという画像検索サイトのAPIとURLにアクセスするためのPythonモジュールのurllibを使って画像データを取得します。

コードはGitHubにあげています。  

大まかな流れは以下のサイトを参考にしてみてください。
【参考】Flickr APIを使って画像ファイルをダウンロードする  

上のサイトを参考にしてここからFlickrAPIの登録をします。

次に、flickrAPIをローカル環境で使えるようにflickrapiをインストールします。
$ pip install flickrapi

FlickrAPIを使ってコードを書いて画像データを取得します。
今回はネコ、ヘビ、ハリネズミ、ペンギンの画像を各400枚ずつ取得しました。
flickrAPIのオプションは以下のように設定しました。

これを実行すると、 以下のようなデータが返ってくるのでurl_qをkeyにして、URLを取得します。

urlretrieveを使ってダウンロードを実行します。

このファイルを保存して、カレントディレクトリに「cat」というフォルダを用意した後に、 $ python download.py catと実行すると、こんな感じにぞくぞくとダウンロードされていきます。 

データの前処理

Pillow(PIL)という画像処理ライブラリを使います。
画像を回転させたり、反転させたり、色々な操作ができるようです。

コードはこちらです。  
【参考】Pythonの画像処理ライブラリPillow(PIL)の使い方 | Python / note.nkmk.me  

最後に、その画像データをnumpy行列に変換し、保存します。

あとで知ったのですが、Kerasにそもそも画像を加工するImageDataGeneratoという関数が用意されているのですね。
次の機会にはこちらを使ってみようと思います。  

CNNモデルを実装

コードはこちら。  
備忘録がてらKerasのCNNのモデル実装部分の使い方を。  

Convolution層

この部分ですね。
model.add(Conv2D(32, (3 ,3), padding="same", input_shape=X.shape[1:])) 
この1行が示していることは、 3×3のサイズフィルターを32個使用する。
入力と出力が同じサイズになるようにpaddingを適用させる。
入力の画像サイズは50×50×3(縦×横×チャネル) 今回はRGBの画像を使用しているので3チャネルになります。  

この画像を見てもらうとわかりやすいかと思います。

【引用元】conv_arithmetic/same_padding_no_strides.gif at master · vdumoulin/conv_arithmetic  

上の画像で言うと、 青い画像(5×5)が入力される画像。
緑の画像が出力された画像。
青の画像の上で動いている灰色の部分(3×3)がフィルター。
となります。

ここで、CNNではこのフィルターが重みになっており、このフィルターの値を随時更新していきます。  
再びこのコードを見てみましょう。
model.add(Conv2D(32, (3 ,3), padding="same", input_shape=X.shape[1:]))

自分で指定するのは、まずは灰色のフィルターの枚数です。
上のgif画像では1枚しか写っていませんが、 上のコードでは32枚のフィルターを用意して、gif画像と同じような作業を32回するということです。  

次にフィルターの大きさ。
画像と同じように3×3のフィルターを用意しています。  
paddingもgif画像と同じようになっています。

要は余白の大きさ(gif画像の点線の部分のサイズ)はあまり意識せず、青(入力)と緑(出力)のサイズを同じするということです。  
今回のデータはRGBも考慮しているので 50×50×3の3次元データになっているので、1回のinputに対して3枚のフィルターがかかっています。  

Pooling層

次にCNN特有なのがこの部分です。
プーリング層を実装しています。

データの一部から最も大きい値を選んで伝播させ、凝縮します。
model.add(MaxPooling2D(pool_size=(2, 2)))

ここでは、オプションでpool_sizeを指定していますが、 これは「ダウンスケールする係数」とドキュメントに書かれてあります。

つまり、インプットやアウトプットのサイズのことではなく、縦横それぞれにおいて何分の1にするかを指定します。
(2,2)とした場合はそれぞれの次元において半分にするので、画像サイズ自体は4分の1になりますね。  

convnet-drawer

ちょっとサーフィンしてたら、たまたまこんなものを見つけたので使ってみました。
上のKerasのコードをコピペするだけで、以下のような画像を作成してくれます。

以下の画像は、今回作ったモデルをまったくそのまま図にしたものになります。
これはブログ記事やLTのときなどに便利そうですね。

【参考】畳み込みニューラルネットワークをKeras風に定義するとアーキテクチャの図をパワーポイントで保存してくれるツールを作った – Qiita  

Colaboratory

では、次にGoogleのColaboratoryを使ってGPUサーバーで学習をしていきます。

この、Colaboratoryとはなんなのかというと、jupyter notebookをブラウザ上で、 しかもGPUまで使用できるようなGoogleのサービスです。
また、機械学習によく使われるモジュールなどはすでにインストールされているので、環境構築をする手間も要りません。  
気軽にGPUを使用したい、とか、機械学習系のハンズオンで簡単に環境を共有したい、などのときに便利かと思います。  

まず、先ほど作ったnpyファイルをクラウドにアップロードし、学習をしたいと思います。
コードスニペットで「uplaod」などを検索すると、スニペットが表示されますので、これをコピペして実行するとファイルをアップロードすることができます。

ここで、ランタイム>ランタイムのタイプを変更>ハードウェアアクセラレータからGPUを使うことを選択することができます。
その後、先ほどのコードをコピペして実行すれば、学習が開始されます。  

時間比較

  colabを使ったのとローカルでの学習時間を比較してみてみました。  

colab

test loss: 1.2305 test acc: 0.75 time: 53.83715105056763  

local

loss: 1.6377 test acc: 0.65 time: 677.4231910705566  

accが大分落ちたのは謎ですが、注目すべきは時間です。
さすがGPU。
約12倍も速いです・・。  

result

maxPoolingとAvePoolingの比較

CNNでは、よくmaxPoolingが使われていますが、なんか直感的には平均取ったほうが良くない?って思ったので、 他のパラメータを一緒にして1回ずつ実行してみました。
batch_size = 32 epoch = 50 結果は以下の通りです。  

MaxPooling

test loss: 1.485 test acc: 0.8125  

AveragePooling

test loss: 1.901 test acc: 0.7775  

1回しかやってないのであれですが、たしかにAveを取ったほうが正答率が下がっています。
なんでなんですかね。
誰か教えてください。  

h5pyファイルのダウンロード方法

あとでFlaskの実行時に使うために学習結果であるh5pyファイルをクラウド上からローカルに移したいときは、 以下の行を追加すれば良いです。
これはコードスニペットのところで「download local」など検索すれば出てきます。

ちなみにcolabとローカルのkerasやtensroflowのバージョンがズレているとh5ファイルが利用できなかったりします。

その時の対策をメモしておきます。   !pip freezeでインストール済みパッケージのバージョン一覧を確認できます。  
また、
$ pip install keras --upgrade $ pip install tensorflow --upgrade
でアップグレードので、バージョンを揃えてきましょう。  

Flaskでwebアプリケーションを作成する

コードはこちら。  

Flaskの起動

普通に実行するだけです。 $ python predict_file.py  

Flaskでファイルをアップロードする

 このチュートリアルのコードを参考にして記述します。  

Dropzone.js

Dropzone.jsとはファイルをアップロードするformの、jQueryプラグインです。
Flaskとの互換性を持たすためにflask-dropzoneというのがあったので、 今回はそれを使わせてもらいます。
非常にシンプルで使いやすく、パラメータの調整とかやりやすいのですが、 僕のflaskに対する知識が微妙なので、上手くsubmitできませんでした。 今後修正します。  

Chart.js

Chart.jsは、簡単にグラフを描画できるjsフレームワークです。
日本語ドキュメントもあって、非常に使いやすいです。  

コードはこちら。  

こんな風に綺麗に描画されました。  

最後に

今回は初めてのものをふんだんに使ってみました。

今度は、

  • acc向上のためのアプローチ
  • CapsuleNetworkなど別ののモデル
  • パラメータの自動調整
  • Chainer

などを使ってみたいです。

また、今回はどこで使うねんって感じの画像判定機でしたが、 今度はもうちょい役に立つものを作ってみたいと思います。