機械学習のための数学

目次

概要

ベクトル、微分、確率を「モデルが学ぶ理由」とつなげて理解する

機械学習では、数学は単なる前提知識ではなく、データを表し、ずれを測り、更新方向を決め、不確実性を扱うための言語になります。この章では、線形代数、微分積分、確率統計、最適化、数値計算を、機械学習との接点が見える形で整理します。

要点

この章は、数学を「公式の暗記」ではなく「機械学習で何をしているかを説明する道具」として読むための土台です。ベクトルと行列はデータ表現、微分は更新方向、確率は不確実性、統計は推定、最適化は学習そのものにつながります。

この章で重視すること

  • 数学の各分野が、機械学習のどこに現れるかを対応づける
  • 公式より先に、何を見ている道具かを押さえる
  • 手計算の詳細より、モデル設計と評価につながる見方を優先する

数学が機械学習で果たす役割

機械学習の流れを雑に分けると、

  • データを表す
  • モデルで予測する
  • ずれを測る
  • ずれが減る方向へ更新する
  • 未知データでも通用するかを確かめる

の5段階です。数学はそれぞれの段階で役割が違います。

数学 機械学習での役割
線形代数 データとパラメータの表現
微分積分 勾配、変化率、更新方向
確率 ノイズ、不確実性、確率的予測
統計 推定、検定、評価、汎化
最適化 学習の更新則
数値計算 厳密解がないときの近似

ベクトルと行列

機械学習で1サンプルは、通常 順番付きの数の列 として扱います。これがベクトルです。多くのサンプルを縦に積むと行列になります。

  • 1サンプル: x
  • サンプル全体: X
  • 正解: y
flowchart TB A["1サンプル"] --> B["ベクトルx"] C["サンプルを集める"] --> D["行列X"] D --> E["各行が1サンプル"] D --> F["各列が特徴量"]

この見方を持つと、前処理、モデル、評価の多くが「行列に対する操作」としてまとまって見えるようになります。

線形変換と固有値

行列は単なる表ではなく、入力を別の空間へ写すルール としても読めます。これが線形変換です。

  • 線形回帰: 重み付き和で予測
  • PCA: 分散の大きい方向へ軸を取り直す
  • 埋め込み: 高次元ベクトルへの写像

固有値・固有ベクトルは、変換しても向きが保たれる特別な方向を表します。PCAやスペクトル分解の直感はここにあります。

微分と勾配

微分は 変化率 を見る道具です。機械学習では「パラメータを少し動かしたとき、損失がどちらへ増減するか」を知るために使います。

  • 1変数: 傾き
  • 多変数: 勾配
flowchart LR A["損失L(theta)"] --> B["微分・偏微分"] B --> C["勾配"] C --> D["減る方向へ更新"]

勾配降下法の核心は、勾配そのものよりも、

  • 今どちらへ進むべきか
  • どれだけ進みすぎると不安定か

を読むことにあります。

積分と連続量の見方

積分は、機械学習の入門では目立ちにくいですが、確率密度、期待値、連続分布、物理モデルベースの最適化では重要です。

積分の見方は一貫しています。

  • 小さな寄与に分ける
  • 全体を足し合わせる

連続確率分布の面積が1になる、期待値が「重み付き平均」として書ける、という感覚は積分の延長です。

確率と確率分布

分類モデルの出力は「ラベル」ではなく、まず 確率 として読む方が自然です。確率分布を使うと、

  • 不確実性の大きさ
  • よく起こる範囲
  • 外れ値の見え方

を整理できます。

よく出てくる分布:

  • ベルヌーイ分布
  • 二項分布
  • 正規分布
  • ポアソン分布

期待値、分散、共分散

期待値は長期平均、分散はばらつきの大きさ、共分散は2つの量が一緒に動く傾向を表します。

これらは、

  • 損失の平均
  • ノイズの大きさ
  • 特徴量の相関
  • 分散共分散行列

へそのままつながります。PCA、線形回帰、ガウス分布系モデルでは特に重要です。

回帰と統計的推測

回帰は「当てる技術」ですが、統計の視点では

  • 何を説明変数にするか
  • 係数をどう解釈するか
  • 不確実性をどう扱うか

も大事です。

統計的推測の考え方は、機械学習でいう

  • サンプルから全体を推定する
  • 訓練データの結果をそのまま信じすぎない
  • 偶然の当たりを見抜く

という姿勢の土台になります。

最適化

機械学習では、学習はほぼ「目的関数を下げる問題」として書けます。

代表的な考え方:

  • 勾配降下法
  • 確率的勾配降下法(SGD)
  • Momentum
  • Adam
  • 正則化

最適化で見るべき点は、

  • 目的関数の形
  • 更新の安定性
  • 局所解や平坦部
  • 学習率の設計

です。

数値計算と近似

現実の機械学習では、閉形式の厳密解より、近似反復の方がずっと多く使われます。

たとえば、

  • 勾配を反復で追う
  • 逆行列を直接作らず分解で解く
  • 大規模行列を近似で扱う
  • ニュートン法や数値積分を使う

といった場面です。

数値計算の観点を持つと、「理論式はあるのに実装では別の形を使う」理由が分かりやすくなります。

機械学習の前提として何を先に学ぶか

全部を同じ深さで先に学ぶ必要はありません。優先度をつけるなら次です。

  1. ベクトルと行列
  2. 微分と勾配
  3. 確率、期待値、分散
  4. 回帰と統計の基本
  5. 最適化

積分、固有値、数値計算は、その後に必要なタイミングで深める方が入りやすいことが多いです。

ヒント

数学を先に完全に仕上げようとすると止まりやすいです。機械学習の章を読みながら「ここでこの数学が必要になるのか」と往復すると定着しやすくなります。

損失関数と幾何

機械学習の数学は、式を覚えるより「何を最小化しているか」を見ると理解しやすくなります。損失関数は、予測と正解のずれを地形として表します。学習は、その地形の低い場所を探す手続きです。

概念 機械学習での意味
勾配 どちらへ動くと損失が増えるか
学習率 1回の更新でどれだけ動くか
凸性 局所解と大域解の扱いやすさ
正則化 解の複雑さへ罰則を置く

線形回帰では地形が比較的扱いやすく、深層学習では高次元で非凸な地形になります。

確率をどう読むか

分類モデルの出力は、しばしば確率として扱われます。ただし、softmaxの最大値が高いことと、現実に正しい確率であることは別です。

確率で見るべきこと:

  • 不確実性
  • キャリブレーション
  • 事前確率
  • 条件付き確率
  • 尤度

ベイズ的な見方では、観測データによって信念を更新する、と捉えます。頻度主義的な見方では、データ生成過程と推定量の性質を重視します。実務では両方の語彙が出るため、混同しないことが大切です。

行列計算と実装

ベクトルや行列は、単なる数学記号ではなく、実装上の性能にも関係します。

  • 行列積はGPUで高速化しやすい
  • batch化すると並列度が上がる
  • メモリ配置が性能に影響する
  • broadcastingは便利だが意図しない形の計算を生むことがある

数式で XW + b と書ける処理は、実装ではshape、dtype、device、memory layoutを確認する必要があります。

先に押さえる優先順位

機械学習のための数学を学ぶなら、最初から全分野を均等に深掘りする必要はありません。

  1. ベクトル、行列、内積、ノルム
  2. 微分、偏微分、勾配
  3. 確率、期待値、分散
  4. 線形回帰と最小二乗
  5. 交差エントロピーと最尤推定
  6. 最適化と正則化

この順に理解すると、回帰、分類、ニューラルネット、評価指標がつながりやすくなります。

線形代数の機械学習への応用

機械学習の多くのアルゴリズムは、線形代数の操作に帰着します。行列と ベクトルの理解が、アルゴリズムの動作原理を把握する鍵となります。

ベクトルと行列の意味

ベクトル:データポイントの特徴表現

user1 = [age: 25, height: 180, income: 60000]
      = [25, 180, 60000]  # 3次元ベクトル

行列:複数のデータポイント

     age  height  income
u1:  25    180    60000
u2:  30    175    75000
u3:  22    165    45000

行列 X = [[25, 180, 60000],
          [30, 175, 75000],
          [22, 165, 45000]]  # 3×3 行列

線形変換

行列の乗算は、ベクトル空間の変換を表します。

import numpy as np

