はじめに
今回はKaggleで賞金付きのタスクにチャレンジします。メキシコのパンメーカーのBIMBOタスクで、パンの需要予測をします。学習データが約3Gと、そこそこメーカーの本気さが伺えるタスクになってます。優勝賞金は12,000ドルです。
データを眺めてみる
データはかなり莫大なので眺めるにしても工夫が必要。例えば、とりあえず先頭から1000件ずつを抜き出して眺めてみる場合は、cygwinで下記コマンドを打てば抜き出せる。あとはgrepを活用するなどして、多方面からデータを眺めてみる。
$ head -n 1000 train.csv > train.1000.csv
$ head -n 1000 test.csv > test.1000.csv
TrainとTestで共通する項目は以下のようになっている。
属性名 | 説明 |
---|---|
Semana | 週 |
Agencia_ID | 販売した町 |
Canal_ID | セールスチャネル |
Ruta_SAK | ルート |
Cliente_ID | 顧客名 |
Producto_ID | 商品名 |
「Semana」は週の情報である。今週の需要を予測するときに前の週までの需要を参考にすることは容易に想像できる。Semanaそのものを素性にする意味はないだろう。 「Agencia_ID」は別のデータから州と町を特定できるようになっている。パンの種類は地域ごとに特色があるかもしれない。地域をクラスタリングした素性は何か役に立つかも。 「Canal_ID」は販売チャネルのようだが、数字しかないのでよくわからない。きっと店頭販売やインターネット通販、宅配もやっているかもしれない。チャネルによって需要量の違いはあるかもしれない。 「Ruta_SAK」はルートということだが、正直いって説明を読んでもよくわからない。ただデータを見て言えるのは、同じ地域、顧客でもルートが異なる情報が登録されていることもある点だ。そしてルートごとに需要量は大きく異なり、そしてオーダーは週ごとに固定である。 「Cliente_ID」は顧客名で、別のデータから名前がわかる。町情報と合わせて用いれば、顧客名から顧客同士が親族かどうかわかるかもしれない。 「Producto_ID」は商品名で、別データから名前がわかる。データを見ると、パンだけでなく飲み物のデータもあるようだ。重さも名前の中にあったりなかったりする。名前の最後の方に「英字 + 数字」の組み合わせがあるが、一見すると数字の方はProducto_IDのように見える。商品もジャンルによって需要量に傾向があるとなんとなく予測できるので、クラスタリングして素性にするとおもしろそう。 データにないけどあったら良かったなと思うのは天気の情報。残念ながら公開データから天気を予測するのは無理だと思うので、素性化は諦めよう。 あとは、顧客は複数の商品を注文しているので、顧客のプロファイリング(大型、中型、小型店舗)も商品とその需要量から予測できそう。また、注文している商品の組み合わせにも何か相関があるかもしれない。例えばフランスパン1個にコーヒー10g、みたいな。 ちなみに、「Agencia_ID,Canal_ID,Ruta_SAK,Cliente_ID,Producto_ID」をキーにした場合のキーの数は以下のようになっている。 ユニーク 27752102個 出現数1回以上 10028743個
方針を立てる
兎にも角にもデータが大きくて、ちょっとした加工や整形にも時間がかかる。なによりメモリが足りない。ということで、比較的ライトにできることを検討してみた。ちなみに、Forumはかなり盛り上がってて、公開されているコードで上位10%くらいまでには入れる。 Bimbo XGBoost R script LB:0.457 商品のクラスタリングのコードを公開している人もいる。これを使うと、商品名が近いものを自動的にクラスタリングできる。 Products Clustering それで私はどうするかだが、以下の素性を用いることにした。
属性名 | 説明 |
---|---|
Agencia_ID | 販売した町 |
Canal_ID | セールスチャネル |
Ruta_SAK | ルート |
Cliente_ID | 顧客名 |
Producto_ID | 商品名 |
Producto_Cluster_ID | 商品クラスタID |
Liquid | 個体:0, 液体:1 |
History_t_2 | 2週前の売り上げ |
History_t_1 | 1週前の売り上げ |
「Producto_Cluster_ID」は先程のコードを使わせていただいて生成した。クラスタ数は300~400で適当に調整した。メモリが潤沢にあるならばこちらを参考にして適切なクラスタ数を求めてみるのもいいと思う。 「Liquid」は「Producto_Cluster_ID」単位で、商品名に「ml」が入っているものは飲み物、そうでないものは食べ物とした。 「History_t_n」はn週前の需要で、データが欠落している場合はNULLとした。 分類器はXgboostを用いた。パラメータは公開されているこちらと同じものを使っている。 学習データは全部突っ込むとOutOfMemoryになったので、7~9週目のデータのみを用いた。肝心のスコアは・・・0.48447だった。上位約30%というところだ。ちなみに評価手法は Root Mean Squared Logarithmic Errorなので、値が小さいほど良い。 (つまり、公開されているものより低い性能・・・)
おわりに
というわけで、Bimboに挑戦してみた。これから少し試行錯誤をする。ちなみに、今回の結果を出すにあたり、Windows10 16GBメモリのマシンを使用したが、ほぼ限界ギリギリだった。GCPなどをつかって一時的にスーパーマシンを使うことも検討しないとダメですね。