どうもニコイチです。長く続けてきました、Pythonではじめるデータ分析もいよいよ最後のセッションです。前回は、重回帰モデルを作成し、予測を行う方法を学びました。今回は、最終回として、モデルの予測精度を向上させるための方法について解説します。
全編はこちらから

モデルの精度を改善する必要性
モデルを作って終わりではありません。実際のビジネスでは、より精度の高いモデルを作ることで、より正確な意思決定をすることができます。
例えば、宿泊料金の予測モデルの精度を向上させることで、最適な価格設定ができ、収益の最大化に繋げることができます。
モデルの精度改善のための代表的なアプローチ
モデルの精度を改善するためには、さまざまなアプローチがありますが、今回は代表的な3つのアプローチについて解説します。
- データ量の変更: モデルの学習に使うデータ量を調整します。
- アルゴリズムの変更・チューニング: モデルの種類を変更したり、モデルのパラメータを調整したりします。
- 特徴量エンジニアリング: モデルの学習に使う説明変数(特徴量)を加工・選択します。
今回は、特に特徴量エンジニアリングに焦点を当てて解説します。
特徴量エンジニアリングとは?
特徴量エンジニアリングとは、モデルの予測精度を向上させるために、データから特徴量を作り出したり、既存の特徴量を選択したりすることです。
- 特徴量作成: データから新しい特徴量を生成すること(例:年齢から年齢層を作る)
- 特徴量選択: 予測に不要な特徴量を削除すること(例:相関の低い特徴量を削除する)
特徴量エンジニアリングは、モデルの予測精度を向上させるための最も重要なステップの1つです。
特徴量作成
予測に役立ちそうな情報をデータから加工して作り出すことを特徴量作成と言います。
例えば、年齢データがある場合、年齢層という特徴量を作成することで、モデルが年齢という情報をより理解しやすくなります。
また、複数のデータを集約したり、基本統計量を作成したりすることも、特徴量作成の一環です。
特徴量選択
特徴量選択とは、モデルに不要な特徴量を削除することで、過学習を防ぎ、モデルをよりシンプルにするための手法です。
過学習は、例えるなら「テストの過去問ばかりを丸暗記して、初めて見る問題に対応できない」ような状態です。特徴量が多すぎると、モデルが学習データに過剰に適合し、汎化性能が低下する可能性があります。
特徴量選択の代表的な手法としては、以下のものがあります。
- フィルタ法: 相関係数や分散分析などの統計的な指標を使って特徴量を選択する手法。
- ラッパー法: 特徴量を出し入れしながら、モデルの予測精度を評価する手法(例:ステップワイズ法)
- 組み込み法: モデルの学習過程で、自動的に特徴量を選択する手法(例:Lasso回帰)
オッカムの剃刀
特徴量を選択する上で、オッカムの剃刀という考え方が役に立ちます。オッカムの剃刀とは、「必要以上に多くの仮説を立てるべきではない」という考え方で、よりシンプルで説明しやすいモデルほど良いとされます。
今回のデータでモデルを改善してみよう
それでは、実際に宿泊価格について_demo.csv のデータを使って、モデルの精度を改善してみましょう。
1. データの確認
まず、Mission 2 で確認した内容を思い出しましょう。
- bathrooms の値が 8 の時、価格の中央値が極端に低い
- これは room_type が Shared room である物件に多く見られる現象である
2. room_type ごとにモデルを作成する
room_type ごとにデータの特徴が異なるため、今回は room_type ごとにモデルを作成してみましょう。
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
import numpy as np
from sklearn.metrics import mean_squared_error as MSE
import seaborn as sns
import matplotlib.pyplot as plt
# CSVファイルの読み込み
data = pd.read_csv('宿泊価格について_demo.csv')
select_columns = ['room_type','accommodates','bed_type','bathrooms','cleaning_fee']
# room_typeがEntire home/aptのデータのbathroomsとyの箱ひげ図を書きましょう。
sns.boxplot(data=data[data["room_type"]=="Entire home/apt"],x="bathrooms",y="y")
plt.show()
# room_typeがShared roomのデータのbathroomsとyの箱ひげ図を書きましょう。
sns.boxplot(data=data[data["room_type"]=="Shared room"],x="bathrooms",y="y")
plt.show()
# room_type別にデータを分割
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)
# entire
# モデルの準備
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)
# private
# モデルの準備
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)
# share
# モデルの準備
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)
room_type ごとにモデルを作成した結果、RMSEが以下のように改善されました。
- 学習データRMSE: 135 -> 131
- 評価データRMSE: 131 -> 123
3. モデルを使って適正価格を算出する
最後に、作成したモデルを使って、自社物件の適正価格を算出してみましょう。
# property.csvを読み込んで変数mydataに代入しましょう。
mydata = pd.read_csv("property.csv")
# cleaning_feeがt,fになっているので1,0に変換してください。
def change_tf(x):
if x =="t":
return 1
else:
return 0
mydata['cleaning_fee'] = mydata["cleaning_fee"].apply(change_tf)
select_columns = ['room_type','accommodates','bed_type','bathrooms','cleaning_fee']
# データの分割
data_entire = mydata[mydata["room_type"]=="Entire home/apt"]
data_private = mydata[mydata["room_type"]=="Private room"]
data_share = mydata[mydata["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)
# 予測
pred_e = model_e.predict(dummy_data_entire)
pred_p = model_p.predict(dummy_data_private)
pred_s = model_s.predict(dummy_data_share)
print(pred_e)
print(pred_p)
print(pred_s)
つまずきやすいポイント
- データ量の変更:
- データ量が少ないと、モデルは学習不足になり、予測精度が低くなる。
- データ量が多すぎると、過学習を起こす可能性がある。
- アルゴリズムの変更・チューニング:
- モデルのアルゴリズムには、それぞれ得意な問題と不得意な問題がある。
- モデルのパラメータは、調整することで、精度を向上させることができる。
- 特徴量エンジニアリング:
- 特徴量作成は、予測に役立ちそうな情報をデータから作り出すこと。
- 特徴量選択は、モデルに不要な特徴量を削除すること。
まとめ
今回は、モデルの予測精度を向上させるための方法について学びました。
- モデルの精度を改善することで、より良い意思決定が可能になる。
- モデルの精度を改善するためには、データ量の変更、アルゴリズムの変更、特徴量エンジニアリングなどがある。
- 特徴量エンジニアリングとは、モデルの予測精度を向上させるために、データから特徴量を作り出したり、既存の特徴量を選択したりすること。
- 特徴量作成は、予測に役立ちそうな情報をデータから作り出すこと。
- 特徴量選択は、モデルに不要な特徴量を削除すること。
今回の内容を参考に、ぜひデータ分析に挑戦してみてください!
この講座を通して、Pythonを使ったデータ分析の基礎を学ぶことができました。データ分析は奥深く、学ぶことはまだまだたくさんありますが、まずは今回学んだ内容をしっかりと身につけて、データ分析の世界を楽しんでください!
今回の記事はここまでです。次回は、今回の内容を実際にPythonコードで一連に取り組みます。お楽しみに!
コメント