来月の商品の売上数を予測する〜Kaggle Predict Future Salesに挑む(その2)

来月の商品の売上数を予測する〜Kaggle Predict Future Salesに挑む(その2)

前回の投稿からだいぶ経ってしまいましたが、Kaggleの「Predict Future Sales」に再度取り組んでみました。
タスクの概要については以下の記事をご参照ください。


今回は前回とは違い、一応機械学習モデルを入れています。
今回のポイントはマスタであるitem_categories(商品カテゴリ)とshops(店舗)から大分類的な情報を生成したことと、商品売上数と商品売上金額についてラグ特徴量を取り入れたことです。

データ準備

各種ライブラリを読み込み、データセットをpandas.DataFrameで保持します。

INPUT加工

マスタであるitem_categories(商品カテゴリ)とshops(店舗)において大分類的なデータを抽出します。

item_categories(商品カテゴリ)

まずはデータを眺めてみましょう。
input:

output:

item_category_nameをみてみると、文字列” – “で前後に分割できそうです。
ちなみにGoogle翻訳では「Аксессуары – PS2」→「アクセサリー – PS2」だそうです。
item_category_nameは「大分類 – 小分類」のような構造になっているので、以下、” – “で文字列を分割します。

output:

いい感じに分割できました。
ざっと眺めたところ、似たような大分類があるのでまとめてしまいます。

output:

無事集約できました。

shops(店舗)

こちらもデータを眺めてみましょう。

こちらもGoogle翻訳でみてみます。
「!Якутск Орджоникидзе」は「ヤクーツク・オルゾニキゼ」らしいです。
ググってみると、ヤクーツクは都市名のようでした。
つまり、” “で文字列分割すると、都市名を抽出できることになるので、以下、shop_nameからcity_name(都市名)を抽出します。

item_categories(商品カテゴリ)と同様に表記揺れがあるので統一します。

output:

無事集約できました。

sales_train(売上学習データ)

sales_train(売上学習データ)についてもみてみます。
sales_trainは、日次の店舗×商品別のitem_cnt_day(商品売上数)、item_price(商品単価)が格納されているデータです。
ここで、売上金額カラムが存在しないので、新たにdate_sales(売上金額)を作成しておきます。

予測に必要な粒度にデータを変換

このタスクのゴールは、テストデータセットに含まれる店舗ID×商品IDを対象に、2015/11の商品売上数を予測することです。
上記のためには月次で売上データを集約し、かつ、テストデータセットに含まれる店舗ID×商品IDのみの学習データを準備する必要があります。

日次集計から月次集計に変換

学習データセットでは日次でデータを保持しているので、いったん月次に集計して粒度を揃えます。

テストデータの組み合わせに学習データをトリム

テストデータセットに含まれる店舗ID×商品ID、かつ、月のシーケンス(date_block_num)が0~34の組み合わせを生成します。

これに、月次集計データおよびマスタを結合させます。

データ可視化

月次の商品売上数のトレンドを可視化します。
まずは月次の商品売上数の合計から見てみましょう。


どうやら周期性がありそうです。
毎年12月付近は売上数が跳ね上がっています。

次にセグメント別に月次商品売上数を可視化します。
item_categories(商品カテゴリ)やshops(店舗)だと数が多すぎて可視化しても分かりにくいので、自分で追加したbig_category_name(商品カテゴリ大分類)やcity_name(都市名)でセグメント分けします。


big_category_name(商品カテゴリ大分類)も同様の周期性がみられます。


city_name(都市名)も同様です。
したがって、ラグ特徴量をいくつか追加して予測モデルを構築してみることにします。

ラグ特徴量の作成

月次商品売上数には周期性がみられるので、ラグ特徴量を生成した方が良いモデルになりそうです。
その前に、KaggleのOverview>Evacuationに以下の記述があるので、月次商品売上数を(0,20)にクリップします。

True target values are clipped into [0,20] range.

次に商品売上数、商品売上金額についてラグ特徴量を生成します。
1ヶ月前、3ヶ月前、6ヶ月前、9ヶ月前、12ヶ月前のラグを作成します。
ちなみに、このラグ間隔は直観的な理由で作っています。
なんとなく、前月と1クオータ前の同月、2クオータ前の同月、3クオータ前の同月、前年同月は予測にいい影響を与えそうなので。

最後にNAの項目は全て0埋めします。

予測モデルの構築

まず学習データセットとテストデータセットを分割します。
ラグ特徴量で最大12ヶ月前を使用しているため、学習データセットにはdate_block_numが12~33のデータ、テストデータセットにはdate_block_numが34のデータを割り当てます。

次に、string型の特徴量をLabel Encodingします。
今回の特徴量だと、big_category_name、city_nameが該当します。

次に予測モデルを当てはめます。今回はランダムフォレスト回帰木を使用します。

モデルに入力した特徴量の重要度を確認してみます。


前月の商品売上数、店舗、商品の重要度が高いようです。
今回作成した特徴量であるbig_category_nameは大した重要ではないようです。。。

さて、このモデルの学習データセットにおけるRMSEを計算します。
input:

output:

すごくいい結果が出ていますが、時系列データであること、過学習している可能性などが大いに考えられるので、あくまで参考程度に留めます。

予測結果を提出

結果はRMSEが1.07832で1,327/2,572位でした。
ランダムフォレストをちゃんとパラメータチューニングしたり、XGBoostなんかに変えたりすればもっと精度が上がると思います。
また、Kernelをみると各セグメントの組み合わせごとにmean encodingをしていたりもするようです。