今回は研修の一環で、過去のkaggleコンペに取り組みましたので
簡単にまとめてみました。
・Mercari Price Suggestion Challenge
メルカリの商品情報から、Ridge回帰を用いて価格を予想していきます。
1. モジュールの用意
import numpy as np
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.preprocessing import LabelBinarizer
from scipy.sparse import csr_matrix, hstack
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Ridge
from sklearn.metrics import mean_squared_log_error
## 2. データの準備 データを読み込みます。
train = pd.read_csv('train.tsv', sep='\t')
test = pd.read_csv('test.tsv', sep='\t')
データ数を確認しておきます。
print(train.shape)
print(test.shape)
# (1482535, 8)
# (693359, 7)
train データと test データを結合します。
all_data = pd.concat([train, test])
all_data.head()
データの基本情報を確認します。
all_data.info(null_counts=True)
'''
<class 'pandas.core.frame.DataFrame'>
Int64Index: 2175894 entries, 0 to 693358
Data columns (total 9 columns):
brand_name 1247687 non-null object
category_name 2166509 non-null object
item_condition_id 2175894 non-null int64
item_description 2175890 non-null object
name 2175894 non-null object
price 1482535 non-null float64
shipping 2175894 non-null int64
test_id 693359 non-null float64
train_id 1482535 non-null float64
dtypes: float64(3), int64(2), object(4)
memory usage: 166.0+ MB
'''
各列データのユニーク数(重複をカウントしない)を調べます。
print(all_data.brand_name.nunique())
print(all_data.category_name.nunique())
print(all_data.name.nunique())
print(all_data.item_description.nunique())
# 5289
# 1310
# 1750617
# 1862037
## 3. 前処理 データを各列ごとに前処理していきます。
今回は文字データが多いので、BoWベクトル や TF-IDF を用いて、データを整えていきます。
その際、他のラベルエンコーディングする特徴量については、データ量が大きくなりすぎてしまうため
疎行列(成分に 0 が多い行列=スパース行列)に変換して、圧縮をしておきます。
# name
cv = CountVectorizer()
name = cv.fit_transform(all_data.name)
# item_description
all_data.item_description.fillna(value='null', inplace=True)
tv = TfidfVectorizer()
item_description = tv.fit_transform(all_data.item_description)
# category_name
all_data.category_name.fillna(value='null', inplace=True)
lb = LabelBinarizer(sparse_output=True)
category_name = lb.fit_transform(all_data.category_name)
# brand_name
all_data.brand_name.fillna(value='null', inplace=True)
brand_name = lb.fit_transform(all_data.brand_name)
# item_condition_id, shipping
onehot_cols = ['item_condition_id', 'shipping']
onehot_data = csr_matrix(pd.get_dummies(all_data[onehot_cols], sparse=True))
最後に、これらのデータを結合し、疎行列データに変換しておきます。
X_sparse = hstack((name, item_description, category_name, brand_name, onehot_data)).tocsr()
## 4. モデルの作成 結合データ all_data について train データには目的変数がありますが、test データにはないので X のデータ量を y と同じサイズ(= tran データの行数)にしておきます。
nrows = train.shape[0]
X = X_sparse[:nrows]
y(価格データ)にはデータにばらつきがあり、予測結果に影響を及ぼしてしまうため
標準化でも良いですが、今回は対数変換をしておきます。
尚、y の値が 0 でも問題ないように、$\log(y+1)$ で変換を行います。
y = np.log1p(train.price)
y[:5]
'''
0 2.397895
1 3.970292
2 2.397895
3 3.583519
4 3.806662
Name: price, dtype: float64
'''
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
ridge = Ridge()
ridge.fit(X_train, y_train)
'''
Ridge(alpha=1.0, copy_X=True, fit_intercept=True, max_iter=None,
normalize=False, random_state=None, solver='auto', tol=0.001)
'''
## 5. 性能評価
y_pred = ridge.predict(X_test)
今回は RMSE(コンペ用に少し改良)の指標で評価します。
モデリングする前に y を対数変換したので、モデリング後で元に戻す必要がありますが
評価式の中で、その処理を行っています。
def rmse(y_test, y_pred):
return np.sqrt(mean_squared_log_error(np.expm1(y_test), np.expm1(y_pred)))
rmse(y_test, y_pred)
# 0.4745184301527575
以上より、メルカリの商品情報から価格予測をし、評価することができました。
今回は初学者の方に向けて、記事をまとめさせていただきましたが
少しでも参考になったようでしたら、LGBTをしていただけますと幸いです。
ご精読いただきありがとうございました。