2017年6月13日火曜日

深層学習を使ってツイッター画像のラベル付けができるまで(3)

深層学習のラベル精度向上のためにやったこと 


前の記事で、無事マルチラベルのラベル付けができる学習モデルが作成できるようになりました。ただ、その精度は納得できるレベルではなかったので、その改善のために「やったこと」と「起きたこと」を説明します。

やったこと1: 教師データを増やす。

精度が低いのは教師データが少ないからだろう、ということで「教師データを増やす」→「学習モデルを作る」→「ラベル付けする」を繰り返します。
するとあることが起きます。それは…
  • トレーニング用データのファイル作成ができなくなる。
エラーログを元に調べてみると、こんな記事を発見。これによると、macのPython3.4で、トレーニング用データをファイル出力するときのライブラリpickleに不具合があることが発覚!

そこでちょっと工夫して、教師データの上限を決めてランダムに選択するようにしてみたがかえって精度が悪くなる結果に。
苦肉の策として画像サイズを128→96にしてみたところ、精度もそれほど大きな違いがなかったのでこちらを採用して教師データを増やすことにしました。
その時の結果はこんな感じ。
  • loss= 0.503688128473
  • accuracy= 0.937188613881


やったこと2: 教師データを見直す。

過去に作成した教師データはラベル付けの基準が今と少し違うのが気になっていたので、改めて教師データを見直して修正。
しかし、見直したあとに作成した学習モデルでも大きな改善はみられず。(loss、accuracyの記録なし)


やったこと3: 期待から外れている画像の教師データを追加する。

毎日ラベル付けを行うようにして、その結果を閲覧、期待から外れている画像を補正のための教師データとして登録。
こうすればもっと精度が高くなることを期待しましたが、意外と精度は上がらず。
逆に大きく外れてしまう(特定のラベルが出やすくなる)事象が発生。


やったこと4: 合議制を導入。

画像サイズをもっと大きくしたり、層を増やしたり、…などが王道だと思われますが、残念ながら現在自宅の旧型mac-miniで頑張っているためマシンパワーは不足しており、さらに、上記の通りmac版のライブラリ不具合が判明しているのでちょっと小細工することに。
癖がある学習モデルから3つを選び、それぞれの分析結果を平均化して0.5以上(つまり、2つのモデルが判定したラベル)を採用することにしました。

現在は、自分としては70点くらいの結果は出ているかな、と思っています。
とは言っても、現在判定できるのは「イラスト」「文字」「ポスター・プラカード」くらいで「写真」の判定ができないのが残念なところです…


■最後に: 今後やりたいこと。

今後、精度改善としてやりたいこと。
  1.  画像サイズを大きくする。純粋にマシンパワーの問題なのでGCP上にTensorFlowで作り直してみたいです。ただ、データ量がそれなりにあるので個人の道楽にしてもいくらになるのか気になるところ。
  2. トレーニング用データのチューニング。現在の教師データはかなり偏りがあるので調整が必要と感じています。やり方はまだわかりませんが。
  3. 画像の別の情報を組み合わせた機械学習。例えば「写真」の判定は、色のスペクトルを取ればある程度判定できるのでは、と思ったり。
深層学習を自分でやってみた結果、細かいパラメータチューニングや、教師データの作成はほとんどブラックボックスなので職人芸が必要なように感じました。そういう意味では、ビジネスチャンスの匂いがします。ちょっと前にこんな記事がありましたし。

また何か実験してみたら報告します。

2017年6月12日月曜日

深層学習を使ってツイッター画像のラベル付けができるまで(2)

深層学習によるマルチラベルのラベル付け


前の記事で、ツイッター画像へのラベル付けの流れを説明しました。
今回は、特に重要なポイントになるラベル付けのための学習モデルをどのように改善していったか説明します。

画像の深層学習には畳み込みニューラルネットワーク(CNN: Convolutional Neural Networks)を使います。(ここでは深層学習については詳しく説明しません。前の記事で紹介した本やこの記事で学習して下さい)


1. まずは動かす。

Pythonによるスクレイピング&機械学習」の7-3をベースに教師データからトレーニング用データを作成し、そのトレーニング用データから学習モデルを作成するコードを作成します。
この時、以下のパラメータをそのまま採用しました。
  • 活性化関数: ReLU、softmax(最後のみ)
  • ドロップアウト: 0.25、0.5(最後のみ)
  • ロス関数: binary_crossentropy
  • optimizer: rmsprop
その他のパラメータは以下で設定。
  • 画像サイズ: 128
  • バッチサイズ: 64
  • エポック(学習回数): 10

■学習モデルのテスト結果

  • loss= 0.263982442949
  • accuracy= 0.917964078352

■サンプル画像でのラベル付け(抜粋)

サンプル画像のファイル名に、期待しているラベルを付けている。
  • sample-calendar01.jpg
    • illust: 1.0
  • sample-capture_text01.jpg
    • text: 3.62731e-12
    • capture: 1.0
  • sample-icon01.jpg
    • icon: 1.0
  • sample-icon06.jpg
    • illust: 3.1109e-17
    • text: 1.0
  • sample-illust_calendar05.jpg
    • illust: 1.0
    • text: 2.97645e-10
