3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

NTTテクノクロスAdvent Calendar 2024

Day 12

はじめてのデータ分析 重回帰分析

Last updated at Posted at 2024-12-11

この記事はNTTテクノクロス Advent Calendar 2024 シリーズ2の13日目です。

NTTテクノクロスの大澤と申します。
普段はPythonを用いてデータ分析業務を担当しており、去年はデータ分析初学者向けに、Pythonを使ってデータ前処理から回帰直線で数値を予測するところまでを記事にしました。

今年は説明変数を増やして重回帰分析をして、簡単ではありますが評価するところまでを記事にしました。

使用するデータの紹介

今回使用するデータはscikit-learnから提供されている、カリフォルニアの住宅価格データセットを使用して、住宅の価格を予測するモデルを構築してみます。

カラム構成も併せて記載します。

可視化

予測したいのは住宅価格なので、その他の各カラムとどのような関係を持っているかを可視化してみます。

# ライブラリのインポート
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.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import japanize_matplotlib
# カリフォルニアの住宅価格データセットをロード
california_housing = fetch_california_housing()

# データをデータフレームに格納
df = pd.DataFrame(california_housing.data, columns=california_housing.feature_names)
df['Price'] = california_housing.target

# データの確認
df.head(5)
MedInc HouseAge AveRooms AveBedrms Population AveOccup Latitude Longitude Price
0 8.3252 41.0 6.984127 1.023810 322.0 2.555556 37.88 -122.23 4.526
1 8.3014 21.0 6.238137 0.971880 2401.0 2.109842 37.86 -122.22 3.585
2 7.2574 52.0 8.288136 1.073446 496.0 2.802260 37.85 -122.24 3.521
3 5.6431 52.0 5.817352 1.073059 558.0 2.547945 37.85 -122.25 3.413
4 3.8462 52.0 6.281853 1.081081 565.0 2.181467 37.85 -122.25 3.422
# 各特徴量と目的変数の散布図を描画
# サイズの関係上、一部抜粋して添付
sns.set(style="whitegrid")
for column in df.columns:
    if column == 'Price':
        continue  # "Price"カラムの場合は散布図の描画をスキップ
    plt.figure(figsize=(8, 6))
    sns.scatterplot(data=df, x=column, y='Price')
    plt.title(f'{column}_Price')
    plt.xlabel(column)
    plt.ylabel('Price')
    plt.show()

ダウンロード.png

ダウンロード (1).png

カラムを絞って価格の予測

すべての散布図を見ていただくとわかると思いますが、
テストデータということもありまんべんなく分布されているような散布図になっており選定しづらいです。
本来はこのように可視化をした結果からどのようなカラムと相関があるかを確認したり、新しくデータを作成したり、加工したデータと見比べてみたりして説明変数の選定をしていきます。

今回は、一般的に住宅の価格に影響を与えていそうなカラムを主観で選定してみてモデルを作ってみようと思います。

  • HouseAge:築年数の中央値
  • AveRooms:1世帯当たりの平均部屋数
  • AveBedrms:1世帯当たりの平均寝室数
  • Population:地区の人口
# カリフォルニアの住宅価格データセットをロード
california_housing = fetch_california_housing()

# データをデータフレームに格納
df = pd.DataFrame(california_housing.data, columns=california_housing.feature_names)
df['Price'] = california_housing.target

# 説明変数と目的変数に分割
selected_features = ['HouseAge', 'AveRooms', 'AveBedrms', 'Population']
X = df[selected_features]
y = df['Price']
# データをトレーニングセットとテストセットに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 線形回帰モデルを作成
model = LinearRegression()

# モデルをトレーニングデータにフィット
model.fit(X_train, y_train)

# テストデータを用いて予測
y_pred = model.predict(X_test)

評価

これでモデルの構築は完了しましたが、このモデルがどれくらい信用できるかを確認する必要があります。

去年実施した単回帰の場合はグラフを作成することができたので、直感的にこのモデルは良い、悪いの判断ができましたが、重回帰の場合グラフを図示するのは難しいです。

このような場合に(単回帰でも使用できますが)、モデルの良し悪しを判断できる数値化した指標がいくつかあるのですが、今回は二つの指標をざっくり紹介します。
詳細はscikit-learnの公式ドキュメントなどのサイトをご覧ください。

  • MSE

    • 値が小さいほうが精度がいい
    \displaylines{
    MSE = \frac{1}{n} \sum_{k=1}^{n} (y_i - \hat{y_i})^2\
    }
    
    y_i:実際の値  \quad \hat{y_i}:予測値
    
  • 決定係数

    • 0-1をとり、0に行くほど精度悪く、1に行くほど精度がいいが、1に近すぎると過学習が疑われる。
     R^2 = 1- \frac{\sum_{k=1}^{n} (y_i - \hat{y_i})^2}{\sum_{k=1}^{n} (y_i - \bar{y_i})^2}
    
       \bar{y_i}:実際の値全体の平均値
    
# モデルの評価
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f"Mean Squared Error: {mse}")
print(f"R^2 Score: {r2}")

# 回帰係数を表示
coefficients = pd.DataFrame(model.coef_, X.columns, columns=['Coefficient'])
print(coefficients)
Mean Squared Error: 1.125648161565992
R^2 Score: 0.1409947731912915
            Coefficient
HouseAge       0.015889
AveRooms       0.349354
AveBedrms     -1.700036
Population     0.000033

結果として回帰係数も表示していますが、MSEは1.12、決定係数は0.14と算出されました。
どちらの評価軸でも精度はあまりよくなさそうなので、次はすべての説明変数を使用してモデルを構築してみます。

すべてのカラムを使用して予測

# 説明変数と目的変数に分ける
X = df.drop('Price', axis=1)
y = df['Price']

# データをトレーニングセットとテストセットに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 線形回帰モデルを作成
model = LinearRegression()

# モデルをトレーニングデータにフィット
model.fit(X_train, y_train)

# テストデータを用いて予測
y_pred = model.predict(X_test)

# モデルの評価
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f"Mean Squared Error: {mse}")
print(f"R^2 Score: {r2}")

# 回帰係数を表示
coefficients = pd.DataFrame(model.coef_, X.columns, columns=['Coefficient'])
print(coefficients)
Mean Squared Error: 0.5558915986952444
R^2 Score: 0.5757877060324508
            Coefficient
MedInc         0.448675
HouseAge       0.009724
AveRooms      -0.123323
AveBedrms      0.783145
Population    -0.000002
AveOccup      -0.003526
Latitude      -0.419792
Longitude     -0.433708

結果として、説明変数を絞るよりはすべて使った方が精度が良い結果になりました。
今回もテストデータのため、説明変数の選定を順序だててできませんでしたが、実際のデータの場合は目的変数との相関を見ながら複数のモデルを構築することで良い結果が得られるかと思います。
重回帰だけでなく、様々な回帰の手法もあるため、うまくいかない場合は手法を変えるのも念頭に入れながら試行錯誤してみてください。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?