LESSON

線形モデル

田中VPoE:「いよいよモデルの構築に入る。まずはシンプルな線形モデルから始めよう。複雑なモデルの前に、まずベースラインとなる線形モデルの精度を把握することが大切だ。」

あなた:「線形モデルは単純すぎて精度が出ないのでは?」

田中VPoE:「そう思うだろうが、解釈性が高くて動作が安定しているし、正則化を加えれば実用的な精度も出る。複雑なモデルと比較するためのベースラインとしても必須だ。」

ロジスティック回帰

分類問題の基本モデルです。線形結合をシグモイド関数で確率に変換します。

基本的な使い方

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, f1_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

# パイプラインで構築(スケーリング + モデル)
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('model', LogisticRegression(random_state=42, max_iter=1000)),
])

# 学習
pipeline.fit(X_train, y_train)

# 予測
y_pred = pipeline.predict(X_test)
y_prob = pipeline.predict_proba(X_test)[:, 1]

# 評価
print(classification_report(y_test, y_pred, target_names=['継続', '離反']))
print(f"F1スコア: {f1_score(y_test, y_pred):.3f}")

シグモイド関数

import numpy as np
import matplotlib.pyplot as plt

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

z = np.linspace(-6, 6, 100)
plt.figure(figsize=(8, 5))
plt.plot(z, sigmoid(z))
plt.axhline(y=0.5, color='r', linestyle='--', label='閾値=0.5')
plt.xlabel('z = w1*x1 + w2*x2 + ... + b')
plt.ylabel('離反確率 P(Y=1)')
plt.title('シグモイド関数')
plt.legend()
plt.grid(True)
plt.show()

係数の解釈

# 係数を確認(解釈性の高さが線形モデルの強み)
model = pipeline.named_steps['model']
coef = pd.Series(model.coef_[0], index=feature_names)
coef = coef.sort_values()

print("=== 係数(影響度) ===")
for name, c in coef.items():
    direction = "離反↑" if c > 0 else "離反↓"
    print(f"  {name}: {c:+.4f} ({direction})")

線形回帰

連続値を予測する回帰問題の基本モデルです。

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# 例: 顧客生涯価値(LTV)を予測
model = LinearRegression()
model.fit(X_train, y_train_ltv)

y_pred_ltv = model.predict(X_test)
print(f"RMSE: {np.sqrt(mean_squared_error(y_test_ltv, y_pred_ltv)):.2f}")
print(f"R²: {r2_score(y_test_ltv, y_pred_ltv):.3f}")

正則化(Regularization)

過学習を防ぐために、モデルの複雑さにペナルティを加えます。

L1正則化(Lasso)

不要な特徴量の係数を0にする(特徴量選択効果)。

from sklearn.linear_model import LogisticRegression

# L1正則化
model_l1 = LogisticRegression(
    penalty='l1',
    solver='liblinear',
    C=0.1,  # 小さいほど強い正則化
    random_state=42,
)
model_l1.fit(X_train_scaled, y_train)

# 係数が0になった特徴量を確認
zero_features = [f for f, c in zip(feature_names, model_l1.coef_[0]) if c == 0]
print(f"係数が0の特徴量: {zero_features}")

L2正則化(Ridge)

すべての係数を小さく抑える(縮小推定)。

# L2正則化(デフォルト)
model_l2 = LogisticRegression(
    penalty='l2',
    C=1.0,
    random_state=42,
)
model_l2.fit(X_train_scaled, y_train)

Elastic Net

L1 と L2 を組み合わせた正則化。

from sklearn.linear_model import SGDClassifier

model_en = SGDClassifier(
    loss='log_loss',
    penalty='elasticnet',
    l1_ratio=0.5,  # L1の割合
    random_state=42,
)
model_en.fit(X_train_scaled, y_train)

正則化の比較

正則化特徴使いどころ
L1 (Lasso)特徴量選択効果あり不要な特徴量が多い場合
L2 (Ridge)全係数を均等に縮小多重共線性がある場合
Elastic NetL1 + L2両方のメリットが欲しい場合

C パラメータの調整

from sklearn.model_selection import cross_val_score

C_values = [0.001, 0.01, 0.1, 1, 10, 100]
results = []

for C in C_values:
    model = LogisticRegression(C=C, random_state=42, max_iter=1000)
    scores = cross_val_score(model, X_train_scaled, y_train, cv=5, scoring='f1')
    results.append({'C': C, 'F1_mean': scores.mean(), 'F1_std': scores.std()})
    print(f"C={C:>6}: F1 = {scores.mean():.3f} (+/- {scores.std():.3f})")

best_C = max(results, key=lambda x: x['F1_mean'])['C']
print(f"\n最適な C: {best_C}")

線形モデルの長所と短所

長所短所
解釈性が高い(係数の意味が明確)非線形な関係を捉えにくい
学習・推論が高速特徴量間の交互作用を自動で学習しない
少ないデータでも安定特徴量のスケーリングが必須
過学習しにくい複雑なパターンへの適応力が低い

まとめ

  • ロジスティック回帰は分類問題のベースラインモデルとして最適
  • シグモイド関数で線形結合を確率に変換する
  • 正則化(L1/L2/Elastic Net)で過学習を防ぐ
  • 係数から特徴量の影響度を解釈できるのが最大の強み
  • C パラメータで正則化の強さを調整する

チェックリスト

  • ロジスティック回帰の仕組みを説明できる
  • L1/L2 正則化の違いを理解した
  • C パラメータの意味と調整方法を把握した
  • 線形モデルの長所・短所を説明できる

次のステップへ

次のレッスンでは、非線形な関係も捉えられる決定木とランダムフォレストを学びます。


推定読了時間: 30分