# 3次元の点
point = np.array([1, 0, 0])

# 回転行列(z軸周り 45度)
rotation = np.array([
    [np.cos(45°), -np.sin(45°), 0],
    [np.sin(45°),  np.cos(45°), 0],
    [0,            0,            1]
])

# 変換後の点
rotated = rotation @ point  # 行列積

機械学習では:

  • 特徴変換(Feature Transformation)
  • 次元削減(PCA)
  • ニューラルネットの層間計算

すべてが線形変換です。

固有値・固有ベクトル

行列 A に対して、方向が変わらない特殊なベクトル v と、その倍率 λ:

A @ v = λ * v

例:顔認識での主成分分析(Eigenfaces)

# 顔画像の共分散行列
cov_matrix = compute_covariance(face_images)

# 固有値と固有ベクトルを計算
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)

# 最大の固有値に対応する固有ベクトル = 最も重要な顔パターン
main_face_pattern = eigenvectors[:, 0]

固有ベクトルが「顔認識において最も差別的な特徴」を表します。

確率と統計の基礎

機械学習は本質的に確率的です。データからの学習には不確定性が伴います。

確率分布

正規分布(Gaussian Distribution)

機械学習で最も一般的。多くの自然現象が正規分布に従う。

身長、テスト成績、センサー計測値など
from scipy.stats import norm
import numpy as np

# 平均 170cm、標準偏差 10cm の身長分布
mu, sigma = 170, 10
x = np.linspace(mu - 4*sigma, mu + 4*sigma, 100)
pdf = norm.pdf(x, mu, sigma)

# 180cm 以上の確率
p_above_180 = 1 - norm.cdf(180, mu, sigma)  # ≈ 0.1587

ベルヌーイ分布

コイン投げのように、0 または 1 の結果。

メール分類:スパム(1)か正常(0)

ベイズ定理

P(A|B) = P(B|A) * P(A) / P(B)

事後確率 = 尤度 * 事前確率 / 周辺確率

例:スパム分類

P(Spam | "Buy now") = P("Buy now"|Spam) * P(Spam) / P("Buy now")

テキスト内に「Buy now」があれば、スパムの確率を上げる。

最尤推定(Maximum Likelihood Estimation)

データから分布のパラメータを推定する方法。

# コイン投げで表が n 回出た
# コインのバイアスを推定

def likelihood(p, outcomes):
    """尤度関数"""
    heads = sum(outcomes)
    tails = len(outcomes) - heads
    return p**heads * (1-p)**tails

outcomes = [1, 1, 0, 1, 0]  # 3回表、2回裏
p_estimate = 3 / 5  # 0.6

# この p で、観測データが得られる確率は最大
likelihood(0.6, outcomes)  # 最大値

最適化アルゴリズム

モデルのパラメータを最適化する過程。

勾配降下法(Gradient Descent)

損失関数の勾配を計算して、最小値へ向かう。

def gradient_descent(x, y, learning_rate=0.01, iterations=1000):
    m, b = 0, 0  # 初期値
    n = len(x)
    
    for _ in range(iterations):
        # 勾配計算
        y_pred = m * x + b
        error = y_pred - y
        
        dm = (2 / n) * np.dot(x, error)  # m の勾配
        db = (2 / n) * np.sum(error)     # b の勾配
        
        # パラメータ更新
        m -= learning_rate * dm
        b -= learning_rate * db
    
    return m, b

変種:確率的勾配降下法(SGD)

全データで勾配計算する代わりに、小さなバッチで計算。

batch_size = 32
for epoch in range(num_epochs):
    for batch_start in range(0, n, batch_size):
        batch_end = batch_start + batch_size
        x_batch = x[batch_start:batch_end]
        y_batch = y[batch_start:batch_end]
        
        # batch でパラメータ更新
        update_params(x_batch, y_batch)

メリット

  • 学習が高速
  • メモリ効率的
  • 局所最小値から脱出しやすい

アダプティブ学習率(Adam)

学習率を動的に調整し、より良い収束を実現。