そこそこよい感じだが、マルチラベルでの判定になっていない。(実質、一つのラベルになっている)

■マルチクラスとマルチラベル

一つの入力に対して複数(3以上)の分類先がある問題を「マルチクラス問題」と呼ぶそうです。機械学習のサンプルでよく使われるMNISTは、「手書き数字の画像」を0から9のどれかに分類するので、典型的なマルチクラス問題です。
一方、マルチラベルは、一つの入力に複数のラベルがつく問題です。ツイッター画像には「イラスト」「文字」「写真」など一つの画像に複数のラベルが付けたいのでマルチラベルに適したアルゴリズムが必要っぽいです。

2.マルチラベル問題のための設定

単純に教師データが少ないためかと思い教師データを増やしたが変わらず。ドロップアウトのパラメータを変更してみたが変わらず。
ロス関数をbinary_crossentropyからcategorical_crossentropyに変えてみたところ、loss、accuracyの値は変わりましたが、結果はやはりマルチラベルからは程遠い…
また、このサイトの情報によると

  • categorical_crossentropy: 1-of-N (one-hot)  → for multiclass
  • binary_crossentropy: 1-or-more 0/1 labels  → for multilabel
のようです。なのでbinary_crossentropyが正解です。

マルチラベルについて調べたところ、以下のようなメモを発見。
他にソフトマックスではなくてシグモイドに通してloss関数に binary_crossentrpy などfchollet/keras#741予測する時は確率が0.5以上なら採用
ということで、最後のロス関数をsoftmaxからsigmoidに変更したところ、マルチラベルの結果が得られるようになりました!!
※ただ、sigmoidを使う方が良い理由は分からないので、ご存知の方がいましたら教えていただけると嬉しいです。

■学習モデルのテスト結果


  • loss= 0.427535426005
  • accuracy= 0.945025641674 

■サンプル画像でのラベル付け(抜粋)

  • sample-capture_text05.jpg
    • illust: 1.0
    • text: 1.0
  • sample-illust_calendar07.jpg
    • text: 1.0
    • placard: 1.0
  • sample-illust_text01.jpg
    • illust: 1.0
  • sample-illust02.jpg
    • illust: 1.0
    • text: 1.0
    • placard: 1.0
  • sample-placard01.jpg
    • text: 1.0
    • placard: 1.0
  • sample-text01.jpg
    • illust: 1.0
    • text: 1.0
次は精度を高めるための工夫について続きます。

2017年6月11日日曜日

深層学習を使ってツイッター画像のラベル付けができるまで(1)

最近はすっかりAIブームですね。
ということで、流行りの「深層学習」を使って何かやってみよう!と半年くらい色々と試行錯誤してましたが、ある程度形になったので、その時に困ったことなどの技術メモを残します。
これから同じようなことをやってみたい方の参考になれば幸いです。

なお、深層学習の専門家ではないので、用語などの間違いはご容赦下さい。
教えていただけると助かります m(_ _)m

テーマと結果

やったこと

やったことの流れと概要を以下に記載します。
  1. ツイートの収集: Twitter APIを使ってツイートを収集する。ツイートはmongoDBに保存。
  2. ツイート画像のダウンロード: 収集したツイートの中のentities.media.media_urlのURLから画像ファイルをローカルPCにダウンロードして保存。ツイートを見ると画像があるのにmedia_urlの存在しないツイートがあるため全ての画像が取れるわけではない。
    ※本当は全画像を分析したいのですが…誰かご存知の方、教えて下さい。
  3. 教師データの作成: 手作業で画像一つ一つにラベル付けを行う。ラベル付けのためのツールをnode.jsのアプリとして作成。(Google Cloud Vision APIを使って教師データを作る方法を考えたが、残念ながら自分の期待したラベルがつかなかった。教師データ作成は深層学習の課題になりそう。)
  4. トレーニング用データの作成: 学習モデルを作成するために、リサイズした画像データとラベルのペアにして一つのファイルにまとめる。「トレーニング用」と「テスト用」に分ける。ランダムで分けるコードにしているため、複数回実行すると毎回異なる(はず)。
    オリジナル画像の縦横比は気にしないで全て1:1になるようにリサイズする(これでも上手くいっているように見えるのが不思議…)
  5. 学習モデルの作成: 参考テキストの「第5章 深層学習に挑戦しよう」を参考にしてKeras(裏で動くライブラリはTensorFlow)を使ってコーディングし、学習モデルを作成。
  6. サンプル画像のラベリング(学習モデルの確認): 特徴的な画像をサンプルとして用意しておき、作成した学習モデルでのラベリング結果をみる。
  7. ツイート画像への適用: サンプル画像のラベリング結果でOKと判断した場合、ツイート画像へ適用する。
最初は「よい学習モデル」ができなかったため、工夫して3〜6を繰り返し、学習モデルの改善をしていきました。

この改善ノウハウついて次回説明します。




深層学習を使ってツイッター画像のラベル付けができるまで(3)

深層学習のラベル精度向上のためにやったこと  前の記事 で、無事マルチラベルのラベル付けができる学習モデルが作成できるようになりました。ただ、その精度は納得できるレベルではなかったので、その改善のために「やったこと」と「起きたこと」を説明します。 やったこと1: 教師...