# Import train_test_split.from sklearn.model_selection import train_test_split
# Create features X and target y.
X = pd.DataFrame(housing.data, columns=housing.feature_names)[["AveRooms"]]
y = housing.target # Median house value in $100,000s# Split the dataset into training (80%) and testing (20%) sets.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)提供:
# Uses all features.import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# Load data set.
housing = fetch_california_housing()# Split into X, y.
X = pd.DataFrame(housing.data, columns=housing.feature_names)
y = housing.target # Median house value in $100,000s
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# Scale the data.
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)# Create model and fit it to the training data.
model = LinearRegression()
model.fit(X_train_scaled, y_train)# Make predictions.
y_pred = model.predict(X_test_scaled)# Calculate and print errors.
r2 = r2_score(y_test, y_pred)print(f"R-squared: {r2:.4f}")
mse = mean_squared_error(y_test, y_pred)print(f"Mean squared error: {mse:.4f}")
rmse = mse **0.5print(f"Root mean squared error: {rmse:.4f}")提供:
R-squared:0.5758
Mean squared error:0.5559
Root mean squared error:0.7456提供:
ここで Ri2 は、予測因子 Xi を他のすべての予測因子に対して回帰したときに得られる R2 値です。VIFが高いほど、その予測因子は他の変数と強く相関しています。
VIF = 1:多重共線性なし(理想的)。
VIF < 5:低〜中程度の多重共線性(概ね許容範囲)。
VIF > 5:高い多重共線性(相関の高い変数の削除や結合を検討)。
VIF > 10:深刻な多重共線性(強い冗長性の示唆)。
# Import libraries.import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
from statsmodels.stats.outliers_influence import variance_inflation_factor
# Load the dataset.
housing = fetch_california_housing()
X = pd.DataFrame(housing.data, columns=housing.feature_names)# Compute the correlation matrix.
corr_matrix = X.corr()# Identify pairs of features with high collinearity (correlation > 0.8 or < -0.8).
high_corr_features =[(col1, col2, corr_matrix.loc[col1, col2])for col1 in corr_matrix.columns
for col2 in corr_matrix.columns
if col1 != col2 andabs(corr_matrix.loc[col1, col2])>0.8]# Convert to a DataFrame for better visualization.
collinearity_df = pd.DataFrame(high_corr_features, columns=["Feature 1","Feature 2","Correlation"])print("\nHighly Correlated Features:\n", collinearity_df)# Compute Variance Inflation Factor (VIF) for each feature.
vif_data = pd.DataFrame()
vif_data["Feature"]= X.columns
vif_data["VIF"]=[variance_inflation_factor(X.values, i)for i inrange(X.shape[1])]# Print VIF values.print("\nVariance Inflation Factor (VIF) for each feature:\n", vif_data)提供:
Highly Correlated Features:
Feature 1 Feature 2 Correlation
0 AveRooms AveBedrms 0.8476211 AveBedrms AveRooms 0.8476212 Latitude Longitude -0.9246643 Longitude Latitude -0.924664
Variance Inflation Factor (VIF)for each feature:
Feature VIF
0 MedInc 11.5111401 HouseAge 7.1959172 AveRooms 45.9936013 AveBedrms 43.5903144 Population 2.9357455 AveOccup 1.0952436 Latitude 559.8740717 Longitude 633.711654提供:
AveBedrmsをモデルから除外してみましょう。
# Import libraries.import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import fetch_california_housing
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# Load California housing dataset.
housing = fetch_california_housing()# Create DataFrame and remove "AveBedrms" feature.
X = pd.DataFrame(housing.data, columns=housing.feature_names).drop(columns=["AveBedrms"])
y = housing.target # Median house value in $100,000s# Split data into training and testing sets.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# Scale the data (Standardization).
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)# Create a linear regression model and train it.
model = LinearRegression()
model.fit(X_train_scaled, y_train)# Make predictions on the test set.
y_pred = model.predict(X_test_scaled)# Calculate performance metrics.
r2 = r2_score(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)# Print evaluation metricsprint(f"R-squared: {r2:.4f}")print(f"Mean squared error: {mse:.4f}")print(f"Root mean squared error: {rmse:.4f}")提供:
R-squared:0.5823
Mean squared error:0.5473
Root mean squared error:0.7398提供:
線形回帰は、統計学と機械学習における基本的な手法で、変数間の関係をモデル化するのに役立ちます。簡単に言うと、1つ以上の要因に基づいて結果を予測できるようにするものです。不動産価格の算定、売上予測、リスク評価など、幅広い分野で活用されています。
このチュートリアルでは、scikit-learnにおける線形回帰を取り上げ、その仕組み、有用性、そしてscikit-learnを使った実装方法を解説します。最後には、データに基づいた予測のために線形回帰モデルを構築・評価できるようになります。
部屋数に対する住宅価格の散布図
線形回帰と機械学習
住宅価格の推定に限らず、線形回帰は機械学習において重要な役割を果たします。
シンプルでありながら、効率性・解釈性・汎用性の高さから、線形回帰は機械学習において不可欠なツールであり続けています。
線形回帰とscikit-learnライブラリ
scikit-learnライブラリを使うと、線形回帰を簡単に実装できます。このライブラリには多くの利点があります。
model.fit(X_train, y_train)の1行で済みます。scikit-learnが初めての場合は、Pythonライブラリを実践的に学べるMachine Learning with scikit-learnコースをご覧ください。
線形回帰を理解する
単回帰では、データは「最適な直線」でモデル化されます。この直線の式は次のとおりです。
ここで、m は傾き、b は切片です。
「重回帰」は、1つの予測変数のケースを複数の予測変数(部屋数、海からの距離、近隣の中央値所得など)に拡張します。式は次のように一般化されます。
ここで各 xi は独立変数で、対応する bi はその係数です。3次元では直線は平面に、さらに高次元では「超平面」になります。
係数と切片はどのように解釈するのでしょうか。切片は、すべての独立変数が0のときの y の予測値、言い換えると、予測因子の寄与がないときの従属変数の基準値です。各係数 bi は、他の独立変数を一定に保ったまま、xi が1単位変化したときの従属変数 y の変化量を表します。
環境のセットアップ
scikit-learnのインストールは簡単です。コマンド
pip install scikit-learnを実行するだけです。特定のバージョン(例:1.2.2)をインストールしたい場合は、バージョン指定を追加します:pip install scikit-learn==1.2.2.Anacondaを使用している場合、scikit-learnは既にインストール済みのはずです。もしAnacondaディストリビューションで改めて必要な場合はconda install scikit-learnを使用してください。scikit-learnを使う際には、いくつかのライブラリが必須または推奨です。特徴量とラベルの格納には
numpyが必要です。データの読み込み、前処理、探索にはpandasの利用が推奨されます。scikit-learnを使っているなら、データ前処理にはすでにpandasを使っていることが多いでしょう。結果の可視化には
matplotlibやseaborn(または両方)を使うのが一般的です。これらのライブラリは、先ほどの例と同様にpipでインストールできます。1つのコマンドで複数ライブラリをまとめてインストールすることも可能です:pip install scikit-learn numpy pandas matplotlib seaborn.sklearnで線形回帰を実装する
データセットを読み込む前に、定番のライブラリをインポートしましょう。
データセットの読み込み
よく知られたCalifornia housingデータセットを使いましょう。
データの準備
データを学習用とテスト用に分割します。
sklearn.model_selectionからtrain_test_split()をインポートし、テストデータの割合とrandom_stateを指定して実行します。ここでは単回帰として、平均部屋数に対応する特徴量を使います。データを学習用・テスト用に分割したので、続いて特徴量を標準化します。すべての変数を同一スケールに揃えることで、モデル性能や数値安定性の向上が期待できます。
このコードにおける
StandardScalerは、平均を取り除き、分散が1になるようにスケーリングする前処理ツールです。スケールの違いによって一部の特徴量がモデルを支配してしまうのを防ぎます。スケーラーは
fit_transform()で学習データに当てはめてから変換します。テストデータはtransform()で別途変換し、学習データと同じ係数でスケーリングすることで、データ漏洩を防ぎます。線形回帰モデルの学習
線形回帰モデルを作成するには、
sklearn.linear_modelからLinearRegression()をインポートし、インスタンス化して変数に代入します。学習データでモデルをフィットするのは簡単です。
予測の実行
モデルを学習したので、テストデータに対して予測を行います。
モデル性能の評価
テストデータで予測したら、実際の値とどれだけ一致しているかを確認する必要があります。回帰アルゴリズムの性能評価にはいくつかの指標があります。代表的なものに決定係数(R2)、平均二乗誤差(MSE)、二乗平均平方根誤差(RMSE)があります。
決定係数R2は、回帰モデルが目的変数の変動をどれだけ説明できているかを測る指標です。言い換えると、予測因子によって目的変数の変動のどれだけが説明されるか(適合度)を定量化します。
これをさらに理解するために、次の式を見てみましょう。
ここで、yactual は目的変数の実測値、ypredicted はモデルの予測値、ȳ は実測値の平均です。この式により、目的変数の分散のうちどれだけをモデルが説明できているかがわかります。分母はデータ全体の分散、分子は回帰モデル適用後に説明できなかった分散を表します。その比率が、モデルによって説明された分散の割合を示します。
R2はどのように解釈するのでしょうか。
留意すべき点:
scikit-learnを使えば、決定係数による性能評価は簡単です。
その他によく使われる指標として、平均二乗誤差(MSE)と二乗平均平方根誤差(RMSE)があります。これらは、モデルの予測が実際の値からどれだけ離れているかを測ります。
MSEは、実測値と予測値の差の二乗の平均です。
ここで n は観測数です。誤差は平均化の前に二乗されるため、大きな誤差が小さな誤差よりも強くペナルティ化され、MSEは外れ値に敏感です。MSEが小さいほど、モデルの適合は良好です。
この問題に対処するために、MSEの平方根であるRMSEが用いられます。RMSEは目的変数と同じ単位を持つため、平均的にどの程度予測が外れているかをより解釈しやすく示します。
MSEとRMSEの計算も、scikit-learnで簡単に行えます。
scikit-learnでの重回帰
今度は平均部屋数だけでなく、利用可能なすべての特徴量を使ってモデルを再実行してみましょう。結果は良くなるでしょうか、悪くなるでしょうか。
単一特徴量のときよりも、かなり良い結果になっていることがわかります。しかし、すべての特徴量が必要かどうかという疑問が生じます。より重要な特徴量はあるのでしょうか。データセットから最も関連性の高い特徴量を選ぶことを特徴量選択と呼びます。
特徴量選択は、次のような理由で重要です。
複数の特徴量が高い相関を持つ場合、それらは冗長であり、モデルに本質的に同じ情報を与えています。これは多重共線性と呼ばれます。多重共線性は、必ずしも予測精度に影響するわけではありませんが、特に線形回帰や関連モデルにおいて、特徴量選択や解釈を複雑にします。
分散拡大要因(VIF)は、予測因子間の多重共線性を検出するための指標です。各予測因子について、VIFは次の式で計算されます。
ここで Ri2 は、予測因子 Xi を他のすべての予測因子に対して回帰したときに得られる R2 値です。VIFが高いほど、その予測因子は他の変数と強く相関しています。
AveBedrmsをモデルから除外してみましょう。
結果は(わずかに)改善しました。
モデルから洞察を得る
回帰モデルの構築は第一歩に過ぎません。出力を理解することも同じくらい重要です。モデルの係数を分析することで、どの特徴量が予測に最も大きな影響を与えているかを把握できます。
回帰係数を理解する
線形回帰モデルを学習すると、
model.coef_で係数、model.intercept_で切片にアクセスできます。LinearRegression() で学習した線形回帰モデルでは、
model.coef_で係数、model.intercept_で切片にアクセスできます。モデル結果の要約
Scikit-LearnにはStatsmodelsのような組み込みの
summary()メソッドがないため、回帰係数を使って各特徴量の重要度を手動で抽出・可視化できます。絶対値の大きな係数を持つ特徴量ほど、目的変数への影響が強いといえます。次のコードを参照してください。係数値に基づく特徴量重要度のグラフ
次に、残差と回帰当てはまりを可視化してみましょう。
残差と回帰当てはまりを可視化するプロット
残差の分布(左図)はゼロ付近を中心にしているのが望ましく、誤差がランダムに分布していることを示します。残差が正規分布に従うなら、モデルの当てはまりは良好ですが、歪みや傾向があれば、体系的な誤差の可能性があります。回帰当てはまり(右図)は実測値と予測値を比較し、赤の破線は完全一致の直線を表します。点がこの線に密接に沿っていれば予測は正確ですが、(曲線のような)パターンが見られる場合、関係は真に線形ではないかもしれません。
これらの可視化は、過学習や過小適合の診断、見落としている関係性を示唆する残差のパターンの発見、モデルの有効性の明確な評価に役立ちます。
実世界での応用
線形回帰は、予測や意思決定のためにさまざまな業界で広く使われています。不動産分野では、広さや立地などの要因に基づいて住宅価格を推定します。
営業・マーケティングでは需要予測や予算最適化に、医療では疾患リスク評価に用いられます。金融では株価予測や信用スコアリング、製造では品質管理や故障予測に役立ちます。
線形回帰を使うべき状況
線形回帰を使うべきでない状況
まとめ
線形回帰は、機械学習や統計モデリングにおいて最も基本的かつ広く使われる手法の1つです。シンプルでありながら、変数間の関係を理解し、実世界のさまざまな場面で予測を行うための強力なツールです。
本チュートリアルの主なポイント:
Pythonの文字列補間に関する詳細は、DataCampのリソースをご覧ください。