u++の備忘録

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