SIGNATE Quest③ 宿泊価格推定


もくじ:回帰問題の処理手順

①欠損値の処理(①と②を繰り返す)
②基本的手順に沿ってデータの特徴を把握する
  基本統計量
  可視化
③特徴量生成
④重回帰モデルの作成と予測の実行
⑤予測結果の評価(RMSE)
⑥モデルの予測精度改善(⑤に戻る)

欠損値の処理

重要な関数

  DataFrame.isnull().sum()
  DataFrame.dropna()
  DataFrame.fillna()

データ操作

# bedsがNaNになっているデータの抜き出し(SQLで言う select * where )
beds_nan_data = DataFrame[DataFrame['beds'].isnull()]

# bed_typeの種類ごとの件数を表示
print(beds_nan_data['bed_type'].value_counts())

# beds,bedrooms,bathroomsに欠損値を含むデータを削除
data = data.dropna(subset=['beds','bedrooms','bathrooms'])

# 変数mean_valにreview_scores_ratingの平均値を代入してください。
mean_val = data['review_scores_rating'].mean()

# review_scores_ratingの欠損値を平均値で補完してください。
data['review_scores_rating'] = data['review_scores_rating'].fillna(mean_val)

データの可視化

基本統計量

#要素の内容を表示
print(DataFrame['カラム名'].unique())
#要素の数を表示
print(DataFrame['カラム名'].nunique())
#重要:要素ごとの数を降順で表示
print(DataFrame['カラム名'].value_counts())

#2,4,7,7,10,12,13,17,20,22,30の統計量を表示する
#平均値、中央値、最大値などの値と最頻値を表示
s = pd.Series([2,4,7,7,10,12,13,17,20,22,30])
print(s.describe())
print(s.mode())

ヒストグラム、棒グラフ

# 変数dataからy列のみを抜き出し、変数yに代入しましょう
y = data['y']
# ヒストグラムの可視化
y.plot.hist(title='宿泊価格')
# 可視化結果を表示する為に必要な関数
plt.show()

# value_counts()の結果を棒グラフで表示
v = data['カラム名'].value_counts()
v.plot.bar()
plt.show()

外れ値の削除

# yが10以上のデータを抽出したい(10未満を削除したい)ので、条件はdata['y'] >= 10

# 削除前の行数を確認
before_rows = data.shape[0]
print(before_rows)

# 削除
data = data[data['y'] >= 10]

# 削除後の行数を確認
after_rows = data.shape[0]
print(after_rows)

箱ひげ図の描画

# 箱ひげ図の描画
sns.boxplot(data=DataFrame, x='横カラム名', y='縦カラム名')

# 表示範囲を制限
plt.ylim(0,600)

plt.show()

散布図の描画

DataFrame.plot.scatter(x='横カラム名', y='縦カラム名')
plt.show()

複数の条件で抜き出す

# dataからbathroomsが0.0でyが1000ドル以上のデータを抜き出して、表示させてください。
# 複数条件を満たす場合は DataFrame[(条件) & (条件)]
data_tmp = data[(data['bathrooms']==0.0) & (data['y'] >= 1000)]

特徴量の加工

関数

自作関数だと関数を定義した後に関数を呼び出す必要があるが、lambda関数だと関数定義と呼び出しが1行でできる。

# property.csvを読み込んで変数dataに代入しましょう。
mydata = pd.read_csv('property.csv')

# cleaning_feeがt,fになっているので1,0に変換してください。
def change_tf(x):
    if x == 't':
        return 1
    elif x == 'f':
        return 0
mydata['cleaning_fee'] = mydata['cleaning_fee'].apply(change_tf)

評価関数

RMSEの計算方法

# ライブラリのインポート
import numpy as np
from sklearn.metrics import mean_squared_error as MSE

# 変数の準備
actual = [3,4,6,2,4,6,1]
pred = [4,2,6,5,3,2,3]

# MSEの算出
mse = MSE(actual,pred)
print(mse)

# RMSEの算出
rmse = np.sqrt(mse)
print(rmse)

RMSEはscikit-learnに実装されていません。RMSEの平方根を取る前の値であるMSE(Mean Squared Error)は実装されています。MSEの平方根をとる部分を実装することでRMSEを算出しています。

線形回帰モデル

