koji/メガネ男の日誌

日々の学び、活動状況を記録します。仕事のことは少なめ。

精度評価指標について調べてみた(後半)

f:id:kj_man666:20200816155723j:plain

先日記載したとおり、精度評価指標の後半部分としてコードで各精度評価指標を実装したまとめです。

長いので全文は記載しません、全文を確認される場合はこちらをご覧ください。

前半の理論部分は下記リンクからご覧ください。

megane-man666.hatenablog.com

概要:
データセットHousePriceコンペ
学習モデル:LightGBM
評価指標:MSE、MAE、決定係数、RSME

以降の精度結果は、train データをホールドアウト法で分割した30%部分の検証用データの予測値と実績値を比較しています。

1.欠損値を含まない数値データを特徴量とする

単純に欠損値を含まず、カテゴリデータを除く数値データのみを特徴量とします。

LightGBMは欠損値を含んでいても回せるのですが、他の欠損値処理が必要なモデルで回す場合も考慮して対象外としています。

結果は以下のとおりでした。

MSE :718051766.5529627
MAE :16540.0487430681
決定係数 :0.8970991518382367
RMSE :26796.48795183732

2.1 に加え、欠損値処理を行った数値データを特徴量とする

欠損値の割合が2割超の項目は特徴量から除外します。

欠損値の割合が2割以下の項目については、trainデータについては行を削除し、testデータについては中央値に置換します。

f:id:kj_man666:20200830103146p:plain

train_miss_ratio ...トレインデータの欠損値の割合
test_miss_ratio ... テストデータの欠損値の割合
NaN ... トレインデータ、テストデータいずれかに欠損値があり、一方には欠損値がない

# 欠損値の割合
train_miss_ratio = pd.DataFrame(train.isnull().sum()[train.isnull().sum() != 0]/train.isnull().count()[train.isnull().sum() != 0]*100, columns=["train_miss_ratio"])

test_miss_ratio = pd.DataFrame(test.isnull().sum()[test.isnull().sum() != 0]/test.isnull().count()[test.isnull().sum() != 0]*100, columns=["test_miss_ratio"])

# trainデータとtestデータで比較
pd.concat([train_miss_ratio, test_miss_ratio], axis=1)
MSE :1050826489.8539871
MAE :19378.48196261921
決定係数 :0.8685064360941711
RMSE :32416.45399876407

特徴量を増やしすぎたこと、数値データの欠損値を中央値で置き換えたことが悪影響したのか、精度が悪化してしまいました。

なお、前述のとおりLightGBMは欠損値を含んでいても回せるのですが、他の欠損値処理が必要なモデルで回す場合も考慮して欠損値処理しています。

3.2 に加え、ラベルエンコーディングしてカテゴリデータも特徴量とする

ラベルエンコーディングすることでカテゴリデータも特徴量に追加しています。

# ラベルエンコーディング
from sklearn import preprocessing
encorder = preprocessing.LabelEncoder()

# object型のカテゴリデータのリストを作成
cat_list = list(train.select_dtypes(include=object).isnull().sum()[train.select_dtypes(include=object).isnull().sum() > 0].index)

# ラベルエンコーディングは欠損値があるとできないので missing に置き換える
for i in cat_list:
    train3[i].fillna("missing", inplace=True)

for i in cat_list:
    test3[i].fillna("missing", inplace=True)

# ラベルエンコーディングを実施
for i in cat_list:
    train3[i] = encorder.fit_transform(train3[i])
    test3[i] = encorder.fit_transform(test3[i])

2 と同様に、欠損値が2割超の項目は特徴量から除外しています。

MSE :716059827.242882
MAE :16895.93255402717
決定係数 :0.8973846079209897
RMSE :26759.29422168832

若干ではありますが、精度は1と比べてもおおむね改善ました。

4.3 に加え、外れ値を処理する

目的変数である"SalePrice"と各項目の相関関係を散布図で確認し、外れ値を削除しました。

f:id:kj_man666:20200830105223p:plain

LotAreaの処理のみ抜粋

# LotArea が 30,000未満、かつ、SalePriceが600,000超の項目を除外
train = train.drop(train[(train['LotArea']<30000) & (train['SalePrice']>600000)].index)

# LotArea が 100,000超の項目を除外
train = train.drop(train[train['LotArea']>100000].index)

外れ値除外前

f:id:kj_man666:20200830105823p:plain

外れ値除外後

f:id:kj_man666:20200830105833p:plain

MSE :444408261.28365076
MAE :14892.964374929155
決定係数 :0.9052214999301952
RMSE :21080.992891314458

外れ値を除外することで、精度を向上させることができました。

まとめ

特徴量選択 1 欠損値を含まない数値データを特徴量とする

MSE :718051766.5529627
MAE :16540.0487430681
決定係数 :0.8970991518382367
RMSE :26796.48795183732

特徴量選択 2 欠損値を削除した数値データを特徴量とする

MSE :1050826489.8539871
MAE :19378.48196261921
決定係数 :0.8685064360941711
RMSE :32416.45399876407

特徴量選択3 ラベルエンコーディングしてカテゴリデータも対象にした場合

MSE :716059827.242882
MAE :16895.93255402717
決定係数 :0.8973846079209897
RMSE :26759.29422168832

特徴量選択4 外れ値を除外した場合

MSE :444408261.28365076
MAE :14892.964374929155
決定係数 :0.9052214999301952
RMSE :21080.992891314458

外れ値を除外することで、精度が向上しました!

以上になります、最後までお読みいただきありがとうございました。

参考サイト

medium-s.jp