u++の備忘録

Djangoで「名古屋/東京」の画像分類アプリを作った


はじめに

Djangoを使って「名古屋/東京」を判定する画像分類アプリを作ってみました。下記の記事で学んだことを活かして、自分で手を動かしてみたという経緯です。

upura.hatenablog.com

インターフェイス

index.html

この画面で、画像を選択します。「推定する」ボタンを押すと、result.htmlに推移します。

f:id:upura:20190728064910p:plain

result.html

推論結果の画面です。前画面で選択したファイル名・画像ファイル・推論結果・推論確率を表示しています。

f:id:upura:20190728064915p:plain

分類器

画像の収集

画像は、flickr API を用いて収集しました。「名古屋」「東京」の関連度順の検索結果を400枚ずつ収集しています。

機械学習モデル

KerasのVGG16使って転移学習させています。AUCは.65程度でお世辞にも良い精度とは言えませんが、今回はWebアプリ化が目的だったのでハイパーパラメータなどを少しだけチューニングして終わりました。

おわりに

本記事では、Djangoを使って自作した「名古屋/東京」を判定する画像分類アプリを紹介しました。やはり自分で手を動かすと、特に慣れてないDjango部分は詰まりどころが少なからずあって勉強になるなるなと感じました。

実装はGitHub上で管理していますが、講座で提供されたコードを流用している部分が大半なので、private設定にしています。

f:id:upura:20190728082935p:plain

大相撲のデータ収集は「Sumo Reference」が便利

8月24日(土)に開催予定の「Sports Analyst Meetup #4」で大相撲関連の分析をするに当たって、まずはデータ収集に取り組んでいます。

spoana.connpass.com

Sumo Reference

筆者は「Sports Analyst Meetup #2」のtomi_ さんのLTで知ったのですが、大相撲のデータ収集は「Sumo Reference」が便利です。

sumodb.sumogames.de

f:id:upura:20190726205258p:plain

収録されている項目

デフォルトは英語のサイトですが、日本語版も公式でサポートしています。

歴代力士

例:横綱一覧表

力士の出世記録検索

例:大関取り

取組検索

例:対戦相手

おわりに

本記事では「Sports Analyst Meetup #4」でのLTに向けて、大相撲のデータを収録している「Sumo Reference」を紹介しました。次回は、収集したデータの簡単な探索的分析・可視化をしていく予定です。

Udemy講座「【Python・Django・TensorFlow + 転移学習】画像分類AIアプリ自作入門」をやった

Udemy講座「【PythonDjango・TensorFlow + 転移学習】画像分類AIアプリ自作入門」をやりました。タイトル通り、PythonのTensorFlowで作成した機械学習モデルをDjangoを用いてWebアプリ化する講座です。全3.5時間を一晩で流し見しながら追体験しましたが、個人的に求めていた内容にピンポイントで合致して満足しています。

f:id:upura:20190723072704p:plain

https://www.udemy.com/django-ai-app/

受講の動機

受講した理由は、機械学習モデルをWebアプリに組み込む方法をザックリと知りたかったためです。最近、Kaggleなどで機械学習モデルの構築に取り組んでいる中で、Webアプリなど自分・他人が扱いやすい形で表現する必要性を感じていました。普段からPythonを使っているので、Djangoが選択肢となりました。

下記の講座の受講を経て、Udemy講座には好印象を持っていたのも大きかったです。

upura.hatenablog.com

受講前の知識

  • 教師あり機械学習はKaggleなどで経験あり
  • DjangoもTo doアプリなど簡単なチュートリアル経験あり
  • 保存した機械学習モデルをどう組み込んでいくか、ある程度の当たりは付いていたが、手っ取り早く動画で一連の流れを勉強したかった

各セクションの雑感

基本的に、全部1.5〜2倍速で観ていました。聞き逃した際には15秒戻る機能があるので、ある程度自信がある内容なら講師の話し方に合わせた早回しで受講して問題ないと考えています。

イントロ

概要です。一応聞いておいた方が良いと思いますが、事前の講座説明に書いてある通りです。

環境構築(既修者はスキップOK)

セクション名にある通り、飛ばしました。

データの収集・クレンジング

Flickr APIでのデータ収集の流れが説明されているので、自分で独自データを集める際に参考になりそうです。

CNNによるトレーニン

機械学習の学習・推論の流れはある程度事前に知っていたので、2倍速で流し見しました。

転移学習でスコアアップを図ろう!

同上。

コマンドラインアプリ化しよう!

Djangoでのアプリ化に向けて、一段階置いた橋渡しになっている構成は分かりやすいなと思いました。

Djangoでウェブアプリ化しよう

本講座の本丸です。「Djangoのインストールと動作確認」から始め、機械学習モデルを用いたWebアプリを段階的に作成していく構成になっています。自分でWebアプリを作っていく上でも模倣しやすい形式で、自分の受講理由に合致していると感じました。

おわりに

Udemy講座を通じて、機械学習モデルをDjangoを用いてWebアプリに組み込む方法を学びました。次は今回学んだ内容を用いて、自分なりの簡易的なWebアプリを作っていこうと思います。

Kaggle Jigsawコンペ32位でした

KaggleのJigsawコンペにチーム参加して、32位で銀メダルでした。public 58位からは上昇しましたが、金メダル圏内にはもうひと押し足らずという結果でした。

f:id:upura:20190719104759p:plain

www.kaggle.com

discussionにチームメイトのKazSappさんが投稿した通り、解法は6モデルの重み付き平均です。

1. bert base uncased
2. rnn
3. rnn (data augmented by translation)
4. rnn (data augmented by old toxic competition)
5. bert base cased
6. bert base multilingual cased
w = [0.39193463, 0.14464678, 0.03892303, 0.06871146, 0.317778, 0.038006]

重みは、Kaggle Tokyo Meetup #5 の「Home Credit Default Risk - 2nd place solutions」で知った Scipy Nelder-Mead を用いて CV 最適化しています。

public kernel含めて多くのチームはidentity_columnsの欠損値を0で穴埋めしていたと思いますが、僕らのチームに特徴的なアプローチとしてRNNで予測した値で欠損値を補完していました。今回のデータセットにおける identity_columns の欠損値は単にアノテータ(評価者)がいなかったという意味で、必ずしも0を意味しないと考えたからです。このアイディアはKazSappさんが思いついたもので、こういった自分の手持ちにはなかった手法に辿りつけるのがチーム戦の良いところだなと改めて感じました。

同じくチームメイトのtakuokoさんも、embeddingに関する知見をdiscussion投稿しています。

金メダルを取れなかった点は悔やまれますが、Bertの強さを身に沁みて実感するなど、学びが多いコンペでした。

LightGBMでtargetをsqrt(target)に変換して予測する「reg_sqrt=True」

機械学習教師あり学習における一つのテクニックとして、学習時の target 変換があります。昨晩に LightGBM の documentation を読んでいたところ、sqrt 限定ですが、target の変換を自動で処理してくれる parameter "reg_sqrt" を(恥ずかしながら初めて)知りました。

本記事では、学習時の target 変換の概要を述べ、LightGBM の parameter "reg_sqrt" を紹介します。

学習時の target 変換とは

target の分布が偏ったり過度に広がっている場合などに効果を発揮し得る手法です。target の各データに対して、log, sqrt を取るなどの変換を加えることで、全体の分布を整える狙いがあります。

例えば筆者が先に参加した地震コンペでは "time_to_failure" という連続値が target になっていました。この target は小さい値のデータが多く、各データに対して sqrt を取ることで、全体の分布を正規分布に近づけることが可能でした。

f:id:upura:20190718115634p:plain

upura.hatenablog.com

学習時に target を変換した場合は、当然ですが test の値を予測した後に逆変換の処理が必要になります。例えば sqrt の場合は、予測値を二乗することになります。

