0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

線形回帰、Scikitlearnメモメモ

Posted at

キャンセルする
送信する
ChatGPT:
思考時間: 12s
分析が終了しました
常に詳細を表示する

Cell 1: セットアップとデータ生成

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split

再現性

rng = np.random.default_rng(42)

人工データ生成(一次関係 + ノイズ)

n = 200
X = rng.uniform(-5, 5, size=(n, 1))

真の関係: y = 3.0 * x + 2.0 + ノイズ

y_true = 3.0 * X[:, 0] + 2.0
noise = rng.normal(0, 2.0, size=n)
y = y_true + noise

df = pd.DataFrame({"x": X[:, 0], "y": y, "y_true": y_true})

学習・評価データに分割

X_train, X_test, y_train, y_test = train_test_split(df[["x"]].values, df["y"].values, test_size=0.25, random_state=0)

表示用サマリ

summary = pd.DataFrame({
"n_total": [n],
"n_train": [len(X_train)],
"n_test": [len(X_test)],
"x_min": [df["x"].min()],
"x_max": [df["x"].max()],
"y_min": [df["y"].min()],
"y_max": [df["y"].max()],
})

import caas_jupyter_tools
caas_jupyter_tools.display_dataframe_to_user("データ概要", summary)

先頭5行も表示

caas_jupyter_tools.display_dataframe_to_user("データ先頭5行", df.head())

結果
x y y_true
0 2.739560 11.505335 10.218681
1 -0.611216 -0.622857 0.166353
2 3.585979 12.747694 12.757938
3 1.973680 7.594155 7.921041
4 -4.058227 -9.499530 -10.174680
データ概要
データ先頭5行
分析が終了しました
常に詳細を表示する

Cell 2: 線形回帰(最小二乗)と可視化

import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error
import numpy as np

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

予測と指標

y_pred_test = linreg.predict(X_test)
r2 = r2_score(y_test, y_pred_test)
mae = mean_absolute_error(y_test, y_pred_test)
rmse = mean_squared_error(y_test, y_pred_test, squared=False)

print("=== 線形回帰(最小二乗) ===")
print(f"係数 w: {linreg.coef_[0]:.3f}, 切片 b: {linreg.intercept_:.3f}")
print(f"R^2 (test): {r2:.3f}")
print(f"MAE (test): {mae:.3f}")
print(f"RMSE (test): {rmse:.3f}")

可視化: 散布図 + 回帰直線

x_plot = np.linspace(df["x"].min(), df["x"].max(), 200).reshape(-1, 1)
y_line = linreg.predict(x_plot)

plt.figure()
plt.scatter(X_train[:,0], y_train, label="train", alpha=0.6)
plt.scatter(X_test[:,0], y_test, label="test", alpha=0.9, marker="x")
plt.plot(x_plot[:,0], y_line, label="linear fit")
plt.xlabel("x")
plt.ylabel("y")
plt.title("Linear Regression: data & fitted line")
plt.legend()
plt.show()

STDOUT/STDERR
=== 線形回帰(最小二乗) ===
係数 w: 3.124, 切片 b: 1.984
R^2 (test): 0.956
MAE (test): 1.463
RMSE (test): 1.810

Linear Regression: Data & Fitted Line
分析が終了しました
常に詳細を表示する

Cell 3: 残差プロット(線形回帰)

import matplotlib.pyplot as plt
residuals = y_test - y_pred_test

plt.figure()
plt.scatter(y_pred_test, residuals, alpha=0.8)
plt.axhline(0, linestyle="--")
plt.xlabel("Predicted (test)")
plt.ylabel("Residual (y - y_hat)")
plt.title("Residuals vs Predicted (Linear Regression)")
plt.show()

Residuals Vs Predicted (Linear Regression)
分析が終了しました
常に詳細を表示する

Cell 4: Lasso回帰 & Ridge回帰(CV付)と係数比較の可視化

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.linear_model import LassoCV, RidgeCV

Lasso(正則化付き最小二乗, L1)

lasso = LassoCV(alphas=None, cv=5, random_state=0, n_alphas=1000)
lasso.fit(X_train, y_train)
y_pred_lasso = lasso.predict(X_test)

Ridge(L2)

ridge = RidgeCV(alphas=np.logspace(-3, 3, 50), cv=5)
ridge.fit(X_train, y_train)
y_pred_ridge = ridge.predict(X_test)

from sklearn.metrics import r2_score, mean_absolute_error, mean_squared_error

def metrics(y_true, y_pred):
return {
"R^2": r2_score(y_true, y_pred),
"MAE": mean_absolute_error(y_true, y_pred),
"RMSE": mean_squared_error(y_true, y_pred, squared=False)
}

rows = []
rows.append({"model": "Linear", **metrics(y_test, y_pred_lasso*0 + 0)})

係数と切片の比較テーブル

coef_df = pd.DataFrame({
"model": ["Linear", "Lasso", "Ridge"],
"coef_w": [linreg.coef_[0], lasso.coef_[0], ridge.coef_[0]],
"intercept_b": [linreg.intercept_, lasso.intercept_, ridge.intercept_],
"R2_test": [r2_score(y_test, linreg.predict(X_test)),
r2_score(y_test, y_pred_lasso),
r2_score(y_test, y_pred_ridge)]
})

表示

import caas_jupyter_tools
caas_jupyter_tools.display_dataframe_to_user("係数・性能比較", coef_df.round(4))

print("=== Lasso ===")
print(f"alpha*: {lasso.alpha_:.5f}, coef: {lasso.coef_[0]:.3f}, intercept: {lasso.intercept_:.3f}")
print(f"R^2 (test): {r2_score(y_test, y_pred_lasso):.3f} MAE: {mean_absolute_error(y_test, y_pred_lasso):.3f} RMSE: {mean_squared_error(y_test, y_pred_lasso, squared=False):.3f}")

print("\n=== Ridge ===")
print(f"alpha*: {ridge.alpha_:.5f}, coef: {ridge.coef_[0]:.3f}, intercept: {ridge.intercept_:.3f}")
print(f"R^2 (test): {r2_score(y_test, y_pred_ridge):.3f} MAE: {mean_absolute_error(y_test, y_pred_ridge):.3f} RMSE: {mean_squared_error(y_test, y_pred_ridge, squared=False):.3f}")

可視化: テストデータの予測値比較(散布図)

plt.figure()
plt.scatter(X_test[:,0], y_test, label="test (true)", marker="x")
plt.plot(np.sort(X_test[:,0]), linreg.predict(X_test[np.argsort(X_test[:,0])]), label="Linear")
plt.plot(np.sort(X_test[:,0]), y_pred_lasso[np.argsort(X_test[:,0])], label="Lasso")
plt.plot(np.sort(X_test[:,0]), y_pred_ridge[np.argsort(X_test[:,0])], label="Ridge")
plt.xlabel("x (test)")
plt.ylabel("y / y_hat")
plt.title("Predictions on Test Data")
plt.legend()
plt.show()

可視化: 係数比較(棒グラフ)

plt.figure()
models = ["Linear", "Lasso", "Ridge"]
coefs = [linreg.coef_[0], lasso.coef_[0], ridge.coef_[0]]
plt.bar(models, coefs)
plt.ylabel("Coefficient (w)")
plt.title("Coefficient Comparison")
plt.show()

STDOUT/STDERR
=== Lasso ===
alpha*: 0.02563, coef: 3.121, intercept: 1.984
R^2 (test): 0.956 MAE: 1.463 RMSE: 1.811

=== Ridge ===
alpha*: 0.06866, coef: 3.124, intercept: 1.984
R^2 (test): 0.956 MAE: 1.463 RMSE: 1.810

係数・性能比較
Predictions On Test Data
Coefficient Comparison

以下は「セル分割されたノートブック風」の実行コードです。

まず人工データで単回帰(最小二乗) → 散布図+回帰直線+残差図

次に機械学習的な正則化として Lasso と Ridge(どちらもCVでα自動選択)を学習し、係数・性能を比較します。
(可視化には matplotlib、学習には scikit-learn を使用)

上から順に実行してください👇
(それぞれ「セル」として分割して実行できるようにしてあります)

セル1:セットアップとデータ生成

上のセルでデータ概要と先頭5行が表示されます。

(実行済み)

セル2:線形回帰(最小二乗)と可視化

学習済みモデルの係数・切片・評価指標(R²/MAE/RMSE)を表示

散布図 + 回帰直線を描画

(実行済み/グラフ表示済み)

セル3:残差プロット

予測値 vs 残差を描画

線形性や等分散のざっくり確認に使えます

(実行済み/グラフ表示済み)

セル4:Lasso & Ridge(CVつき)+係数比較

