Kaggle：Merucari（Ridge回帰）

今回は研修の一環で、過去のkaggleコンペに取り組みましたので
簡単にまとめてみました。

・[Mercari Price Suggestion Challenge](https://www.kaggle.com/c/mercari-price-suggestion-challenge)

メルカリの商品情報から、Ridge回帰を用いて価格を予想していきます。

## 1. モジュールの用意
```python

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
```
<br>
## 2. データの準備
データを読み込みます。

```python

train = pd.read_csv('train.tsv', sep='\t')
test = pd.read_csv('test.tsv', sep='\t')
```
データ数を確認しておきます。

```python

print(train.shape)
print(test.shape)

# (1482535, 8)
# (693359, 7)
```
train データと test データを結合します。

```python

all_data = pd.concat([train, test])
all_data.head()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725082/5b9ce46f-6de8-7631-5bdb-3967703c75db.png)

データの基本情報を確認します。

```python

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
'''
```
各列データのユニーク数（重複をカウントしない）を調べます。

```python

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
```
<br>
## 3. 前処理
データを各列ごとに前処理していきます。

今回は文字データが多いので、BoWベクトル や TF-IDF を用いて、データを整えていきます。

その際、他のラベルエンコーディングする特徴量については、データ量が大きくなりすぎてしまうため
疎行列（成分に 0 が多い行列＝スパース行列）に変換して、圧縮をしておきます。

```python
# name

cv = CountVectorizer()
name = cv.fit_transform(all_data.name)
```

```python

# item_description

all_data.item_description.fillna(value='null', inplace=True)

tv = TfidfVectorizer()
item_description = tv.fit_transform(all_data.item_description)
```

```python

# 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)
```

```python
# brand_name

all_data.brand_name.fillna(value='null', inplace=True)

brand_name = lb.fit_transform(all_data.brand_name)
```

```python

# item_condition_id, shipping

onehot_cols = ['item_condition_id', 'shipping']
onehot_data = csr_matrix(pd.get_dummies(all_data[onehot_cols], sparse=True))
```
最後に、これらのデータを結合し、疎行列データに変換しておきます。

```python

X_sparse = hstack((name, item_description, category_name, brand_name, onehot_data)).tocsr()
```
<br>
## 4. モデルの作成
結合データ all_data について
train データには目的変数がありますが、test データにはないので
X のデータ量を y と同じサイズ（= tran データの行数）にしておきます。

```python
nrows = train.shape[0]
X = X_sparse[:nrows]
```
y（価格データ）にはデータにばらつきがあり、予測結果に影響を及ぼしてしまうため
標準化でも良いですが、今回は対数変換をしておきます。

尚、y の値が 0 でも問題ないように、$\log(y+1)$ で変換を行います。

```python

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
'''
```

```python

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
```
```python

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)
'''
```
<br>
## 5. 性能評価

```python

y_pred = ridge.predict(X_test)
```

今回は RMSE（コンペ用に少し改良）の指標で評価します。

モデリングする前に y を対数変換したので、モデリング後で元に戻す必要がありますが
評価式の中で、その処理を行っています。

```python

def rmse(y_test, y_pred):
    return np.sqrt(mean_squared_log_error(np.expm1(y_test), np.expm1(y_pred)))
```

```python

rmse(y_test, y_pred)

# 0.4745184301527575
```

以上より、メルカリの商品情報から価格予測をし、評価することができました。

今回は初学者の方に向けて、記事をまとめさせていただきましたが
少しでも参考になったようでしたら、LGBTをしていただけますと幸いです。

ご精読いただきありがとうございました。