# Adam(Adaptive Moment Estimation)
def adam(x, y, learning_rate=0.001, iterations=1000):
    m_grad, v_grad = 0, 0  # 1st, 2nd moment
    beta1, beta2 = 0.9, 0.999
    epsilon = 1e-8
    
    for t in range(1, iterations + 1):
        grad = compute_gradient(x, y)
        
        # モーメント更新
        m_grad = beta1 * m_grad + (1 - beta1) * grad
        v_grad = beta2 * v_grad + (1 - beta2) * grad**2
        
        # バイアス補正
        m_hat = m_grad / (1 - beta1**t)
        v_hat = v_grad / (1 - beta2**t)
        
        # パラメータ更新
        params -= learning_rate * m_hat / (np.sqrt(v_hat) + epsilon)
    
    return params

多くのディープラーニングフレームワークの標準最適化器。

ニューラルネットワークの数学

フォワードパス(Forward Pass)

入力から出力まで、層を通してデータが流れる計算。

入力 x
  → 線形変換:z₁ = W₁ @ x + b₁
  → 非線形活性化:a₁ = ReLU(z₁)
  → 線形変換:z₂ = W₂ @ a₁ + b₂
  → ソフトマックス:y_pred = softmax(z₂)
  → 出力

バックプロパゲーション(Backpropagation)

逆方向に誤差を伝播させ、各パラメータの勾配を計算。

Loss = Cross-Entropy(y_pred, y_true)
  ↓
dLoss/dW₂ を計算
  ↓
dLoss/da₁ を計算(連鎖律)
  ↓
dLoss/dW₁ を計算
  ↓
パラメータ更新

連鎖律(Chain Rule)

∂L/∂W₁ = ∂L/∂z₂ * ∂z₂/∂a₁ * ∂a₁/∂z₁ * ∂z₁/∂W₁

過学習と正則化

モデルがトレーニングデータに過度に適応する問題。

L1 / L2 正則化

損失関数にパラメータのノルムを加える。

# L2 正則化(Ridge)
loss = mse_loss(y_pred, y_true) + lambda * np.sum(weights**2)

# L1 正則化(Lasso)
loss = mse_loss(y_pred, y_true) + lambda * np.sum(np.abs(weights))

効果

  • L1:スパース解(多くのパラメータが 0 になる)
  • L2:小さなパラメータを選好

ドロップアウト

トレーニング中、ランダムにニューロンを無効化。

def dropout(x, dropout_rate=0.5):
    mask = np.random.binomial(1, 1 - dropout_rate, size=x.shape)
    return x * mask / (1 - dropout_rate)

トレーニング時に異なるネットワークトポロジーを強制し、過学習を防ぐ。

実装とデバッグ

勾配計算の数値安定性が重要。Gradient clipping、batch normalization で training の安定化。Adam などの adaptive optimizer で収束性向上。

実装時の数値安定性

機械学習アルゴリズムを実装するときの落とし穴:

Underflow/Overflow

# 悪い例:log likelihood が underflow
p = 1e-300
log_p = log(p)  # overflow

# 良い例:log-space で計算
log_p = -300 * log(10)  # 安全

log-sum-exp trick:

def logsumexp(x):
  max_x = max(x)
  return max_x + log(sum(exp(x_i - max_x) for x_i in x))

数値的に安定。

Gradient Clipping

梯度消失/爆発を防止:

gradients = [min(max(g, -1.0), 1.0) for g in gradients]

RNN training で必須。

Numerical Issues in Algorithms

線形方程式求解:

A @ x = b の solution

A が ill-conditioned の場合、round-off error が増幅。

SVD を使った robust solution:

U, S, Vt = np.linalg.svd(A)
x = Vt.T @ np.diag(1/S) @ U.T @ b  # SVD による求解

統計的有意性

機械学習では統計的有意性テストが重要。

仮説検定

帰無仮説 H0: model A と model B に差なし 対立仮説 H1: 差がある

p-value < 0.05 なら H0 を棄却(有意)。

多重検定補正

複数の仮説検定でalpha error が増加 → Bonferroni correction:

adjusted_alpha = 0.05 / number_of_tests

モデル評価の陥穽

時系列データの cross-validation

通常の random split は invalid(data leakage)。

正しい方法:

Train: [year 1-2]
Test: [year 3]
 ↓
Train: [year 1-3]
Test: [year 4]

時間順に forward-chaining。

不均衡データセット

クラス不均衡の場合、accuracy は misleading。