LassoCV と RidgeCV で最適 α を交差検証で決定

係数・切片・R² を表で比較

テストデータの予測曲線と係数の棒グラフを可視化

(実行済み/グラフ・比較表表示済み)

使い方・応用(根拠と理由を添えて)

自分のCSVに差し替える(1変数 x→y の回帰)
セル1のデータ生成を、たとえば次の読み込みに置き換えればOKです。

import pandas as pd
df = pd.read_csv("your_data.csv") # 例: 列名は 'x', 'y' を想定
X = df[["x"]].values
y = df["y"].values

理由:以降のセルは X と y を前提にしているため、この2変数を同じ形で用意すればそのまま動きます。

特徴量が複数ある場合

X = df[["x1","x2","x3", ...]].values

Lasso(L1)は係数を0へ押し込み特徴量選択として働く(疎な解)傾向。

**Ridge(L2)**は係数の大きさを均等に抑え、多重共線性に強く、過学習を抑える。

理由:正則化項の性質(L1は絶対値和、L2は二乗和)により、解の幾何学的制約が異なるため。

線形モデルの仮定と残差図の読み方

線形性・等分散・独立性などが満たされるほど、最小二乗の推定は妥当。

残差図が予測値に対してパターンなくランダムなら、線形モデルの前提が合いやすい。

理由:残差に構造が見える(例:U字)場合、非線形・分散不均一の可能性が高いため。

必要であれば、多項式回帰や交差項の追加、学習曲線・k分割CVの導入、標準化の追加(特に正則化時)まで拡張した実装も用意します。

あなた:
棒グラフは、上から、変数を並べて、Coefficientを出して、正が右、負が左に伸びるように可視化したい。他にできることある?
ChatGPT:
分析が終了しました
常に詳細を表示する

Cell 5: 係数を棒グラフ(水平棒)で可視化

import matplotlib.pyplot as plt
import numpy as np

coef_dict = {
"Linear": linreg.coef_[0],
"Lasso": lasso.coef_[0],
"Ridge": ridge.coef_[0]
}

models = list(coef_dict.keys())
coefs = list(coef_dict.values())

水平棒グラフ:正は右、負は左

plt.figure()
y_pos = np.arange(len(models))
plt.barh(y_pos, coefs, align='center')
plt.yticks(y_pos, models)
plt.axvline(0, color='k', linestyle='--')
plt.xlabel("Coefficient value (w)")
plt.title("Model Coefficients (positive right, negative left)")
plt.show()

Model Coefficients (Positive Right, Negative Left)

こんな感じで「係数を横棒グラフ」で出せました。

正の係数は右向き、負は左向きに伸びるため、直感的に影響の向きを把握できます。

複数変数がある場合は、特徴量名ごとに並べられるので、変数重要度の比較にそのまま使えます。

他にできる可視化・分析の工夫例

特徴量が複数ある場合の重要度可視化

水平棒グラフを変数ごとに並べる(今回のようにモデルごとに並べるのではなく、変数名を縦軸に)。

モデル間で係数の違いを並べて表示することで、Lassoがどの変数をゼロにしているか一目でわかります。

正則化強度と係数の推移

LassoCVやRidgeCVの内部にはαを変化させたときの係数パスがあります。これを折れ線グラフにすると、正則化によって係数がどのように縮むかを可視化できます。

予測 vs 実測の散布図

テストデータで y_true vs y_pred を散布図にし、理想線 y=x と比較すると、誤差の分布が直感的にわかります。

残差の分布(ヒストグラム / QQプロット)

残差が正規分布に近いかどうか確認することで、モデル仮定の妥当性チェックができます。

交差検証スコアの分布

CVスコア(R²やMAE)の分布を箱ひげ図にすれば、モデルの安定性やバラつきを評価できます。

👉 どれを追加しましょうか?「係数パスの可視化」や「予測 vs 実測プロット」あたりを次に実装すると一番効果的ですが、どちらを見たいですか?

あなた:
縦軸は、x1,x2,x3などの変数で、重要度が高いものから上から、、、
ChatGPT:

なるほど!
今の例は説明変数が1個しかないので「x1」だけですが、複数変数がある場合を想定すると、縦軸に x1, x2, x3,... を並べ、係数の絶対値が大きい順(=重要度が高い順)で上から並べるのが良いですね。

実装イメージ(水平棒グラフ)
import matplotlib.pyplot as plt
import numpy as np

例: 変数が複数あるときの係数(ここではダミー)

feature_names = ["x1", "x2", "x3", "x4"]
coefs = np.array([0.5, -1.2, 2.3, -0.8]) # モデルから得た係数

重要度(絶対値)でソート

order = np.argsort(np.abs(coefs))[::-1]
sorted_features = np.array(feature_names)[order]
sorted_coefs = coefs[order]

棒グラフ(水平)

plt.figure(figsize=(6,4))
y_pos = np.arange(len(sorted_features))
plt.barh(y_pos, sorted_coefs, align="center", color="skyblue")
plt.yticks(y_pos, sorted_features)
plt.axvline(0, color="k", linestyle="--")
plt.xlabel("Coefficient value (importance)")
plt.title("Feature importance (by coefficient size)")
plt.gca().invert_yaxis() # 上から重要度が高い順
plt.show()

正の係数 → 右へ、負の係数 → 左へ

上から順に重要度が高い変数

LassoやRidgeの出力をそのまま coefs に渡せばOKです。

他にできる工夫

モデルごとの比較:Linear / Lasso / Ridge の係数を DataFrame 化して、それぞれの特徴量について棒グラフを並べて表示。

標準化後の係数比較:入力を標準化してから回帰すれば、係数をそのまま変数間の重要度比較に利用できます。

SHAP値やPermutation Importance:係数だけでなく、よりモデル全体の寄与を測る方法も組み合わせられます。

👉 実際に「x1,x2,x3,…が複数あるケース」でこのグラフを作ってみますか?(今の人工データを拡張して3変数くらいにして可視化しましょうか?)

あなた:
作ってみて。
ChatGPT:
分析が終了しました
常に詳細を表示する

Cell 6: 複数特徴量データで回帰し、係数を重要度順に可視化

from sklearn.preprocessing import StandardScaler

人工データ生成(3特徴量)

rng = np.random.default_rng(42)
n = 300
X_multi = rng.normal(0, 1, size=(n, 3))
true_coef = np.array([2.0, -1.5, 0.5]) # 真の係数
y_multi = X_multi @ true_coef + 3.0 + rng.normal(0, 1.0, size=n)

feature_names = ["x1", "x2", "x3"]

学習・テスト分割

X_train_m, X_test_m, y_train_m, y_test_m = train_test_split(X_multi, y_multi, test_size=0.25, random_state=0)

標準化 + 線形回帰(標準化すると係数比較しやすい)

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train_m)
X_test_scaled = scaler.transform(X_test_m)

linreg_m = LinearRegression()
linreg_m.fit(X_train_scaled, y_train_m)

coefs = linreg_m.coef_

重要度順(絶対値ソート)

order = np.argsort(np.abs(coefs))[::-1]
sorted_features = np.array(feature_names)[order]
sorted_coefs = coefs[order]

可視化

plt.figure(figsize=(6,4))
y_pos = np.arange(len(sorted_features))
plt.barh(y_pos, sorted_coefs, align="center", color="skyblue")
plt.yticks(y_pos, sorted_features)
plt.axvline(0, color="k", linestyle="--")
plt.xlabel("Coefficient value (importance)")
plt.title("Feature importance (Linear Regression, standardized)")
plt.gca().invert_yaxis() # 上から重要度が高い順
plt.show()

coefs_table = pd.DataFrame({"feature": feature_names, "coef": coefs, "abs_coef": np.abs(coefs)})
coefs_table_sorted = coefs_table.iloc[order].reset_index(drop=True)

import caas_jupyter_tools
caas_jupyter_tools.display_dataframe_to_user("標準化済み線形回帰の係数(大きい順)", coefs_table_sorted.round(3))

結果
feature coef abs_coef
0 x1 2.103 2.103
1 x2 -1.339 1.339
2 x3 0.437 0.437
Feature Importance (Linear Regression, Standardized)
標準化済み線形回帰の係数(大きい順)

複数変数(x1, x2, x3)で回帰を行い、係数の絶対値が大きい順に上から並べた横棒グラフを描きました。

上から順に重要度が高い特徴量

x1(正寄与)

x2(負寄与)

x3(弱い正寄与)

表でも、標準化済みの係数値とその絶対値を並べて確認できるようにしてあります。

👉 次のステップとして、LassoやRidgeでの係数スパース化/縮小も同じ形式で並べて比較できますが、やりますか?

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?