第2章 機械学習:回帰
📚 この章の学習目標
- 分類と回帰の違いを理解する
- 線形回帰の基本原理とコスト関数を学ぶ
- 勾配降下法による最適化手法を習得する
- RSSとMSEの意味と計算方法を理解する
- scikit-learnを用いた回帰モデルの実装を学ぶ
- SGDRegressorによる確率的勾配降下法を実践する
🚀 イントロダクション
💡 分類から回帰へ
第1章では「カテゴリ」を予測する分類問題を学びました。第2章では「連続的な数値」を予測する回帰問題を学びます。
例:
- 分類:この患者は病気か健康か?(カテゴリ)
- 回帰:この患者の血糖値は何mg/dLか?(数値)
🔍 分類 vs 回帰
📊 分類(Classification)
✅ 分類の特徴
- 目的:カテゴリやクラスにデータを分けること
- ターゲット値:離散的なクラス(カテゴリ)を予測
- 例:
- メールがスパムかどうか(スパム or 正常)
- 画像が犬か猫か(犬 or 猫)
- がんの診断(悪性 or 良性)
- 使用アルゴリズム:決定木、SVM、k-NN、ロジスティック回帰など
📈 回帰(Regression)
✅ 回帰の特徴
- 目的:連続的な数値を予測すること
- ターゲット値:連続的な数値を予測
- 例:
- 家の価格を予測(具体的な金額)
- 将来の気温を予測(摂氏何度か)
- 株価の予測(数値)
- 使用アルゴリズム:線形回帰、リッジ回帰、ラッソ回帰、SVRなど
🔄 分類と回帰の違いまとめ
| 観点 | 分類 | 回帰 |
|---|---|---|
| 予測対象 | カテゴリ・ラベル | 連続的な数値 |
| 出力例 | 「病気」「健康」 | 「120mg/dL」 |
| 医療例 | 病気の有無判定 | 血糖値の予測 |
| 不動産例 | 物件タイプ分類 | 価格予測 |
📐 線形回帰(Linear Regression)
💡 線形回帰とは?
線形回帰は、1つまたは複数の特徴量(入力変数)とターゲット(出力変数)の間に線形関係があると仮定して、その関係を数式として表現する手法です。
線形回帰の基本数式
単純線形回帰(1つの特徴量):
y = w₀ + w₁·x
重回帰(複数の特徴量):
y = w₀ + w₁·x₁ + w₂·x₂ + w₃·x₃ + ... + wₙ·xₙ
⚡ 変数の意味
- y:予測したい値(従属変数)
- x₁, x₂, …, xₙ:入力特徴量(独立変数)
- w₀:切片(バイアス)
- w₁, w₂, …, wₙ:回帰係数(重み)
🏠 マンション価格予測の例
✅ 単純線形回帰の例
マンション価格が面積のみで決定されると仮定すると:
価格 = w₀ + w₁ × 面積目標:実際の価格と予測価格の誤差を最小化するw₀とw₁を見つけること
マンション価格
↑
| ● 実測値
| ● /
| ● / 予測線: y = w₀ + w₁·x
| ● /
|● /
|/____________→ 面積(m²)
💡 回帰の核心
最適な回帰モデルを作るということは、データ全体の残差(誤差値)の合計が最小になるモデルを作ることを意味します。
📉 誤差測定:RSSとMSE
RSS(Residual Sum of Squares):残差平方和
💡 RSSとは?
回帰モデルにおいて、予測値と実際の観測値との間の誤差の大きさを表す指標です。
各データポイントの誤差を二乗して合計します。
RSS の計算式:
RSS = Σ (実測値ᵢ - 予測値ᵢ)²
= Σ (yᵢ - (w₀ + w₁·xᵢ))²
マンション価格の例:
RSS = (マンション1の実際価格 - 予測価格)²
+ (マンション2の実際価格 - 予測価格)²
+ (マンション3の実際価格 - 予測価格)²
+ ... (すべてのデータについて実行)
MSE(Mean Squared Error):平均二乗誤差
💡 MSEとは?
RSSを学習データの件数で割った値です。データ量が異なるモデルを比較する際に便利です。
MSE の計算式:
MSE = RSS / N = (1/N) × Σ (yᵢ - ŷᵢ)²
⚠️ 重要な理解
- RSSとMSEは、w₀, w₁(回帰係数)を変数とする関数です
- 学習データのxとyは定数として扱われます
- 学習の目的は、RSSまたはMSEを最小化するw値を見つけることです
🧪 実習:糖尿病進行予測
🔬 糖尿病データセットの概要
scikit-learnに含まれる糖尿病データセットを使用して、1年後の糖尿病の進行状態を予測します。
データセットの詳細
| 項目 | 内容 |
|---|---|
| サンプル数 | 442件 |
| 特徴量数 | 10個(すべて正規化済み) |
| ターゲット | 糖尿病の進行度(連続値) |
特徴量一覧:
- 年齢(Age)
- 性別(Sex)
- BMI(Body Mass Index:体格指数)
- 血圧(Blood Pressure)
- S1, S2, S3, S4, S5, S6(6つの血液検査結果)
📥 データセットの読み込み
from sklearn.datasets import load_diabetes
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
import numpy as np
import pandas as pd
# データセットの読み込み
diabetes = load_diabetes()
keys = diabetes.keys()
print('diabetes dataset keys:', keys)
# 出力結果
diabetes dataset keys: dict_keys(['data', 'target', 'frame', 'DESCR',
'feature_names', 'data_filename', 'target_filename', 'data_module'])
features = diabetes.data
label = diabetes.target
print(type(features), features.shape) # (442, 10)
print(type(label), label.shape) # (442,)
📊 データフレームへの変換
# 特徴量をデータフレームに変換
X = pd.DataFrame(diabetes.data, columns=diabetes.feature_names)
# ターゲット値をSeriesに変換
y = pd.Series(diabetes.target)
print(X.head()) # 最初の5行を表示
print("--------------------------------")
print(y.head(10)) # 最初の10個のターゲット値を表示
# 出力例
age sex bmi bp s1 s2 s3 \
0 0.038076 0.050680 0.061696 0.021872 -0.044223 -0.034821 -0.043401
1 -0.001882 -0.044642 -0.051474 -0.026328 -0.008449 -0.019163 0.074412
2 0.085299 0.050680 0.044451 -0.005670 -0.045599 -0.034194 -0.032356
...
🎯 データの分離
X_train, X_test, y_train, y_test = train_test_split(
X, y,
test_size=0.2, # 20%をテストデータに
random_state=11
)
🤖 モデルの学習と評価
# 線形回帰モデルの作成
lr_model = LinearRegression()
# モデルの学習
lr_model.fit(X_train, y_train)
# 予測
pred = lr_model.predict(X_test)
# 評価
mse = mean_squared_error(y_test, pred)
rmse = np.sqrt(mse)
print("Mean Squared Error (MSE):", round(mse, 2))
print("Root Mean Squared Error (RMSE):", round(rmse, 2))
# 出力結果
Mean Squared Error (MSE): 3212.59
Root Mean Squared Error (RMSE): 56.68
🔄 K-Fold交差検証による評価
from sklearn.model_selection import KFold
# K-Fold分割
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
cv_mse = []
# K-Fold交差検証
n_iter = 0
for train_index, test_index in kfold.split(features):
X_train, X_test = features[train_index], features[test_index]
y_train, y_test = label[train_index], label[test_index]
# モデルの学習と予測
lr_model = LinearRegression()
lr_model.fit(X_train, y_train)
pred = lr_model.predict(X_test)
# MSE評価
mse = mean_squared_error(y_test, pred)
rmse = np.sqrt(mse)
cv_mse.append(mse)
n_iter += 1
print(f'#{n_iter} Fold MSE: {round(mse, 2)}, RMSE: {round(rmse, 2)}')
# 全体の平均MSE
mean_mse = np.mean(cv_mse)
print(f"\nAverage MSE across all folds: {round(mean_mse, 2)}")
🎯 勾配降下法(Gradient Descent)
💡 勾配降下法とは?
コスト関数(MSEなど)を最小化するために、パラメータを反復的に更新していく最適化アルゴリズムです。
「山を下る」ように、誤差が小さくなる方向へ少しずつパラメータを調整します。
勾配降下法の仕組み
コスト関数
↑
| ●初期W
| / \
| / \勾配に沿って降下
| / \
| / ●
|/ \●
|____________\●最小点→ w
⚡ 勾配降下法のポイント
- 初期値:ランダムまたは0でwを初期化
- 勾配計算:コスト関数を微分して勾配を求める
- 更新:勾配の逆方向に少しずつwを移動
- 反復:収束するまで2-3を繰り返す
微分による最小値の探索
💡 なぜ微分を使うのか?
- 微分は関数の増加・減少の方向性を示します
- コスト関数を微分すると、どちらの方向に進めば誤差が減るかがわかります
- 微分値が0に近づく点が、コスト関数の最小点です
更新式:
w_new = w_old - α × (∂MSE/∂w)
⚡ 学習率(α)
- 学習率が大きすぎると、最小点を飛び越えてしまう
- 学習率が小さすぎると、収束に時間がかかる
- 適切な学習率の設定が重要
🔀 SGDとMini-Batch GD
勾配降下法の3つのタイプ
| タイプ | データ使用量 | 特徴 |
|---|---|---|
| GD(Gradient Descent) | 全データ | 正確だが計算コストが高い |
| SGD(Stochastic GD) | 1サンプル | 高速だがノイズが多い |
| Mini-Batch GD | バッチサイズ分 | バランスが良く、最も実用的 |
💡 実務での選択
一般的に、Mini-Batch GDがほとんどのディープラーニングフレームワークで採用されています。
Mini-Batchの動作
全体学習データ(400件)
↓
┌─────────────────────────────┐
│ Batch 1 (100件) → GD計算 → 更新 │
│ Batch 2 (100件) → GD計算 → 更新 │
│ Batch 3 (100件) → GD計算 → 更新 │
│ Batch 4 (100件) → GD計算 → 更新 │
└─────────────────────────────┘
↓
1エポック完了
🔧 SGDRegressorによる実装
💡 SGDRegressorとは?
scikit-learnに含まれる確率的勾配降下法を使った回帰モデルです。
- 大規模データセットに効率的
- パラメータの細かい調整が可能
- 学習率やイテレーション数を設定できる
基本的な実装
from sklearn.linear_model import SGDRegressor
from sklearn.model_selection import KFold
# K-Fold分割
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
cv_mse = []
# K-Fold交差検証
n_iter = 0
for train_index, test_index in kfold.split(X):
X_train, X_test = X.iloc[train_index], X.iloc[test_index]
y_train, y_test = y.iloc[train_index], y.iloc[test_index]
# SGDRegressorモデル
sgd_regressor = SGDRegressor(
max_iter=2000, # 最大イテレーション数
tol=1e-3, # 収束判定の閾値
random_state=42
)
sgd_regressor.fit(X_train, y_train)
pred = sgd_regressor.predict(X_test)
# MSE評価
mse = mean_squared_error(y_test, pred)
rmse = np.sqrt(mse)
cv_mse.append(mse)
n_iter += 1
print(f'#{n_iter} Fold MSE: {round(mse, 2)}, RMSE: {round(rmse, 2)}')
# 平均MSE
mean_mse = np.mean(cv_mse)
print(f"\nAverage MSE across all folds: {round(mean_mse, 2)}")
⚠️ 収束警告への対処
⚠️ ConvergenceWarning
「最大イテレーション回数に達しても収束しなかった」という警告が出る場合があります。
原因と対策:
- max_iterの増加
SGDRegressor(max_iter=8000)
- 学習率の調整
SGDRegressor(learning_rate='constant', eta0=0.001)
- 特徴量の標準化
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
📊 特徴量標準化を含む改善版
from sklearn.preprocessing import StandardScaler
# 特徴量の標準化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# K-Fold交差検証
kfold = KFold(n_splits=5, shuffle=True, random_state=42)
cv_mse = []
n_iter = 0
for train_index, test_index in kfold.split(X_scaled):
X_train, X_test = X_scaled[train_index], X_scaled[test_index]
y_train, y_test = y.iloc[train_index], y.iloc[test_index]
# 改善されたSGDRegressor
sgd_regressor = SGDRegressor(
max_iter=8000,
tol=1e-3,
learning_rate='constant',
eta0=0.001,
random_state=42
)
sgd_regressor.fit(X_train, y_train)
pred = sgd_regressor.predict(X_test)
mse = mean_squared_error(y_test, pred)
rmse = np.sqrt(mse)
cv_mse.append(mse)
n_iter += 1
print(f'#{n_iter} Fold MSE: {round(mse, 2)}, RMSE: {round(rmse, 2)}')
mean_mse = np.mean(cv_mse)
print(f"\nAverage MSE across all folds: {round(mean_mse, 2)}")
📊 結果の比較
LinearRegression vs SGDRegressor
| モデル | 平均MSE | 特徴 |
|---|---|---|
| LinearRegression | 約2900-3000 | 正確、小規模データ向き |
| SGDRegressor(標準化なし) | 約3250 | 収束しにくい |
| SGDRegressor(標準化あり) | 約2900-3000 | 大規模データに効率的 |
💡 実務での選択
- 小規模データ:LinearRegression(シンプルで高精度)
- 大規模データ:SGDRegressor(メモリ効率が良い)
- 必ず特徴量を標準化する(SGD系アルゴリズムでは必須)
🎯 実習課題
🎯 課題:カリフォルニア住宅価格の予測
課題内容:
California Housing Datasetを読み込んで、住宅価格を予測するSGDRegressorモデルを作成してください。
参考URL:
https://scikit-learn.org/1.5/modules/generated/sklearn.datasets.fetch_california_housing.html要件:
- データセットの読み込みと基本情報の確認
- 特徴量の標準化処理
- LinearRegressionとSGDRegressorの両方で実装
- 5-fold交差検証による性能評価
- 両モデルの結果を比較・考察
ヒント:
from sklearn.datasets import fetch_california_housing housing = fetch_california_housing() print(housing.DESCR) # データセットの説明を確認評価指標:
- MSE(Mean Squared Error)
- RMSE(Root Mean Squared Error)
- 各Foldごとの結果と平均値
📚 第2章のまとめ
🎯 第2章の重要ポイント
- 回帰は連続的な数値を予測する機械学習手法
- 線形回帰は入力と出力の線形関係をモデル化
- RSS/MSEは誤差を測定するための指標
- 勾配降下法はコスト関数を最小化する最適化手法
- SGDは大規模データに効率的な学習アルゴリズム
- 特徴量の標準化はSGD系アルゴリズムで重要
💡 次章への繋がり
第2章では数値予測のための回帰を学びました。次の第3章では、画像データを扱うための畳み込みニューラルネットワーク(CNN)の基礎を学びます。
→ 第3章 深層学習:CNN Ⅰ