正例 1%, 負例 99%
→ すべて negative と予測しても 99% accuracy

使用すべき指標:
- Precision, Recall
- F1 score
- AUROC

Stratified Split

クラス比を保持:

from sklearn.model_selection import StratifiedKFold

skf = StratifiedKFold(n_splits=5)
for train, test in skf.split(X, y):
  # クラス比が train/test で同じ

本番機械学習システム

モデルサービング

学習済みモデルを本番環境で使用:

Model → Serialization (pickle, ONNX, SavedModel)
     → REST API (Flask, FastAPI)
     → Inference Server (TensorFlow Serving, Triton)

Latency, throughput, resource usage のトレードオフ。

モデル監視

本番後のモデル性能劣化(data drift)を検知:

Training data distribution: N(mu=0, sigma=1)
Production data: N(mu=0.5, sigma=1.5)  ← drift

定期的に performance metric を監視。

A/Bテスト

新モデル vs 既存モデル:

50% のユーザーに新モデル
50% のユーザーに既存モデル
→ business metric を比較(conversion rate等)

統計的有意性が重要。

ML と Mathematics の関係

Machine learning は applied mathematics。基礎理論と実装が密接。

Linear algebra: データ操作 Calculus: 最適化 Probability: 不確実性の表現 Statistics: 推論

それぞれが ML algorithm に essential。

継続的な学習

ML field は急速に進化:

  • Papers(arXiv)の publish:毎日 50+本
  • Conference:ICML, NeurIPS, ICCV
  • Community:Kaggle, GitHub

最新の technique を追い続ける努力が不可欠。

実装時のチェックリスト

ML モデル実装時:

  1. データ前処理:normalization、handling missing values
  2. 特徴選択:不要な特徴の削除
  3. ハイパーパラメータ tuning:grid search または bayesian
  4. cross-validation:モデル性能の unbiased estimate
  5. テスト セット評価:最後の一度だけ

これらを守ることで、overfitting や selection bias を回避。

継続的成長

機械学習は mathematics と computer science の融合。論文を読んで最新技術を学ぶ、Kaggle で実装してみる、オープンソースに貢献する―これらを通じてスキルを磨きます。

実務での数学的直観

固有値分解(Eigendecomposition)の意義

固有値 λ と固有ベクトル v:

A * v = λ * v

直観:行列 A による変換後も、ベクトル v の方向は変わらず、スカラー λ 倍に伸縮するだけ。

応用例

  1. PCA(主成分分析)

    • 共分散行列 Σ の固有ベクトルが主成分
    • 固有値が各成分の説明分散
    • 大きな固有値 → 重要な成分
  2. PageRank

    • リンク行列の固有ベクトル = ウェブページの重要度
  3. CNN の特徴抽出

    • 畳み込み層は線形変換
    • 固有ベクトルが「学習された特徴」を表現

テーラー展開と近似

複雑な関数を多項式で近似:

f(x)f(a) + f'(a)(x - a) + f''(a)/2! * (x - a)² + ...

応用

  1. 勾配降下法

    • f(x - α * ∇f(x)) ≈ f(x) - α ||∇f(x)||²
    • 1 次テーラー展開で勾配方向の効果を近似
  2. ニュートン法

    • 2 次テーラー展開を使い、1 ステップでより大きく更新
  3. Softmax の安定化

    # 数値不安定(オーバーフロー)
    softmax(x) = exp(x) / sum(exp(x))
    
    # テーラー展開を使った安定化
    softmax(x) = exp(x - max(x)) / sum(exp(x - max(x)))
    # max(x) を引くことで指数の引数を小さくする
    

実装時のチェックリスト詳細

Gradient Checking(勾配検証)

実装した勾配計算が正しいかを確認:

# 数値勾配(有限差分法)
epsilon = 1e-5
numerical_grad = (f(x + epsilon) - f(x - epsilon)) / (2 * epsilon)

# 解析的勾配(バックプロップで計算)
analytical_grad = backprop(x)

# 差分が小さいか確認
assert np.allclose(numerical_grad, analytical_grad, atol=1e-4)

Loss Curve の診断

訓練 loss と検証 loss をプロット:

- 両方が減少 → 正常
- 訓練のみ減少、検証が増加 → overfitting
- 両方が高い値で停滞 → underfitting か学習率が低い
- 訓練 loss がゼロ付近でも検証が高い → 強い overfitting

バッチサイズの影響

小バッチ(32):
- ノイズが多い(勾配推定の分散大)
- 正則化効果(implicit regularization)
- 局所最適値から脱出しやすい
- メモリ効率良い

大バッチ(2048):
- 勾配推定が安定(分散小)
- 並列化効率良い
- 局所最適値に陥りやすい
- メモリ消費多い

実務:通常 32-256 が最適

線形代数の応用: ニューラルネットワークの観点

行列分解とその実用的意義

行列分解(Matrix Factorization)は機械学習の多くの領域で現れます。特にニューラルネットワークの学習過程では、重み行列の更新が行列分解的な性質を持ちます。

特異値分解(SVD)の応用例

SVDはA = UΣV^Tの形式で行列を分解します。ここでΣは対角行列で、特異値を含みます。推薦システムではこの分解を使用して、ユーザー嗜好とアイテム特性を低次元空間に埋め込みます。

import numpy as np
from scipy.sparse.linalg import svds

# ユーザー-アイテム評価行列
R = np.array([
  [5, 0, 3],
  [0, 4, 0],
  [2, 0, 5],
  [0, 3, 4]
])

# SVDで因子化
U, sigma, Vt = svds(R, k=2)
print(f"Singular values: {sigma}")  # [3.4, 5.1] など
R_reconstructed = U @ np.diag(sigma) @ Vt

ランクkでの近似により、ノイズを除去し、スパース行列を密な表現に変換できます。

固有値分解の機械学習への応用

固有値分解(Eigendecomposition)A = PΛP^{-1}は、対称行列の分析で重要です。特に共分散行列の分析では、固有ベクトルは最大分散の方向を示します。

主成分分析(PCA)の理論

PCAは共分散行列の固有値分解に基づきます。最大固有値に対応する固有ベクトルが、データの最大分散方向(第1主成分)です。

from sklearn.decomposition import PCA
import numpy as np

# 100次元のデータを2次元に削減
X = np.random.randn(1000, 100)
pca = PCA(n_components=2)
X_reduced = pca.fit_transform(X)

print(f"Explained variance: {pca.explained_variance_ratio_}")
# 例: [0.45, 0.23] → 68%の分散を保持

PCAの計算複雑度はO(min(n^2d, nd^2))です(n: サンプル数、d: 次元数)。高次元データでは、スケーラビリティが課題になります。

確率・統計の深掘り

ベイズ推定の実装例

ベイズの定理P(θ|D) = P(D|θ)P(θ) / P(D)は機械学習の基礎です。事前分布と尤度関数を組み合わせて事後分布を計算します。

from scipy.stats import binom
import numpy as np

# コイン投げ: 10回中7回表
# 事前分布: Beta(1, 1) (一様)
# 尤度: Binomial
# 事後分布: Beta(1+7, 1+3) = Beta(8, 4)

alpha, beta = 8, 4
x = np.linspace(0, 1, 100)
posterior = binom.pdf(x, n=100, p=alpha/(alpha+beta))

# ベイズ推定: E[θ|D] = alpha / (alpha + beta) = 0.667
posterior_mean = alpha / (alpha + beta)
print(f"Estimated coin bias: {posterior_mean:.3f}")

事前分布の選択は結果に大きく影響します。適切な事前分布を選ぶことは、ドメイン知識の組み込みと同等に重要です。

尤度関数と最大尤度推定

最大尤度推定(MLE)はL(θ; D) = ∏_i P(x_i | θ)を最大化するθを探します。ログ尤度を使うことで数値的安定性が向上します。

def negative_log_likelihood(y_true, y_pred):
    """二項分類のクロスエントロピー"""
    epsilon = 1e-15
    y_pred = np.clip(y_pred, epsilon, 1 - epsilon)
    return -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))

y_true = np.array([1, 0, 1, 1, 0])
y_pred = np.array([0.9, 0.2, 0.8, 0.7, 0.1])
loss = negative_log_likelihood(y_true, y_pred)
print(f"Loss: {loss:.4f}")

