8日目:回帰・分類タスクのためのデータ準備!線形モデルとロジスティック回帰
皆さん、こんにちは!AI学習ロードマップ8日目を迎えました。最初の7日間で、AI学習の土台となるPythonの基礎、データ操作、可視化、前処理、特徴量エンジニアリング、そしてデータ分割の重要性を学びました。
今日からはいよいよ、これらの準備されたデータを使って、AIモデルが実際にどのように学習し、予測を行うのかという核心に迫っていきます。本日は、機械学習の最も基本的なモデルである「線形回帰」と「ロジスティック回帰」に焦点を当て、それぞれのモデルがどのようなタスクに適しているのか、そしてそれらのモデルのためのデータ準備について詳しく解説します。
AIモデルを理解する上で、これらの基礎的なモデルの仕組みを把握することは非常に重要です。本日は、それぞれのモデルの理論、適用例、そしてPythonでの実装方法を、豊富なコード例とともに見ていきましょう。
1. 機械学習のタスク:回帰と分類
AIモデルが解決しようとする問題は、大きく分けて「回帰」と「分類」の2つの主要なタスクに分類されます。
1.1. 回帰 (Regression) タスク
- 目的: 連続的な数値(量)を予測すること。
-
例:
- 住宅価格の予測(例:広さ、築年数、立地から価格を予測)
- 株価の予測(例:過去の株価、経済指標から明日の株価を予測)
- 売上高の予測(例:広告費、季節性から来月の売上を予測)
- 気温の予測(例:過去の気温、湿度から明日の気温を予測)
1.2. 分類 (Classification) タスク
- 目的: データがどのカテゴリ(クラス)に属するかを予測すること。出力は離散的なカテゴリです。
-
例:
- スパムメールの検出(例:メールの内容からスパムか否かを分類)
- 顧客の離反予測(例:顧客の行動履歴から離反するか否かを分類)
- 画像認識(例:画像から猫、犬、鳥などを分類)
- 病気の診断(例:患者の症状、検査結果から病気の種類を分類)
2. 線形回帰 (Linear Regression):連続値予測の基礎
線形回帰は、回帰タスクの最も基本的なモデルであり、特徴量と目的変数の間に線形関係を仮定します。
2.1. 線形回帰の原理
線形回帰は、特徴量(入力)と目的変数(出力)の関係を、最もよく当てはまる 直線(または超平面) で表現しようとします。
-
単回帰(Simple Linear Regression): 1つの特徴量 $x$ から目的変数 $y$ を予測する場合。
$y = w_0 + w_1 x$
ここで、$w_0$は切片、$w_1$は傾き(重み)です。 -
重回帰(Multiple Linear Regression): 複数の特徴量 $x_1, x_2, \dots, x_n$ から目的変数 $y$ を予測する場合。
$y = w_0 + w_1 x_1 + w_2 x_2 + \dots + w_n x_n$
ここで、$w_0$は切片、$w_i$は各特徴量に対応する重みです。
モデルは、予測値と実際の値との差(残差)の二乗和が最小になるように、これらの重み $w_i$ を学習します。これを最小二乗法と呼びます。
2.2. 線形回帰のためのデータ準備
線形回帰は、特徴量と目的変数の間に線形関係を仮定するため、以下の点に注意してデータを準備します。
-
数値特徴量: 全ての入力特徴量は数値である必要があります。カテゴリ変数はワンホットエンコーディングなどで数値に変換します。
- ワンホットエンコーディング: カテゴリカルデータを、各カテゴリに対応するバイナリ(0または1)の列に変換することで、モデルがカテゴリデータを理解しやすくなります。
- 外れ値の処理: 外れ値はモデルの直線に大きな影響を与えるため、適切に処理する必要があります。
- 多重共線性の確認: 特徴量間に強い相関がある場合(多重共線性)、モデルの解釈が難しくなったり、不安定になったりすることがあります。相関の高い特徴量の一方を削除するなどの対策を検討します。
- スケーリング: 線形回帰自体はスケーリングに影響を受けにくいですが、勾配降下法を用いる場合や、他のモデルと比較する際にはスケーリングが推奨されます。
2.3. Pythonでの実装例 (scikit-learn)
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# サンプルデータの生成 (住宅価格予測を想定)
np.random.seed(42)
# 広さ (平方メートル)
X_area = np.random.rand(100, 1) * 100 + 50 # 50〜150平方メートル
# 築年数 (年)
X_age = np.random.rand(100, 1) * 30 + 5 # 5〜35年
# 部屋数
X_rooms = np.random.randint(1, 6, 100).reshape(-1, 1)
# 目的変数: 価格 (万円) - 広さに比例し、築年数に反比例、部屋数に比例
y_price = (X_area * 5 + X_rooms * 100 - X_age * 2 + np.random.randn(100, 1) * 50).flatten()
# DataFrameに結合
df_house = pd.DataFrame({
'Area': X_area.flatten(),
'Age': X_age.flatten(),
'Rooms': X_rooms.flatten(),
'Price': y_price
})
print("--- サンプル住宅データ ---")
print(df_house.head())
# 特徴量 (X) と目的変数 (y) を定義
X = df_house[['Area', 'Age', 'Rooms']]
y = df_house['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"\n--- 線形回帰モデルの評価 ---")
print(f"平均二乗誤差 (MSE): {mse:.2f}")
print(f"決定係数 (R^2): {r2:.2f}")
# モデルの係数と切片
print(f"\n--- モデルの係数と切片 ---")
print(f"係数 (重み): {model.coef_}")
print(f"切片: {model.intercept_:.2f}")
# 予測値と実測値の散布図 (可視化)
plt.figure(figsize=(8, 6))
sns.scatterplot(x=y_test, y=y_pred)
plt.xlabel("Actual Price (万円)")
plt.ylabel("Predicted Price (万円)")
plt.title("Actual vs Predicted Prices (Linear Regression)")
plt.plot([y.min(), y.max()], [y.min(), y.max()], 'r--', lw=2) # 理想的な予測線
plt.grid(True)
plt.show()
LinearRegression
モデルを訓練し、mean_squared_error
(平均二乗誤差)とr2_score
(決定係数)で評価します。MSEは予測誤差の平均、R^2はモデルが目的変数の変動をどれだけ説明できているかを示す指標です。R^2が1に近いほど良いモデルと言えます。
3. ロジスティック回帰 (Logistic Regression):二値分類の基礎
ロジスティック回帰は名前に「回帰」とありますが、実際には分類タスク、特に二値分類(2つのクラスに分類)に用いられるモデルです。
3.1. ロジスティック回帰の原理
線形回帰のように直線を引くのではなく、ロジスティック回帰は、特徴量の線形結合をシグモイド関数(ロジスティック関数)に通すことで、あるクラスに属する確率を出力します。
- 線形結合: $z = w_0 + w_1 x_1 + w_2 x_2 + \dots + w_n x_n$
- シグモイド関数: $\sigma(z) = \frac{1}{1 + e^{-z}}$
シグモイド関数は、任意の実数値を0から1の間の値に変換します。この出力値を確率と解釈し、例えば0.5より大きければクラス1、小さければクラス0と分類します。
モデルは、実際のクラスと予測された確率との差を最小化するように、重み $w_i$ を学習します。この際、最尤推定法という手法が用いられます。
- 最尤推定法(さいゆうすいていほう): 与えられたデータから、そのデータが最も起こりやすい(尤もらしい)と推定される確率分布のパラメータを求める統計学の手法です。より具体的には、尤度関数を最大化するようなパラメータの値を推定します
3.2. ロジスティック回帰のためのデータ準備
ロジスティック回帰も線形回帰と同様に数値特徴量を扱いますが、分類タスクの特性上、以下の点も考慮します。
- 目的変数: 目的変数はカテゴリカル(通常は0と1)である必要があります。
- スケーリング: ロジスティック回帰は勾配降下法で最適化されるため、特徴量のスケーリングは学習の収束を速め、性能を向上させるのに役立ちます。
- クラス不均衡: 分類問題でクラスのデータ数に大きな偏りがある場合(例:正常データ99%、異常データ1%)、モデルが多数派クラスに偏って予測してしまうことがあります。オーバーサンプリング、アンダーサンプリング、または重み付けなどの対策が必要です。
3.3. Pythonでの実装例 (scikit-learn)
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report
from sklearn.preprocessing import StandardScaler # スケーリングの重要性を示すため追加
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# サンプルデータの生成 (顧客の購買予測を想定)
np.random.seed(42)
# 年齢
X_age = np.random.randint(18, 70, 100)
# 収入 (万円)
X_income = np.random.randint(300, 1000, 100)
# 広告クリック回数
X_clicks = np.random.randint(0, 20, 100)
# 目的変数: 購入したか (0:購入せず, 1:購入) - 年齢、収入、クリック回数が多いほど購入確率が高い
# シグモイド関数に近い形で確率を生成し、ランダムに0/1を割り当てる
purchase_prob = 1 / (1 + np.exp(-(0.05 * X_age + 0.005 * X_income + 0.2 * X_clicks - 10)))
y_purchase = (purchase_prob > np.random.rand(100)).astype(int)
df_customer = pd.DataFrame({
'Age': X_age,
'Income': X_income,
'Clicks': X_clicks,
'Purchased': y_purchase
})
print("--- サンプル顧客データ ---")
print(df_customer.head())
print("\n購入クラスの分布:")
print(df_customer['Purchased'].value_counts())
# 特徴量 (X) と目的変数 (y) を定義
X = df_customer[['Age', 'Income', 'Clicks']]
y = df_customer['Purchased']
# 訓練データとテストデータに分割 (stratifyでクラス比率を維持)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# 特徴量のスケーリング (ロジスティック回帰では推奨)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test) # テストデータは訓練データでfitしたscalerでtransformのみ
# ロジスティック回帰モデルの初期化と学習
model = LogisticRegression(random_state=42, solver='liblinear') # solverは小規模データでliblinearが適している
model.fit(X_train_scaled, y_train)
# テストデータで予測
y_pred = model.predict(X_test_scaled)
y_pred_proba = model.predict_proba(X_test_scaled)[:, 1] # クラス1に属する確率
# モデルの評価
accuracy = accuracy_score(y_test, y_pred)
conf_matrix = confusion_matrix(y_test, y_pred)
class_report = classification_report(y_test, y_pred)
print(f"\n--- ロジスティック回帰モデルの評価 ---")
print(f"正解率 (Accuracy): {accuracy:.2f}")
print(f"\n混同行列:\n{conf_matrix}")
print(f"\n分類レポート:\n{class_report}")
# 予測確率の分布 (可視化)
plt.figure(figsize=(8, 6))
sns.histplot(y_pred_proba[y_test == 0], color='blue', label='Actual 0', kde=True, stat='density', alpha=0.5)
sns.histplot(y_pred_proba[y_test == 1], color='red', label='Actual 1', kde=True, stat='density', alpha=0.5)
plt.axvline(x=0.5, color='green', linestyle='--', label='Decision Boundary (0.5)')
plt.title("Predicted Probabilities Distribution")
plt.xlabel("Predicted Probability of Class 1")
plt.ylabel("Density")
plt.legend()
plt.grid(True)
plt.show()
ロジスティック回帰では、accuracy_score
(正解率)、confusion_matrix
(混同行列)、classification_report
(分類レポート)といった指標でモデルを評価します。混同行列は、真陽性(TP)、真陰性(TN)、偽陽性(FP)、偽陰性(FN)の数を表し、分類レポートは適合率(Precision)、再現率(Recall)、F1スコアといった、より詳細な評価指標を提供します。
4. まとめと次へのステップ
本日は、AI学習ロードマップの8日目として、機械学習の主要なタスクである回帰と分類、そしてそれぞれのタスクのための最も基本的なモデルである線形回帰とロジスティック回帰について学びました。
- 回帰タスク: 連続値を予測する問題(例:線形回帰)。
- 分類タスク: カテゴリを予測する問題(例:ロジスティック回帰)。
- 線形回帰: 特徴量と目的変数の線形関係をモデル化し、最小二乗法で最適な直線を学習します。住宅価格予測のような連続値予測に適しています。
- ロジスティック回帰: シグモイド関数を用いて確率を出力し、その確率に基づいて分類を行います。スパム検出や購買予測のような二値分類に適しています。
- 両モデルとも、特徴量の数値化とスケーリングが重要です。特にロジスティック回帰では、クラス不均衡への対策も考慮する必要があります。
これらのモデルはシンプルですが、多くの複雑なモデルの基礎となっており、その原理を理解することは非常に重要です。
明日からは、さらに多様な機械学習モデルの世界に足を踏み入れていきます。決定木やサポートベクターマシンなど、より複雑なパターンを学習できるモデルについて学んでいきましょう。
それでは、また明日!