RMSEについてと、スコアを上げるための考え方

import pandas as pd
import numpy as np
import sklearn
import sklearn.metrics
import category_encoders as ce 
import matplotlib.pyplot as plt
import lightgbm as lgb
%matplotlib inline
path=''
test_data = pd.read_csv(path+'test_data.csv')
train_data = pd.read_csv(path+'train_data.csv')
published_data = pd.read_csv(path+'published_land_price.csv')
print(test_df.shape, train_df.shape, published_df.shape)
(34844, 27) (356344, 28) (2602, 116)
plt.hist(train_data['y'], bins=20)
plt.show()

plt.hist(np.log10(train_data['y']), bins=20)
plt.show()
pd.cut(train_data['y'], [-1, 1, 10, 100, 1000, 10000, 100000]).value_counts(normalize=True)
(10, 100]          0.838403
(100, 1000]        0.078741
(1, 10]            0.076123
(1000, 10000]      0.004771
(-1, 1]            0.001830
(10000, 100000]    0.000132
Name: y, dtype: float64
train_data['最寄駅:距離(分)'] = train_data['最寄駅:距離(分)'].replace('30分?60分','45')
train_data['最寄駅:距離(分)'] = train_data['最寄駅:距離(分)'].replace('1H?1H30','75')
train_data['最寄駅:距離(分)'] = train_data['最寄駅:距離(分)'].replace('1H30?2H','105')
train_data['最寄駅:距離(分)'] = train_data['最寄駅:距離(分)'].replace('2H?','120')
train_data['最寄駅:距離(分)'] = pd.to_numeric(train_data['最寄駅:距離(分)'], errors='coerce')
train_data['建築年'] = train_data['建築年'].dropna()
train_data['建築年'] = train_data['建築年'].str.replace('戦前','昭和20年')
train_data['年号'] = train_data['建築年'].str[:2]
train_data['和暦年数'] = train_data['建築年'].str[2:].str.strip('年').fillna(0).astype(int)
train_data.loc[train_data['年号']=='昭和','建築年(西暦)'] = train_data['和暦年数'] + 1925
train_data.loc[train_data['年号']=='平成','建築年(西暦)'] = train_data['和暦年数'] + 1988
l = ['最寄駅:距離(分)','容積率(%)','建築年(西暦)']
for name in l:
    mean = np.nanmean(train_data[name], axis=0)
    std = np.nanstd(train_data[name], axis=0)
    train_data[name] = (train_data[name] - mean)/std
train_data.describe()
id 市区町村コード 最寄駅:距離(分) 前面道路:幅員(m) 建ぺい率(%) 容積率(%) y 和暦年数 建築年(西暦)
count 356344.000000 356344.000000 3.462150e+05 193279.000000 350958.000000 3.509580e+05 356344.000000 356344.000000 2.735030e+05
mean 178172.500000 13140.019052 -1.358520e-13 6.257812 62.005482 -3.166953e-13 65.434766 20.850894 3.455073e-15
std 102867.796499 46.206047 1.000001e+00 4.902258 13.125221 1.000001e+00 315.011339 19.644583 1.000002e+00
min 1.000000 13101.000000 -1.096071e+00 1.000000 30.000000 -1.343050e+00 0.000500 0.000000 -3.782092e+00
25% 89086.750000 13110.000000 -5.877202e-01 4.000000 60.000000 -7.157682e-01 21.000000 3.000000 -6.865983e-01
50% 178172.500000 13117.000000 -2.827096e-01 5.000000 60.000000 -4.021274e-01 35.000000 17.000000 2.492487e-01
75% 267258.250000 13201.000000 2.256414e-01 6.000000 80.000000 2.251542e-01 53.000000 27.000000 7.531663e-01
max 356344.000000 13421.000000 1.110435e+01 90.000000 80.000000 6.497971e+00 61000.000000 64.000000 1.545037e+00
#使用する説明変数・目的変数を代入
model_input = train_data[['最寄駅:名称','最寄駅:距離(分)','容積率(%)','建築年(西暦)','y']]

#説明変数・目的変数についてnull値を含むレコードを除外
model_input = model_input.dropna(how='any', axis=0) 

#目的変数と説明変数を代入
X = model_input[['最寄駅:名称', '最寄駅:距離(分)', '容積率(%)', '建築年(西暦)']]
X = pd.get_dummies(X, drop_first=True).values
y = model_input['y'].values
print(X.shape, y.shape)
(262610, 648) (262610,)

----ここまではtutorialと同様-----

#5foldでモデルを作成、評価
from sklearn.model_selection import KFold
kf = KFold(n_splits=5, shuffle=True, random_state=1)
s = list(kf.split(X, y))
import sklearn
from sklearn.linear_model import LinearRegression as LR
from sklearn.metrics import mean_squared_error

for train_i, val_i in s:
    model = LR()
    model.fit(X[train_i], y[train_i])
    y_pred = model.predict(X[val_i])
    y_val = y[val_i]
    print('y_valの数:{}, 1000以上のy_valの数:{}, 100以下のy_valの数:{}'.format(len(y_val), len(y_val[y_val>1000]), len(y_val[y_val<100])))
    print('RMSE:', np.sqrt(mean_squared_error(y_val, y_pred)))
    print('1000以上をすべて当てた場合のRMSE:', np.sqrt(mean_squared_error(y_val, np.where(y_val>1000, y_val, y_pred))))
    print('100以下をすべて当てた場合のRMSE:', np.sqrt(mean_squared_error(y_val, np.where(y_val<100, y_val, y_pred))))
    break
y_valの数:52522, 1000以上のy_valの数:223, 100以下のy_valの数:48934
RMSE: 223.67193030133276
1000以上をすべて当てた場合のRMSE: 79.60272441095651
100以下をすべて当てた場合のRMSE: 218.30752617076064

今回の評価指標(RMSE)では全体の90%以上の100以下の値を推論するのはほとんど効果がなく、 全体の5%程度の1000以上の値を予測するのに注力した方が良いと考えられる

添付データ

  • topic.ipynb?X-Amz-Expires=10800&X-Amz-Date=20240418T014357Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIP7GCBGMWPMZ42PQ
  • Aws4 request&x amz signedheaders=host&x amz signature=664decc22047bf83fffea1a1b9e9542106e674a56dcc2b958d6846cded68b622
    chun1182

    こんな感じで考えているのですが、ご意見、コードのミスなどありましたらご指摘お願いします。 1000以上の値は5%じゃなくて0.5%ですね・・・

    Favicon
    new user
    コメントするには 新規登録 もしくは ログイン が必要です。