ログスケールで計算することで、アンダーフロー(underflow)を防ぎ、勾配計算の安定性を高めます。

微積分と最適化

勾配降下法の収束性

凸関数に対して、勾配降下法の更新式θ_{t+1} = θ_t - α∇f(θ_t)は以下の収束保証を持ちます:

  • L-smooth関数: O(1/t)の収束速度
  • 強凸関数: O(e^{-λt})の指数収束
def gradient_descent(f, grad_f, x0, learning_rate=0.01, iterations=100):
    """勾配降下法の実装"""
    x = x0
    history = [x]
    
    for _ in range(iterations):
        grad = grad_f(x)
        x = x - learning_rate * grad
        history.append(x)
        
    return x, history

# 例: f(x) = x^2 を最小化
f = lambda x: x**2
grad_f = lambda x: 2*x

x_opt, history = gradient_descent(f, grad_f, x0=5.0, learning_rate=0.1)
print(f"Optimal x: {x_opt:.6f}")  # ≈ 0.0

学習率αの選択は収束速度に影響します。αが大きすぎるとダイバージし、小さすぎると収束が遅くなります。

ヘッシアンと二階微分

ニューロンネットワークの最適化では、ヘッシアン行列(2階偏導関数)が重要な役割を果たします。ヘッシアンの固有値はその点の曲率を表します。

def hessian(f, x, epsilon=1e-5):
    """数値ヘッシアン計算"""
    n = len(x)
    H = np.zeros((n, n))
    
    for i in range(n):
        for j in range(n):
            x_pp = x.copy()
            x_pp[i] += epsilon
            x_pp[j] += epsilon
            f_pp = f(x_pp)
            
            x_pm = x.copy()
            x_pm[i] += epsilon
            x_pm[j] -= epsilon
            f_pm = f(x_pm)
            
            x_mp = x.copy()
            x_mp[i] -= epsilon
            x_mp[j] += epsilon
            f_mp = f(x_mp)
            
            x_mm = x.copy()
            x_mm[i] -= epsilon
            x_mm[j] -= epsilon
            f_mm = f(x_mm)
            
            H[i, j] = (f_pp - f_pm - f_mp + f_mm) / (4 * epsilon**2)
    
    return H

# 2変数関数
f = lambda x: x[0]**2 + 2*x[1]**2 + x[0]*x[1]
H = hessian(f, np.array([1.0, 1.0]))
eigenvalues = np.linalg.eigvals(H)
print(f"Eigenvalues: {eigenvalues}")  # 凸性の確認

ヘッシアンが正定値なら、その点は局所最小値です。機械学習では、ニュートン法やBFGS法といった二階法が、勾配降下法より少ない反復で収束することがあります。

確率分布と生成モデル

正規分布とガウス過程

多変量正規分布N(μ, Σ)は機械学習の中心的な分布です。共分散行列Σの構造は、変数間の依存性をモデル化します。

from scipy.stats import multivariate_normal
import numpy as np

# 2変量正規分布
mu = np.array([0, 0])
sigma = np.array([[1, 0.5], [0.5, 1]])

rv = multivariate_normal(mean=mu, cov=sigma)
samples = rv.rvs(size=1000)

print(f"Correlation: {np.corrcoef(samples.T)}")
# [[1.0, 0.5], [0.5, 1.0]] に近い

ガウス過程は無限次元の正規分布として見なせます。カーネル関数k(x, x’)により、入力空間の相似性を定義します。

from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF

# RBFカーネルを使用したGP
kernel = RBF(length_scale=1.0)
gp = GaussianProcessRegressor(kernel=kernel, alpha=1e-6)

X = np.array([[0], [1], [2]])
y = np.array([0, 1, 0.5])
gp.fit(X, y)

# 予測と信頼区間
X_test = np.linspace(-1, 3, 100).reshape(-1, 1)
y_pred, sigma = gp.predict(X_test, return_std=True)

ガウス過程の計算量はO(n^3)であり、大規模データセットでは近似が必要になります。

まとめ

機械学習に必要な数学は、線形代数、微分積分、確率統計、最適化、数値計算が中心です。大切なのは、公式の暗記よりも「どの場面で何を見ている道具か」をつなげて理解することです。

参考文献

講義・記事

書籍

解説・補助