target を変換した場合とそうでない場合では、予測の得意・苦手が変わってくる印象があります。例えば地震コンペの場合、sqrt を取った場合は高めの予測値が出づらくなっていました。学習時の target 変換は予測の多様性も生み出すので、アンサンブルの種を作る意味でも試す価値がある認識をしています。

LightGBM の parameter "reg_sqrt"

学習時の target 変換の処理は自分で書いてもさほど難しくないですが、そのせいもあってLightGBM に parameter が用意されているのを知りませんでした。予測値を二乗する処理も自動で行ってくれるので、処理し忘れで的外れなスコアを出すミスも避けられそうです。

  • reg_sqrt 🔗︎, default = false, type = bool
    • used only in regression application
    • used to fit sqrt(label) instead of original values and prediction result will be also automatically converted to prediction^2
    • might be useful in case of large-range labels

https://github.com/microsoft/LightGBM/blob/master/docs/Parameters.rst#reg_sqrt

おわりに

本記事では、学習時の target 変換の概要を述べ、LightGBM の parameter "reg_sqrt" を紹介しました。頻繁に使っている LightGBM ですが、改めて documentation を眺めると意外と認知していない parameter や機能追加に気付けるので面白いなと感じました。

「長さの近いデータを同じbatchに入れる」の性能劣化と速度

先のKaggle Tokyo Meetup #6 でのtksさんの発表で触れられた「長さの近いデータを同じbatchに入れる」について、チームで参加した「Jigsaw Unintended Bias in Toxicity Classification | Kaggle」にて同じような取り組みをしていました。

本記事では、Jigsawコンペにおける「長さの近いデータを同じbatchに入れる」処理について、性能劣化と速度の数字を紹介します。なお、あくまで筆者の事例に過ぎない点にはご留意ください。

TL;DR

「長さの近いデータを同じbatchに入れる」処理で、性能は多少落ちるが、速度が大きく向上する

JigsawコンペでのBERT学習時 性能(CVスコア) 速度(s)
処理前 0.9372215615637538 28000
処理後 0.9365093209503504 14000

「長さの近いデータを同じbatchに入れる」とは

deep learningなどの機械学習アルゴリズムでは、扱うデータの長さが均一である必要があります。テキストデータは長さがバラバラなので、最大長のデータに合わせて適当な値でデータを埋める(padding)処理が実行されます。この処理は一般に、(下図の例では角丸四角で囲まれた)batch単位で行われます。

下図の左の例は、batch単位でのデータの長さがバラバラの場合を示します。このとき、長さの大小が様々なデータが同一のbatchに含まれており、長さの小さいデータでは最大長までpaddingが実施されています。

ここで事前に各データを長さ順にsortし「長さの近いデータを同じbatchに入れる」場合を考えましょう。各batchでの長さが比較的揃うことで、必要なpaddingの処理が少なくなっています。

f:id:upura:20190716123941p:plain

メリット

  • データのpaddingされた部分は、本来欠損している部分なので、機械学習アルゴリズムにおいて特別な処理が求められるので、データの処理時間に影響を与えます
  • 各batchでのpaddingの処理を少なくするとこで、全体での無駄が減り、実行時間が削減できるメリットがあります。

デメリット

  • 一方で、長さの近いデータのみを同一のbatchに収めてしまうことで、データに偏りが生じて性能劣化に繋がる可能性があります

実装・解説など

次のブログに、日本語での実装・解説が記載されています。なお末尾に次の文があり、本記事は数値検証の一つの実例としてまとめた側面があります。

余力があれば、
1 ) 精度面でどれだけ悪化するのか
2 ) どれだけ早くなるのか
を比較実験した記事も書きたいなと思います。

kaeru-nantoka.hatenablog.com

数値検証

Jigsawコンペの場合

学習時

冒頭に記載した通り、性能は多少落ちるが、速度が大きく向上するという結果になりました。

BERT学習時 性能(CVスコア) 速度(s)
処理前 0.9372215615637538 28000
処理後 0.9365093209503504 14000

なおJigsawコンペではAUCを拡張した少し複雑な評価指標が使われていました。AUCと同様に0-1の値を取り、大きいほど優れた評価指標になっています。

https://www.kaggle.com/c/jigsaw-unintended-bias-in-toxicity-classification/overview/evaluation

推論時

Jigsawコンペでは、モデルの推論をKaggle Kernel内でGPU 2時間 (7200s) に収める必要がありました。推論時にもデータのソートを実施したところ、推論時間が58min -> 25min に短縮されました。

Quoraコンペの場合

tksさんがMeetup後に数値検証した結果、性能は悪化したとのことでした。


おわりに

本記事では、Jigsawコンペにおける「長さの近いデータを同じbatchに入れる」処理について、性能劣化と速度の数字を紹介しました。あくまで筆者の事例における結果なので一概に結論を述べるのは難しいですが、一定の性能を犠牲にして高速化が実現できた結果となっています。

最近はKaggleにおいても実行時間の制限があるコンペが増えており、学習・推論の実行時間を短縮できるのは十分に価値のあることだと思います。単体モデルとしては性能劣化が生じるものの、例えば浮いた実行時間で複数モデルをアンサンブルするなど、総合的な性能向上が見込めそうです。実サービス運用においても、多少の性能を犠牲にして実行速度を改善したい場面はあり得るので、選択肢の一つに入ってくるかなと考えています。

Kaggle Tokyo Meetup #6 にて「PetFinder 2nd Place Solution」の題目で発表しました

「Kaggle Tokyo Meetup #6」に参加し、チーム Wodori の一員として「PetFinder 2nd Place Solution」の題目で発表もしました。

connpass.com

本記事では、各発表の簡単な感想などを述べます。twitterの #kaggle_tokyo や kaggler-ja slackの #event-live にも情報が転がっています。

togetter.com

「PetFinder 2nd Place Solution」(Wodori)


「iMet 7th Place Solution & 画像コンペのアプローチ」(phalanxさん)


  • 後半で述べていたphalanxさんなりの汎用的なmodel pipelineが素晴らしかった
    • yamlを書き換えるだけで学習・推論・ログ出力などが自動化されているらしい
    • 懇親会で別の画像の強い人とも話したが同様のpipelineを持っているらしく、自分もきちんとコードを整備したいと感じた

「Quora Insincere Questions 10th Place Solution & 昔話」(tksさん)

  • jigsawのsolutionとして公開されて気になっていた「exponential moving average」について話題になって、個人的にとても勉強になった
  • Kaggle昔話も、知らないことが多くて面白かった

「PLAsTiCC 3rd Place Solution」(nyanpさん)


  • コンペの意義から具体的な解法まで、情報量多い解説だった
  • 有効だが生成に時間がかかる特徴量を大量にインスタンスを立てて作成するなど、勝負どころでの力強さを感じた
  • adversarial pseudo labeling や カテゴリ変数がない場合のCatboostの利用など、将来のコンペで使ってみたいアイディアが多かった

LT①「Neural Network のご機嫌取りがしたい」(tawatawaraさん)

LT②「NLPチュートリアル」(tamakiさん)

www.kaggle.com

github.com

LT③「Freesound Audio Tagging 2019 4th Place Solution」(OUMed: Osciiartさん、jsatoさん)

LT④「Google Landmark Retrieval 2019 1st Place Solution」(smlyさん)


LT⑤「Santander Customer Transaction Prediction 2nd Place Solution」(onoderaさん)

To Be Written.

おわりに

昨年12月に開催された前回は、Kaggle Expertとして参加し、LTをしました。

upura.hatenablog.com

その後なかなかコンペで良い成績が出せず落ち込んでいた時期もあったのですが、良いチームメイトに恵まれ金メダルを獲得してmeetupで発表できたことは、本当に嬉しいです。

日本でのKaggleの人気・実力が高まっていてmeetup参加の難易度が上がっていますが、ぜひ次回も参加できるようKaggleに精進していきたいと思います。

運営の皆さん、会場スポンサーのDeNAさん、ありがとうございました!

f:id:upura:20190713173152j:plain