# LinearRegressionをインポートしましょう。
from sklearn.linear_model import LinearRegression

# モデルの準備
lr = LinearRegression()

# モデルを学習
lr.fit(X_train, y_train)

# 偏回帰係数の表示
print(pd.DataFrame(lr.coef_, index=X_train.columns))

# 切片の表示
print(lr.coef_)

# X_trainに対して予測するように空欄を埋めてください。
y_pred_train = lr.predict(X_train)

# 予測結果の確認
print(y_pred_train)

# 結果を丸めて表示
chk = int(round(y_pred_train[1]))

まとめ:説明変数、データ分割、モデル作成、モデル評価(RMSE)

# 予測に使用する説明変数、データ分割、モデル作成、モデル評価(RMSE)
select_columns = ['room_type','accommodates','bed_type','bathrooms','cleaning_fee']
dummy_data = pd.get_dummies(data[select_columns],drop_first=True)

X_train,X_test,y_train,y_test = train_test_split(dummy_data, data['y'], random_state = 1234)

lr = LinearRegression()
lr.fit(X_train, y_train)

y_pred_train = lr.predict(X_train)

# X_trainのRMSEを算出
rmse_train = np.sqrt(MSE(y_train, y_pred_train))

# 評価用に残しておいたX_testを使って予測
y_pred_test = lr.predict(X_test)

# X_testの予測に対するRMSEの算出
rmse_test = np.sqrt(MSE(y_test,y_pred_test))

# 学習および評価データに対するRMSEを表示
print(rmse_train)
print(rmse_test)

testデータに対するRMSEが約131であることから、このモデルは評価用データに対しては、実際の宿泊価格に対して、平均して131ドル程度の誤差がある予測をしていることが分かります。

3つのモデルを作成し、統合した結果の線形回帰分析結果を表示する


select_columns = ['room_type','accommodates','bed_type','bathrooms','cleaning_fee']

data_entire = data[data['room_type'] == 'Entire home/apt']
data_private = data[data['room_type'] == 'Private room']
data_share = data[data['room_type'] == 'Shared room']
dummy_data_entire = pd.get_dummies(data_entire[select_columns], drop_first=True)
dummy_data_private = pd.get_dummies(data_private[select_columns],drop_first=True)
dummy_data_share = pd.get_dummies(data_share[select_columns], drop_first=True)

X_train_e,X_test_e,y_train_e,y_test_e = train_test_split(dummy_data_entire, data_entire['y'], random_state = 1234)
X_train_p,X_test_p,y_train_p,y_test_p = train_test_split(dummy_data_private, data_private['y'], random_state = 1234)
X_train_s,X_test_s,y_train_s,y_test_s = train_test_split(dummy_data_share, data_share['y'], random_state = 1234)

model_e = LinearRegression()
model_e.fit(X_train_e, y_train_e)
pred_e_train = model_e.predict(X_train_e)
pred_e_test = model_e.predict(X_test_e)

model_p = LinearRegression()
model_p.fit(X_train_p, y_train_p)
pred_p_train = model_p.predict(X_train_p)
pred_p_test = model_p.predict(X_test_p)

model_s = LinearRegression()
model_s.fit(X_train_s, y_train_s)
pred_s_train = model_s.predict(X_train_s)
pred_s_test = model_s.predict(X_test_s)

# pred_e_train, pred_p_train, pred_s_trainを1つの配列にして、pred_trainに代入してください。
pred_train = np.concatenate([pred_e_train, pred_p_train, pred_s_train])
# 実際の値であるy_train_e,y_train_p,y_train_sを1つの配列にして、answer_trainに代入してください。
answer_train = np.concatenate([y_train_e,y_train_p,y_train_s])
# pred_train,answer_trainから全訓練データの予測値のRMSEを求め、rmse_trainに代入してください。
rmse_train = np.sqrt(MSE(pred_train, answer_train))

# 同様に全テストデータの予測値のRMSEを求め、rmse_testに代入してください。
pred_test = np.concatenate([pred_e_test, pred_p_test, pred_s_test])
answer_test = np.concatenate([y_test_e,y_test_p,y_test_s])
rmse_test = np.sqrt(MSE(pred_test, answer_test))

print(rmse_train)
print(rmse_test)

以上