はじめに
この記事はデータ分析の定石というシリーズの1つになります。シリーズでは実データ分析をいくつかのフェーズに分けてまとめています。今回はそのうちの「モデル選択と検証評価」に焦点を当てています。
シリーズ全体の流れはこちらになります。
【実践】カリフォルニア住宅価格予測で学ぶ、データ分析の定石
PyCaretによるモデル活用
このフェーズでは、特徴量エンジで得られた選択特徴量をもとに、本格的にモデル活用を進めます。この際に機械学習モデルのローコード実装を可能にするライブラリ、PyCaretを利用します。このライブラリは、仮説検証や特徴量エンジニアリングといった重要なタスクに集中できるようにすることを開発目的としており、非常にいろんなことができます。
ここでは、特にPyCreatの以下表のような特徴の恩恵を受けて分析を進めます。
| 特徴 | 説明 |
|---|---|
| ローコード | 数行のコードで、複雑な処理(前処理、モデル比較、ハイパーパラメータチューニングなど)を実行できる |
| ベストモデル選択 | 様々なタスク(分類、回帰、クラスタリングなど)に対する機械学習アルゴリズムが用意されており、選択したタスクに対してモデル精度を比較、ベストなモデルを選定できる |
| 性能診断プロット | ROC曲線、混同行列、残差プロット、特徴量重要度など、モデルの性能を詳細に診断するための多数のプロットを生成できるため、モデルの結果の分析ができる |
具体的な手順は以下のようになります。
・検証用データと評価用データに分割、特徴量をスケーリング
・複数のモデルの性能比較
・ベストモデルを選択し性能診断プロットで結果を観察
・評価用データの特徴量をスケーリングした後、目的変数を予測
・元々の目的変数との誤差(汎化誤差)を確認しモデルを評価
これら全てをPycaretで実装していきます。
それでは分析を進めていきましょう!
性能指標と分割とスケーリング
機械学習で評価するのは、未知のデータに対してもうまく予測できること、汎化性能です。
そこで、ここでは既存のデータをあたかも未知のデータとして扱います。具体的には、学習に利用する検証用データと、学習結果をもとに予測する評価用データに分割します。
またモデルを適用する前には、一般に、各特徴量のオーダーを揃える、スケーリングを行います。それはオーダーやばらつきの大きい特徴量が目的変数に強く影響してしまい、オーダーやばらつきが小さいけれども目的変数に影響を与える特徴量が埋もれてしまう場合があるためです。
ここで「場合」と言ったのは理由があります。実は、モデルの種類によっては、特徴量のオーダーを気にしないでも良いものもあります。以下のような表はその分類を表しています。
| 分類 | モデルの動作原理 | モデル例 | スケーリングの必要性 |
|---|---|---|---|
| 距離ベース / 勾配ベースモデル | 複数の特徴量(ベクトル)どうしの幾何学的距離、または特徴量の勾配に基づいて学習を行う。 | SVM, K-近傍法 (KNN), ニューラルネットワーク | ✅ 必要 |
| 決定木ベース / 順序ベースモデル | データの順序と単一特徴量ごとの閾値に基づいて分割を行う。距離やスケールには依存しない。 | 決定木 (DT), ランダムフォレスト (RF), 勾配ブースティング系 (XGBoost, LightGBM) | ❌ 不要 |
例えば、SVMなど距離を使うモデル場合、特徴量ごとに数値のオーダーが異なると、オーダーが大きい方に引っ張られてしまうので、オーダーを揃えるスケーリングが必要です。一方、決定木系などは、1つの特徴量の閾値を決める操作を繰り返すモデルであり、この場合の閾値を決める指標は、値ではなく、相対的な大小関係や順番になるので、スケーリングは必要ありません。
ただPyCaretは、どちらの類のモデルも同時に比較できます。そこで、スケーリングをして比較します。今回は、よく使われるZ-Scoreを採用します。
以上の分割とスケーリングを実装します。なんと、set()という関数の引数の設定により一行で処理完了します。
from sklearn.metrics import mean_absolute_error, mean_absolute_percentage_error
from pycaret.regression import *
# pycaretのセットアップ
# targetに目的変数('Price')を指定するだけで、
# どの特徴量を使うか、前処理の方法などを自動で判断してくれます。
col_feature_objective = ['一人あたり_世帯所得','家の築年数', '部屋の数', '寝室の数', '居住人数', '世帯人数','Coast_dist',
'euclid_dist_to_Los_Angeles', 'euclid_dist_to_San_Francisco',
'euclid_dist_to_San_Diego', 'euclid_dist_to_Sacramento','euclid_dist_to_San_Jose',
'euclid_dist_to_Santa_Barbara',
'euclid_dist_to_Irvine','dist_to_nearest_city','Price']
# 検証用:評価用=0.9:0.1,分割はランダム、シード値は固定(123)
# Z-Score標準化を実施
reg_setup = setup(data=data1[col_feature_objective], target='Price', train_size=0.9, session_id=123
,normalize=True,normalize_method='zscore')
各引数の情報は表のような意味を示しています。
| 引数名 | 意味 | 詳細 |
|---|---|---|
| target='Price' | 目的変数 | モデルが予測する列名前を指定します。ここでは、'Price'列を予測対象とします。 |
| train_size=0.9 | 訓練データのサイズ(割合) | データセット全体のうち、モデルの検証と評価に使用する割合を指定します。90%を検証用、残りの10%を評価用のテストセットとして隔離します。 |
| session_id=123 | 乱数シード | 実験の再現性を確保するための乱数シードを指定します。この値を固定することで、データの分割やモデル訓練の結果が毎回同じになります。 |
| normalize=True | スケーリングの有効化 | 特徴量に対してスケーリング処理を適用することを指示します。Trueに設定することで、特徴量の値の範囲が調整されます。 |
| normalize_method='zscore' | スケーリング手法の指定 | normalize=Trueの場合に適用する手法を指定します。'zscore'は標準化を意味し、特徴量を平均0、標準偏差1に変換します。 |
モデルの性能比較
検証用データで様々なモデルの性能を比較します。
PyCreatの回帰タスクでは例えば以下のようなモデルを扱えます。
| モデルID | モデル名 (Model Name) | 概要と特徴 |
|---|---|---|
| lr | Linear Regression (線形回帰) | 基本的な回帰モデル。特徴量と目的変数の間に線形の関係を仮定します。 |
| lasso | Lasso Regression | 線形回帰にL1正則化を導入したモデル。特徴量の選択(スパースな解)を自動で行い、過学習を抑制します。 |
| ridge | Ridge Regression | 線形回帰にL2正則化を導入したモデル。重みを均等に小さくすることで、多重共線性の影響を抑え、過学習を抑制します。 |
| en | Elastic Net | Lasso (L1) と Ridge (L2) の両方の正則化を組み合わせたモデル。L1の変数選択機能とL2の安定性の両方を持ちます。 |
| dt | Decision Tree Regressor (決定木) | データを再帰的に分割し、予測を行います。解釈が容易ですが、過学習しやすい傾向があります。 |
| rf | Random Forest Regressor (ランダムフォレスト) | 複数の決定木を組み合わせたアンサンブル学習モデル。決定木の過学習を抑え、高い精度と安定性を持ちます。 |
| et | Extra Trees Regressor (Extra Trees) | ランダムフォレストに似ていますが、分割の際にランダム性を高めたモデル。計算速度が速いことが特徴です。 |
| gbr | Gradient Boosting Regressor | 弱い学習器(主に決定木)を順次学習し、前の学習器の誤りを補正していくアンサンブル学習モデル。高い予測精度を誇ります。 |
| ada | AdaBoost Regressor | 誤分類しやすいデータに重みを付けて、弱い学習器を繰り返し学習させることで性能を向上させるアンサンブル学習モデル。 |
| lightgbm | Light Gradient Boosting Machine | Microsoftが開発した勾配ブースティングフレームワーク。高速な学習と高い予測精度が特徴で、大規模データに強いです。 |
| xgboost | Extreme Gradient Boosting | 勾配ブースティングを効率的かつスケーラブルに実装したフレームワーク。コンペティションで非常に高い実績があります。 |
| catboost | CatBoost Regressor | Yandexが開発した勾配ブースティングフレームワーク。カテゴリ変数の扱いに優れており、前処理なしで高い精度を出せることが特徴です。 |
| knn | K Neighbors Regressor (K近傍法) | 訓練データの中で最も近いK個のデータ点の平均値(または中央値)で予測を行うノンパラメトリックな手法です。 |
| svm | Support Vector Regression (SVR) | サポートベクターマシンを回帰問題に適用したモデル。マージン内の誤差を許容しながら最適化を行います。 |
| mlp | MLP Regressor (ニューラルネットワーク) | 多層パーセプトロン(MLP)を用いた回帰モデル。複雑な非線形関係を学習できますが、計算コストが高く、ハイパーパラメータ調整が必要です。 |
| dummy | Dummy Regressor | 常に平均値や中央値など、単純な固定値を返すためのダミーモデル。他のモデルの性能を評価する際のベースラインとして使用されます。 |
各モデルの詳細については別の記事を参考にしてください。
このように、PyCaretでは非常にたくさんのモデルが扱えるのですが、特にすごいのがこれらを関数compare_models()でいっぺんに比較できる点です!
性能評価指標として、このシリーズの冒頭に述べたようにMAEを評価指標として実装します。
# 複数の回帰モデルを比較
# このステップだけで、多くの回帰モデルが学習され、性能が評価されます。
best_model = compare_models(sort='MAE',exclude=['knn', 'lr','dummy','omp','br'])
ここで、MAEが高いほど情報が上位にくるように引数sortに代入しています。
また、比較対象外から外すモデルIDを、引数excludeに代入しています。
分析結果の考察
Extra Trees Regressor (Extra Trees) がベストで、MAE=0.2706に来ています。
特徴量エンジでは特徴量の違いを比較するため、決定木回帰(Decision Tree Regressor)を使用しました。今回こちらのモデルは、MAE=0.3944となっています。2つのMAEの比を取ると、0.2706/0.3944=0.7であり、モデルの違いによって3割程度予測誤差が縮まっています。
ベストモデルの性能診断プロット
回帰モデルの性能を診断するために、Y-YプロットとFeature Importanceの2種類のプロットを確認します。
これら2つのプロットにより、モデルが「どれだけ正確か」(Y-Yプロット)と「なぜその予測をしたか」(Feature Importance)の両面から総合的に診断できます。
Y-Yプロット (実測値 vs. 予測値)
このプロットは、モデルの**適合度と予測の偏り(バイアス)**を視覚化します。
理想: 点群が**傾き1、切片0の直線(理想線)**に密接に沿って並びます。
診断: 点群が理想線から拡散しているほど誤差が大きい。特定の価格帯(例:高価格帯)で点群が線の上または下に偏っている場合、過小評価または過大評価のバイアスが存在することを示します。
それでは分析します。
plot_model(best_model, plot='error')
結果の考察
実測値y=3から5にかけて予測値が大きくずれている傾向があります。
そして、実測値yのサンプル数が3から5にかけてどんどん減ってきている傾向があります。
これは高価格帯のデータ希少性による不安定な閾値採用が起因してそうだと考えられます。
・1.閾値の探索が不安定になる
決定木モデル(Extra Treesなど)は、常に**最も誤差(不純度)を減らせる最適な分割点(閾値)**を探しています。
低〜中価格帯ではデータが多いため、モデルも安定した最適な閾値を採用します。
一方、高価格帯ではデータが数少ないため、モデルとしてもどこを閾値として良いか判断できず、また例外的な値を分離しようとしたりして、不安定な閾値を採用してしまいます。
・2.汎用性のないルールが生まれる
不安定な閾値で作られた分割ルールは、そのトレーニングデータ内の数少ない事例にしか当てはまらない、極めて特殊なルールになってしまいます。
訓練時:この特殊なルールにより、トレーニングデータにおける誤差は最小化されます(過学習)。
予測時:このルールがテストデータの新しい物件に適用されると、その物件が特殊なルールに合わないために予測が大きく外れてしまいます。
そのため、Priceのデータのばらつきをなくす、対数変換や、Yeo-Johnson変換などの処理を施した目的変数で予測すると高価格帯もうまく予測できるようになるかもしれません。
特徴量の重要度 (Feature Importance)
このプロットは、モデルの予測に対してどの特徴量が最も強く貢献しているかを示し、モデルの解釈性を高めます。
目的: モデルの予測根拠を理解する。
診断:
重要度の高い特徴量: 予測ロジックの中心であり、その特徴量に関するビジネス的な洞察を深めるべきです。
重要度の低い特徴量: モデルのノイズとなっている可能性があり、削除や改善を検討すべきです。
エンジニアリングの評価: 独自に作成した特徴量が上位にあれば、その特徴量エンジニアリングが有効であったことを証明します。
plot_model(best_model, plot='feature')
モデル評価
predictions = predict_model(best_model)
おわりに
モデル選択が有効に働いたことを確認しました。
2万7千ドルの誤差が出ています。さてデータクレンジングの分析により、住宅価格50%の時、1.797000 、17万9千ドルなので、相対誤差は15.1%あります。現実のツールとして、このモデルを使うにはまだまだ改良が必要そうです。
この場合は分析結果を考察したように、データの偏りを補正するような特徴量エンジニアリングを行い、再度モデル選択が必要でしょう。
このようにデータ分析から考察して、
また、今回はfeature importanceを使いましたが、
これだと、寄与が小さいものは埋もれてしまったり、相関が高い特徴量の一方を過小評価してしまう傾向があります。この場合は、shap値のような特徴量ごとに解釈できるようなもので解釈を進めていくのが良いでしょう。



