早くも3回目の提出となりました。まずは前回までのコードを一括で記述します。train_df、test_dfにデータ格納するところは割愛してます。地味ですが、kaggleのNotebookでquick saveだけだとoutputが保存されないらしいので、全部コード書き終わったらfullでsaveとりましょう。
#各種テーブルを結合
item_2 = pd.merge(item, categories, how="inner" ,on="item_category_id")
train_2 = pd.merge(train_df, item_2, how="inner" ,on="item_id")
test_2 = pd.merge(test_df, item_2, how="inner" ,on="item_id")
train_3 = pd.merge(train_2, shops, how="inner" ,on="shop_id")
test_3 = pd.merge(test_2, shops, how="inner" ,on="shop_id")
#dateを年、月、日で分解。
train_3["year"] = train_3["date"].str[-4:]
train_3["month"] = train_3["date"].str[-7:-5]
train_3["day"] = train_3["date"].str[0:2]
#item, shop, categoryのrankを作成
train_3[["month", "item_cnt_day"]].groupby(["month"], as_index=False).sum().sort_values(by="item_cnt_day", ascending=True)
train_3[["year", "item_cnt_day"]].groupby(["year"], as_index=False).sum().sort_values(by="item_cnt_day", ascending=True)
#それぞれpivotでテーブルを作り、降順にソート。そこにindexを付与し、売り上げランキングを作成する
item_rank = train_3[["item_name", "item_cnt_day"]].groupby(["item_name"], as_index=True).sum().sort_values(by="item_cnt_day", ascending=False)
#IDとして1から振り直し。sortは上のピボット生成時に実施ずみ
item_rank['item_rank'] = pd.RangeIndex(start=1, stop=len(item_rank.index) + 1, step=1)
shop_rank = train_3[["shop_name", "item_cnt_day"]].groupby(["shop_name"], as_index=True).sum().sort_values(by="item_cnt_day", ascending=False)
category_rank = train_3[["item_category_name", "item_cnt_day"]].groupby(["item_category_name"], as_index=True).sum().sort_values(by="item_cnt_day", ascending=False)
shop_rank['shop_rank'] = pd.RangeIndex(start=1, stop=len(shop_rank.index) + 1, step=1)
category_rank['category_rank'] = pd.RangeIndex(start=1, stop=len(category_rank.index) + 1, step=1)
#train, testにitem, shop, category_rankを結合
#howをleftにしないとtestの行数が変化してあとで困る
train_4 = pd.merge(train_3, item_rank["item_rank"], how="left" ,on="item_name")
test_4 = pd.merge(test_3, item_rank["item_rank"], how="left" ,on="item_name")
train_5 = pd.merge(train_4, shop_rank["shop_rank"], how="left" ,on="shop_name")
test_5 = pd.merge(test_4, shop_rank["shop_rank"], how="left" ,on="shop_name")
train_6 = pd.merge(train_5, category_rank["category_rank"], how="left" ,on="item_category_name")
test_6 = pd.merge(test_5, category_rank["category_rank"], how="left" ,on="item_category_name")
#testに予測したい年月日を入力
test_6["year"] = 2016
test_6["month"] = 11
test_6["day"] = 1
#item_rankに空白があるため、最下位で補填。順位はtest.info()で確認
test_6["item_rank"] = test_6["item_rank"].fillna(21808)
今回の目玉として、item_rankを区分化しようということで、おおよその目安をtrain_6.describe()で確認。
date_block_num | shop_id | item_id | item_price | item_cnt_day | item_category_id | item_rank | shop_rank | ||
---|---|---|---|---|---|---|---|---|---|
count | 2.935849e+06 | 2.935849e+06 | 2.935849e+06 | 2.935849e+06 | 2.935849e+06 | 2.935849e+06 | 2.935849e+06 | 2.935849e+06 | 2.935849e+06 |
mean | 1.456991e+01 | 3.300173e+01 | 1.019723e+04 | 8.908532e+02 | 1.242641e+00 | 4.000138e+01 | 2.649291e+03 | 1.734426e+01 | 9.804866e+00 |
std | 9.422988e+00 | 1.622697e+01 | 6.324297e+03 | 1.729800e+03 | 2.618834e+00 | 1.710076e+01 | 3.292436e+03 | 1.409859e+01 | 1.204331e+01 |
min | 0.000000e+00 | 0.000000e+00 | 0.000000e+00 | -1.000000e+00 | -2.200000e+01 | 0.000000e+00 | 1.000000e+00 | 1.000000e+00 | 1.000000e+00 |
25% | 7.000000e+00 | 2.200000e+01 | 4.476000e+03 | 2.490000e+02 | 1.000000e+00 | 2.800000e+01 | 3.260000e+02 | 5.000000e+00 | 2.000000e+00 |
50% | 1.400000e+01 | 3.100000e+01 | 9.343000e+03 | 3.990000e+02 | 1.000000e+00 | 4.000000e+01 | 1.345000e+03 | 1.400000e+01 | 5.000000e+00 |
75% | 2.300000e+01 | 4.700000e+01 | 1.568400e+04 | 9.990000e+02 | 1.000000e+00 | 5.500000e+01 | 3.726000e+03 | 2.800000e+01 | 1.300000e+01 |
max | 3.300000e+01 | 5.900000e+01 | 2.216900e+04 | 3.079800e+05 | 2.169000e+03 | 8.300000e+01 | 2.180700e+04 | 6.000000e+01 | 8.400000e+01 |
今回は25%, 50%, 75%で区分してみました。
#describeからiterankを区分分け
combine = [train_6, test_6]
for dataset in combine:
dataset.loc[ dataset['item_rank'] <= 326, 'item_rank'] = 0
dataset.loc[(dataset['item_rank'] > 326) & (dataset['item_rank'] <= 1345), 'item_rank'] = 1
dataset.loc[(dataset['item_rank'] > 1345) & (dataset['item_rank'] <= 3726), 'item_rank'] = 2
dataset.loc[ dataset['item_rank'] > 3726, 'item_rank'] = 3
# 先頭から5行を表示
train_6.head()
あとは前回同様に決定木で予想して、提出してみました。
気になる結果は、初回が1.53867、2回目は1.47967、そして今回は1.41241で、これまた微妙に改善。伴って順位は初回7,935位、前回7,782位と来て、今回は7,645位。まだまだやってみたいことがあるので、いろいろ試そう。
次回の改善ポイントは、item_rank同様にcatefory_rankとshop_rankの区分化、あとはitem_priceの特徴量反映、さらに決定木以外の手法の採用+ハイパーパラメータの使用などなど。
ということでまたもやすこーしだけ改善した3回目の提出でした。目標は今週中に何とか半分くらいの順位(4500位くらい)!!