Cpaw AI Competitionを連覇しました

第3回 Cpaw AI Competitionで優勝してきました。


cpaw.connpass.com


前回も優勝したので連覇になります。嬉しいです。

Cpaw AI Competitionがどのようなものかは以下の記事に詳しく記載されています。

knowledge.sakura.ad.jp

 

ざっくり概要を説明すると「短時間で複数のデータセットに対してソリューションを作成するKaggle」です。

データセットの数は毎回異なっているようで、前回は4つでしたが今回は3つでした。

それぞれのタスクは以下のとおりです。

  • 自然言語 + テーブルデータのマルチクラス分類
  • 画像のマルチクラス分類
  • ハイパースペクトル画像のマルチクラス分類

この記事では、今回行った事前準備と私のソリューションの概要について説明します。

 

自然言語 + テーブルデータのマルチクラス分類

観光地に関するデータセットで、観光地の説明文や都道府県・観光地が開かれている曜日・時間帯などの情報を使って観光地のクラス(Temple, Spa, Park, Shopなど8クラス)に分類する問題です。

私のソリューションはMulti Layer PerceptronとLightGBMのスタッキングで、各レイヤーのモデル・特徴量は以下の通りです。

  • 1段目のMLPの特徴量として、word tfidf(形態素解析MeCab + neologd)とcharacter ngram tfidfをconcatして利用
  • 2段目のLightGBMの特徴量として、上記のconcatした特徴量 + MLPの予測値 + 元データの中で型がint, floatのものを利用

データセットの中にはカテゴリカルなカラムもあったので本当はそちらも使いたかったのですが、時間がなくて断念しました。

最終的な精度は84.3%程度でした。

 

画像のマルチクラス分類

手の画像があり、指が何本(1本 or 2本 or 3本)立っているかを予測するマルチクラス分類の問題でした。

モデルは以下のCNNで、kerasのImageDataGeneratorでData Augmentationをし、50エポックほど学習させて精度は97%程度でした。

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(class_num))
model.add(Activation('softmax'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

ハイパースペクトル画像のマルチクラス分類

ハイパースペクトル画像のマルチクラス分類問題です。すみません、解説のときにぼーっとしていたのでこれ以上詳しい説明ができません...。
そもそもハイパースペクトル画像というものを知らなかったのでぐぐってそれっぽい論文を探したり、1次元CNNを実装したりしたのですが学習がうまくいかず、
結局サンプルコードのモデルをリッジ回帰からLightGBMに差し替えたものが最も高精度で、88%程度の精度で終わりました。

Cpaw AI Competitionで勝つために大切なたった2つのこと

勿論Kaggleで求められるような機械学習やプログラミングの基礎的な能力も当然大事なのですが、個人的にはこの大会で勝つために求められる能力は微妙に異なると思っていて、特に以下の2点が重要だと考えています。

やることの優先順位をつけること

Kaggleと比べると圧倒的にタスクを解く時間が足りないので、実装にかかる工数と期待される効果を鑑みてやることの優先順位をつけることがKaggle以上に重要になります。
Kaggleに関しては全てのdiscussionとkernelを見てtry everythingすれば良いだけなので特にやることの優先順位などをつける必要はないのですが、何せ4.5時間で3タスクを解く必要があるのでtry everythingする余裕はありません。
今回は観光地データセットにカテゴリカルなカラムが含まれていて恐らくこのカラムで特徴量を作れば精度が上がったかもしれないのですが、実装工数がかかりそうだったので見送りました。
結果的にはStackingが余り効果がなかったのでひょっとするとfeature engineeringに取り組んだほうが良かったのかもしれないのですが、この辺は結果論ですね。
データセットの各カラムのデータ型を見たときにnumericalなカラムがあったので、カテゴリカルな特徴量に対してfeature engineeringするよりはMLPの予測値とnumericalなfeatureをLightGBMでStackingした方が期待される精度向上は高そうだと考えてそちらを優先しました。

事前準備をすること

この大会ではさくらVPSのハイスペックなサーバーが各参加者に与えられるのですが、ほぼまっさらな状態で与えられるので環境構築を行う必要があります。
地味に時間がかかるので、環境構築はスクリプトで自動化しておくとだいぶ時間が節約できると思います。
私自身前回は準備をせずに行ってかなり時間を取られたので、今回はある程度環境構築を自動化できるようスクリプト化しておきました。それでもmecab周りの設定は準備できておらず、うまくサーバーの方に入っていなかったので結局手元のローカルMacでやる羽目になりましたが...。
後は、(中々そこまでのガチ勢はいないと思いますが)本気で勝つことを目指すのであれば特徴量生成などの関数を自作したり、様々なタスク(e.g. 画像のクラス分類)のテンプレート的なNotebookを作成しておくと時間が節約できると思います。

感想

前回に引き続き大変疲れましたが、とても楽しい大会でした!
4.5時間で3タスクはエグいですね。終始アドレナリンを出しながら仕事以上に集中してやってました。
KaggleもKaggleでコンペ中はとても楽しいのですが、時間がめちゃくちゃ短くてリーダーボードも所謂パブリックリーダーボードしかないのでまた別のヒリヒリ感があります。(Kaggleも1位の人とかだとヒリヒリ感があるのかもしれませんが、なったことがないので感じたことがありません😢)
最後の20秒くらいは出来ることも特になかったので、抜かれないことを祈りながら更新ボタンを押してました。
運営的にはかなり大変(データセットの作成は本当に大変だと思います。いつもありがとうございます)だと思いますが、とても楽しい大会なので是非今後も続けて頂けると嬉しいです。
運営(Cpaw)の皆様、スポンサーの皆様(サイバーエージェント様・さくらインターネット様)、素晴らしい会を開いて頂いてありがとうございました!