わいす工場 Kaggle ど素人のkaggle4 -2nd sub-

ど素人のkaggle4 -2nd sub-


前回は年と月のみのデータを使用して、shopやcategory, itemの名前を全て破棄して予想していました。さらに予測精度を上げるためにはこの辺りの情報を上手く使いたいなと思い、今回はこの辺りを上手く使おうとしました。

あと前回の問題点として、item_idやshop_idをそのまま連続する数値として使用していたので、ノイズとなっていたことが予想されます。idの4の売り上げが3と5の間にあるか?というとない可能性が高いということです。

さてshop_nameなどはロシア語で、さっぱりわからないし機械学習に文字列は僕の拙い知識ではそのまま使用できませんので、なんらかの工夫が必要です。

データの種類が少なければ、男性を1, 女性を0とするなどして数値に置き換えてもいいのですが、item.info()でみてみると、22170種類。。。shopは60でcategoryは30と中々の種類なので、ただ単に置き換えたところで上手く使えなさそうです。

そこで考えたのが、item, shop, categoryそれぞれにおいて、売れ行きランクを作ってやればそこそこ意味があるようになるのでは?と思い、試してみることにしました。使用したコードは次の通りです。

#それぞれ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)

これをitemだけでなく、shopとcategoryでも繰り返します。

#as_index=Falseで結合時にエラー(理由確認必要。。。)
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)

それぞれのrankを各種nameをキーにして、trainとtestに結合します。

#train, testにitem, shop, category_rankを結合
#leftにしないとinnerなどでやると行が変化してしまう。
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")

ここまできたら、nameはもう不要(というか学習時にエラーになる)ですので、次のコードで削除します。

train_6 = train_6.drop(["item_name", "item_category_name", "shop_name"], axis=1)
test_6 = test_6.drop(["item_name", "item_category_name", "shop_name"], axis=1)

これでいいと思い、意気揚々と学習したら、NaNエラー。。。どうもitemリストにないitemが含まれていたようです。

リストにないitemなので、売り上げ少ないだろうということで最下位の数字を入力することに。ちなみにここを適当に0にしたら、最後の評価でRMST 20とか出ておったまげました。。。1が一番売れやすいという特徴量なのに、売上の少ないitemを0にしてしまったため、めちゃくちゃな結果になったのでしょう。

train_6.describe()で確認したところ、maxは21807でした。それよりも売上少ないだろうということで21808で置換することとしました。(本当は確認必要)

null処理のコードはこちら。

#test_6のitem_rankにnullがある。→nullをどう対応するか? maxが21807なので、naは21808と配置
test_6["item_rank"] = test_6["item_rank"].fillna(21808)

手法は前回同様に決定木を使用しました。

from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
X_train_lr, X_test_lr, Y_train_lr, Y_test_lr = train_test_split(X_train, Y_train, test_size=0.2)

decision_tree = DecisionTreeClassifier()
decision_tree.fit(X_train, Y_train)

Y_pred = decision_tree.predict(X_test)
acc_decision_tree = round(decision_tree.score(X_train, Y_train) * 100, 2)

print(acc_decision_tree)

モデルも見直すべきだなと思いつつも、とりあえずこれで提出しました。

結果は1.47967と前回1.53867だったので、少し改善しとる!順位は7,782位。前回は7,935位なので」上がってはいますがまだまだ果てしない。。。

ということで少しだけ改善はしましたが、もう少し頑張りたいところ。しかし本日は1日あたりの提出回数を超えてしまったよう(下記参照)です。。。

You have 3 submissions remaining today. This resets 14 hours from now (00:00 UTC).

次の改善ポイントは、ランクをグループ分け(TOP100を1, それ以下を2にする)するとか。1位と2位の売上差と3000位と3001位の売上差が同じとは思えないからです。もう少しまとめてやった方がいいのかなと。

もう一つはitem_priceを使用していない点です。売り上げに影響を与えている気がします。

次回で出来るかはちょっとわかんないですが、ここまで直感的に特徴量を選んできましたが、次あたりからはちゃんと可視化しながら取捨選択を考えていきます。あと決定木以外の学習も手を付けたいところです。

ということですこーしだけ改善した2回目の提出でした。今週中には何とか半分くらいの順位(4500位くらい)までいくよう頑張ります。

コメントを残す

メールアドレスが公開されることはありません。

CAPTCHA


Related Post