【機械学習】Kaggel演習〜Mercari Price Suggestion Challenge〜

Kaggle演習第二弾!!

Mercari Price Suggestion Challenge

タイトルの通り、言わずと知れたフリマアプリのメルカリの価格予想チャレンジである。

まずはデータDL

411MBと結構重め。

データ取り込み

前回のTitanic : Machine Learning from Disaster同様にまずはPandasでデータ取り込み。

【機械学習】Kaggle演習〜Titanic : Machine Learning from Disaster〜

# データ型
types_dict_train = {'train_id':'int64', 'item_condition_id':'int8', 'price':'float64', 'shipping':'int8'}
types_dict_test = {'test_id':'int64', 'item_condition_id':'int8', 'shipping':'int8'}
# tsvファイルからPandas DataFrameへ読み込み
train = pd.read_csv('ファイルパスtrain.tsv', delimiter='\t', low_memory=True, dtype=types_dict_train)
test = pd.read_csv('ファイルパスtest.tsv', delimiter='\t', low_memory=True, dtype=types_dict_test)

データ確認

データを読み込んだらデータサイズの確認。

# trainとtestのサイズを確認
train.shape, test.shape
((1482535, 9), (693359, 8))

読み込んだデータのheadの確認。

train データの方には「price」headが1 列多い。headの説明は以下。

  • train_id or test_id – the id of the listing
  • name – the title of the listing. Note that we have cleaned the data to remove text that look like prices (e.g. $20) to avoid leakage. These removed prices are represented as [rm]
  • item_condition_id – the condition of the items provided by the seller
  • category_name – category of the listing
  • brand_name
  • price – the price that the item was sold for. This is the target variable that you will predict. The unit is USD. This column doesn’t exist in test.tsv since that is what you will predict.
  • shipping – 1 if shipping fee is paid by seller and 0 by buyer
  • item_description – the full description of the item. Note that we have cleaned the data to remove text that look like prices (e.g. $20) to avoid leakage. These removed prices are represented as [rm]

trainの基本統計量の確認

def display_all(df):
    with pd.option_context("display.max_rows", 1000, "display.max_columns", 1000): 
        display(df)
        
# trainの基本統計量を表示
display_all(train.describe(include='all').transpose())

「transpose」で列行入替。

文字列変換

文字列を値として持っている項目を「category」のデータタイプへ変換

データタイプを文字列からcategoryへ変換する項目(trainとtestで同項目)

  • category_name
  • item_description
  • name
  • brand_name
# trainデータを「category」へ変換
train.category_name = train.category_name.astype('category')
train.item_description = train.item_description.astype('category')
train.name = train.name.astype('category')
train.brand_name = train.brand_name.astype('category')
# testデータを「category」へ変換
test.category_name = test.category_name.astype('category')
test.item_description = test.item_description.astype('category')
test.name = test.name.astype('category')
test.brand_name = test.brand_name.astype('category')

欠損データの確認

# trainの欠損データ確認
train.isnull().sum(),train.isnull().sum()/train.shape[0]
# testの欠損データ確認
test.isnull().sum(),test.isnull().sum()/test.shape[0]

それぞれbrand_nameに欠損値が多くみられる。

ランダムフォレストの作成のためのデータクレンジング

左が前回使用した決定木イメージと右はランダムフォレストイメージ。

ランダムフォレストの方が精度が高い。

# データ結合のためtrainとtestのidカラム名を変更する
train = train.rename(columns = {'train_id':'id'})
test = test.rename(columns = {'test_id':'id'})
# 両方のセットへ「is_train」のカラムを追加
# 1 = trainのデータ、0 = testデータ
train['is_train'] = 1
test['is_train'] = 0
# trainのprice(価格)以外のデータをtestと結合
train_test_combine = pd.concat([train.drop(['price'], axis=1),test],axis=0)
# 念のためデータの中身を表示させましょう
train_test_combine.head()

データ数の確認

train_test_combine.shape
(2175894, 8)

連結させたデータ(train_test_combine)の文字列のデータを数値へ変換。

category形式に変換したら、pandasのcat.codesで数値へ変換。

# train_test_combineの文字列を「category」へ変換
train_test_combine.category_name = train_test_combine.category_name.astype('category')
train_test_combine.item_description = train_test_combine.item_description.astype('category')
train_test_combine.name = train_test_combine.name.astype('category')
train_test_combine.brand_name = train_test_combine.brand_name.astype('category')
# combinedDataの文字列を「.cat.codes」で数値へ変換する
train_test_combine.name = train_test_combine.name.cat.codes
train_test_combine.category_name = train_test_combine.category_name.cat.codes
train_test_combine.brand_name = train_test_combine.brand_name.cat.codes
train_test_combine.item_description = train_test_combine.item_description.cat.codes

変換が完了したらコンバイン。

# 「is_train」のフラグでcombineからtestとtrainへコンバイン
df_test = train_test_combine.loc[train_test_combine['is_train'] == 0]
df_train = train_test_combine.loc[train_test_combine['is_train'] == 1]
# 「is_train」をtrainとtestのデータフレームから削除
df_test = df_test.drop(['is_train'], axis=1)
df_train = df_train.drop(['is_train'], axis=1)
# サイズの確認
df_test.shape, df_train.shape
((693359, 7), (1482535, 7))

「df_train」(訓練データ)へ「train」の価格(price)を戻して、log関数処理

ランダムフォレスト作成

scikit-learnのRandomForestRegressorで作成

# x = price以外の全ての値、y = price(ターゲット)で切り分ける
x_train, y_train = df_train.drop(['price'], axis=1), df_train.price
# モデルの作成
m = RandomForestRegressor(n_jobs=-1, min_samples_leaf=5, n_estimators=200)
m.fit(x_train, y_train)
# スコアを表示
m.score(x_train, y_train)

決定係数は・・・0.74

実際の予測値の算出とCSVファイルの書き出し

# 作成したランダムフォレストのモデル「m」に「df_test」を入れて予測する
preds = m.predict(df_test)
# 予測値 predsをnp.exp()で処理
np.exp(preds)
# Numpy配列からpandasシリーズへ変換
preds = pd.Series(np.exp(preds))
# テストデータのIDと予測値を連結
submit = pd.concat([df_test.id, preds], axis=1)
# カラム名をメルカリの提出指定の名前をつける
submit.columns = ['test_id', 'price']
# CSVへ書き出し
submit.to_csv('submit_rf_base.csv', index=False)

完了

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA