- Authors
- Name
- はじめに
- Part 1:線形代数(Linear Algebra) — AIの骨格
- Part 2:微積分(Calculus) — 学習のエンジン
- Part 3:確率と統計 — AIの言語
- Part 4:情報理論 — LLMの数学的基礎
- 数学 → AI マッピング要約
- 学習ロードマップ
- おすすめリソース
- 関連シリーズとおすすめ記事

はじめに
「AIを勉強するには数学をどこまでやればいいの?」
答え:線形代数 + 微積分 + 確率/統計 + 最適化。この4つがあれば論文の90%を読むことができます。
この記事は数学の教科書ではありません。AIでなぜこの数学が使われるのかをコードと直感で説明します。nanoGPTをゼロから作るとき、画像生成モデル(DDPM)を学習するとき — この数学がどこで登場するかを紐づけます。
Part 1:線形代数(Linear Algebra) — AIの骨格
なぜ必要か?
ニューラルネットワークのすべての演算は行列の掛け算です。
import numpy as np
# ニューロン1つ = ベクトルの内積
weights = np.array([0.5, -0.3, 0.8]) # 重み
inputs = np.array([1.0, 2.0, 3.0]) # 入力
bias = 0.1
output = np.dot(weights, inputs) + bias
# 0.5*1.0 + (-0.3)*2.0 + 0.8*3.0 + 0.1 = 2.5
# レイヤー全体 = 行列の掛け算
W = np.random.randn(4, 3) # 3 → 4 ニューロン
x = np.random.randn(3) # 入力ベクトル
h = W @ x # 行列-ベクトル積 = レイヤー出力
ベクトル(Vector) — データの表現
# 単語をベクトルで表現(Word Embedding)
king = np.array([0.8, 0.2, 0.9, -0.5])
queen = np.array([0.7, 0.8, 0.85, -0.4])
man = np.array([0.9, 0.1, 0.5, -0.6])
woman = np.array([0.8, 0.7, 0.45, -0.5])
# king - man + woman ≈ queen(有名な関係!)
result = king - man + woman
print(f"king - man + woman = {result}")
print(f"queen = {queen}")
# ほぼ同じ!
# コサイン類似度 — 2つのベクトルがどれくらい似ているか
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
print(cosine_similarity(result, queen)) # ~0.95(非常に類似!)
行列の掛け算(Matrix Multiplication) — ニューラルネットワークの核心
# TransformerのSelf-Attentionも行列の掛け算!
# Q, K, V = 入力に重み行列を掛けたもの
batch_size, seq_len, d_model = 2, 10, 64
X = np.random.randn(batch_size, seq_len, d_model)
W_Q = np.random.randn(d_model, d_model)
W_K = np.random.randn(d_model, d_model)
W_V = np.random.randn(d_model, d_model)
Q = X @ W_Q # Query: (2, 10, 64)
K = X @ W_K # Key: (2, 10, 64)
V = X @ W_V # Value: (2, 10, 64)
# Attention Score = Q × K^T / √d
scores = Q @ K.transpose(0, 2, 1) / np.sqrt(d_model)
# scores shape: (2, 10, 10) — 各トークンが他のトークンに与えるattention
固有値分解(Eigenvalue Decomposition) — PCA、SVD
# PCA:データの主要方向を見つける
from sklearn.decomposition import PCA
# 100次元データ → 2次元に圧縮
data = np.random.randn(1000, 100)
pca = PCA(n_components=2)
reduced = pca.fit_transform(data)
# 内部で起きていること:
# 1. 共分散行列の計算:C = X^T X / n
# 2. 固有値分解:C = V Λ V^T
# 3. 最大の固有値に対応する固有ベクトルを選択
# → データの分散が最も大きい方向!
# SVD(特異値分解) — LLMの圧縮に使用!
# LoRAがまさにこれ:大きな行列を小さな行列2つに分解
W = np.random.randn(768, 768) # GPT-2のattention weight
# SVD: W = U × Σ × V^T
U, S, Vt = np.linalg.svd(W)
# 上位r個だけ残して近似(LoRAの原理!)
r = 16 # rank
W_approx = U[:, :r] @ np.diag(S[:r]) @ Vt[:r, :]
# 元:768×768 = 589,824 パラメータ
# LoRA:768×16 + 16×768 = 24,576 パラメータ(たった4%!)
error = np.linalg.norm(W - W_approx) / np.linalg.norm(W)
print(f"Rank-{r} 近似誤差: {error:.4f}")
Part 2:微積分(Calculus) — 学習のエンジン
なぜ必要か?
ニューラルネットワークの学習 = 損失関数の最小化 = 微分で勾配を求めてパラメータを更新
偏微分(Partial Derivative)
# f(x, y) = x² + 2xy + y²
# ∂f/∂x = 2x + 2y(yを定数として扱う)
# ∂f/∂y = 2x + 2y(xを定数として扱う)
def f(x, y):
return x**2 + 2*x*y + y**2
def df_dx(x, y):
return 2*x + 2*y # x方向の勾配
def df_dy(x, y):
return 2*x + 2*y # y方向の勾配
# 勾配ベクトル(Gradient)
gradient = np.array([df_dx(3, 2), df_dy(3, 2)])
print(f"∇f(3,2) = {gradient}") # [10, 10]
# → この方向の反対に進めば関数値が減少する!
連鎖律(Chain Rule) — 逆伝播の数学的基礎!
# y = f(g(x)) → dy/dx = df/dg × dg/dx
# ニューラルネットワークでは:
# Loss = CrossEntropy(softmax(Wx + b), target)
# dLoss/dW = dLoss/dsoftmax × dsoftmax/d(Wx+b) × d(Wx+b)/dW
# PyTorchがこれを自動で行う!
import torch
x = torch.tensor([1.0, 2.0, 3.0], requires_grad=True)
W = torch.randn(2, 3, requires_grad=True)
b = torch.randn(2, requires_grad=True)
# Forward
h = W @ x + b
loss = h.sum()
# Backward(連鎖律が自動適用!)
loss.backward()
print(f"dLoss/dW = {W.grad}") # 自動微分!
print(f"dLoss/db = {b.grad}")
print(f"dLoss/dx = {x.grad}")
勾配降下法(Gradient Descent) — 山を下りる目隠し登山家
# 損失関数:L(w) = (w - 3)²
# 最小値:w = 3
def loss(w):
return (w - 3) ** 2
def grad(w):
return 2 * (w - 3)
# 勾配降下法
w = 10.0 # 開始点(見当違いの場所)
lr = 0.1 # 学習率
for step in range(20):
g = grad(w)
w = w - lr * g # 勾配の反対方向に移動!
if step % 5 == 0:
print(f"Step {step}: w={w:.4f}, loss={loss(w):.4f}")
# Step 0: w=8.6000, loss=31.3600
# Step 5: w=3.2150, loss=0.0462
# Step 10: w=3.0070, loss=0.0000
# Step 15: w=3.0002, loss=0.0000
# → wが3に収束!
学習率の重要性
lrが大きすぎると:
w: 10 → -4 → 18 → -22 → 発散!
lrが小さすぎると:
w: 10 → 9.86 → 9.72 → ... → 100万ステップ後 → 3.001
適切なlr:
w: 10 → 8.6 → 7.48 → ... → 20ステップ → 3.0002
実践オプティマイザ:Adam
# Adam = Momentum + RMSprop(現代のディープラーニング標準)
class Adam:
def __init__(self, params, lr=0.001, beta1=0.9, beta2=0.999, eps=1e-8):
self.lr = lr
self.beta1 = beta1 # モメンタム(慣性)
self.beta2 = beta2 # 勾配の二乗の移動平均
self.eps = eps
self.m = {id(p): 0 for p in params} # 1次モーメント
self.v = {id(p): 0 for p in params} # 2次モーメント
self.t = 0
def step(self, params, grads):
self.t += 1
for p, g in zip(params, grads):
pid = id(p)
# モメンタム:以前の勾配方向を記憶
self.m[pid] = self.beta1 * self.m[pid] + (1 - self.beta1) * g
# 適応的学習率:勾配の大きさに応じて調整
self.v[pid] = self.beta2 * self.v[pid] + (1 - self.beta2) * g**2
# バイアス補正
m_hat = self.m[pid] / (1 - self.beta1**self.t)
v_hat = self.v[pid] / (1 - self.beta2**self.t)
# 更新
p -= self.lr * m_hat / (np.sqrt(v_hat) + self.eps)
Part 3:確率と統計 — AIの言語
なぜ必要か?
AIモデルの出力はほぼ常に確率分布です。
# GPTの出力 = 次のトークンの確率分布
logits = np.array([2.0, 1.0, 0.1, -1.0, 3.0]) # モデル出力(生の値)
vocab = ["the", "cat", "sat", "on", "mat"]
# Softmax:logits → 確率
def softmax(x):
exp_x = np.exp(x - np.max(x)) # 数値安定性
return exp_x / exp_x.sum()
probs = softmax(logits)
for word, p in zip(vocab, probs):
print(f" {word}: {p:.4f}")
# the: 0.2312, cat: 0.0851, sat: 0.0346, on: 0.0115, mat: 0.6276
# → "mat"が最も高い確率!
ベイズの定理(Bayes' Theorem)
# P(A|B) = P(B|A) × P(A) / P(B)
# 「データを見たときにモデルが正しい確率」
# 例:スパムフィルター
# P(スパム|"無料") = P("無料"|スパム) × P(スパム) / P("無料")
p_free_given_spam = 0.8 # スパムで「無料」が出現する確率
p_spam = 0.3 # 全メール中のスパム割合
p_free = 0.35 # 全メールで「無料」が出現する確率
p_spam_given_free = (p_free_given_spam * p_spam) / p_free
print(f"P(スパム|'無料') = {p_spam_given_free:.2f}") # 0.69 (69%!)
確率分布
# ガウス(正規)分布 — Diffusion Modelの核心!
def gaussian(x, mu=0, sigma=1):
return (1 / (sigma * np.sqrt(2 * np.pi))) * np.exp(-0.5 * ((x - mu) / sigma) ** 2)
# DDPM(画像生成):
# Forward:きれいな画像 → ガウスノイズ追加(徐々に破壊)
# Reverse:ノイズ → ノイズ除去(ニューラルネットが学習) → きれいな画像!
# ノイズ追加プロセス
def add_noise(image, t, noise_schedule):
"""x_t = √(α_bar_t) × x_0 + √(1 - α_bar_t) × ε"""
alpha_bar = noise_schedule[t]
noise = np.random.randn(*image.shape) # ガウスノイズ
noisy = np.sqrt(alpha_bar) * image + np.sqrt(1 - alpha_bar) * noise
return noisy, noise
クロスエントロピー(Cross-Entropy) — 損失関数の王様
# モデルの予測が正解とどれだけ違うかを測定
def cross_entropy(predictions, targets):
"""H(p, q) = -Σ p(x) log q(x)"""
return -np.sum(targets * np.log(predictions + 1e-9))
# 正解:"cat"(ワンホットエンコーディング)
target = np.array([0, 1, 0, 0, 0]) # [the, cat, sat, on, mat]
# 良い予測
good_pred = np.array([0.05, 0.85, 0.03, 0.02, 0.05])
print(f"Good: {cross_entropy(good_pred, target):.4f}") # 0.1625(低い)
# 悪い予測
bad_pred = np.array([0.3, 0.1, 0.2, 0.2, 0.2])
print(f"Bad: {cross_entropy(bad_pred, target):.4f}") # 2.3026(高い)
Part 4:情報理論 — LLMの数学的基礎
エントロピー(Entropy) — 不確実性の尺度
def entropy(probs):
"""H(X) = -Σ p(x) log₂ p(x)"""
return -np.sum(probs * np.log2(probs + 1e-9))
# 公正なコイン:H = 1 bit(最大の不確実性)
fair_coin = np.array([0.5, 0.5])
print(f"公正なコイン: {entropy(fair_coin):.2f} bits") # 1.00
# 偏ったコイン:H は 1 bit 未満(予測可能)
biased_coin = np.array([0.9, 0.1])
print(f"偏ったコイン: {entropy(biased_coin):.2f} bits") # 0.47
# GPTの出力エントロピーが低ければ → モデルが確信している
# Temperatureを上げれば → エントロピー増加 → より多様な出力
KL Divergence — 2つの分布の差
def kl_divergence(p, q):
"""D_KL(P || Q) = Σ p(x) log(p(x) / q(x))"""
return np.sum(p * np.log(p / (q + 1e-9) + 1e-9))
# VAE(Variational Autoencoder)では:
# KL(q(z|x) || p(z))を最小化
# = エンコーダの出力分布を標準正規分布に近づける!
# RLHFでは:
# KL(π_new || π_ref)をペナルティとして追加
# = 新しいモデルが元のモデルから離れすぎないように!
数学 → AI マッピング要約
| 数学概念 | AIでの役割 | 登場する場所 |
|---|---|---|
| 行列の掛け算 | レイヤー演算 | すべてのニューラルネット |
| コサイン類似度 | 埋め込み比較 | 検索、RAG |
| SVD | モデル圧縮 | LoRA、量子化 |
| 偏微分 | 勾配計算 | 逆伝播 |
| 連鎖律 | 自動微分 | PyTorch autograd |
| 勾配降下法 | パラメータ最適化 | Adam、SGD |
| Softmax | 確率分布変換 | 分類、Attention |
| クロスエントロピー | 損失関数 | LLM、分類器 |
| ガウス分布 | ノイズモデリング | DDPM、VAE |
| ベイズの定理 | 事後確率推論 | ベイジアンML |
| KL Divergence | 分布の差の測定 | VAE、RLHF |
| エントロピー | 不確実性の測定 | Temperature、情報量 |
学習ロードマップ
[1週目] 線形代数の基礎
→ ベクトル、行列の掛け算、転置、逆行列
→ numpyで直接実装
[2週目] 微積分 + 最適化
→ 偏微分、連鎖律、勾配降下法
→ PyTorch autogradの理解
[3週目] 確率 + 統計
→ 条件付き確率、ベイズ、分布
→ softmax、cross-entropyの実装
[4週目] 情報理論 + 実践
→ エントロピー、KLダイバージェンス
→ nanoGPT/DDPMのコードから数学を見つける
おすすめリソース
- 3Blue1Brown(YouTube) — 線形代数/微積分の直感的な可視化
- Mathematics for Machine Learning(無料教材) — 数学 → MLへの橋渡し
- Andrej Karpathyのmicrograd — 逆伝播をゼロから
- Stanford CS229 — 確率/統計 + ML数学
- Ian GoodfellowのDeep Learning Book — Ch.2〜4(無料オンライン)
クイズ — AI数学(クリックして確認!)
Q1. ニューラルネットワークにおける行列の掛け算の役割は? ||入力ベクトルに重み行列を掛けて次のレイヤーの出力を計算。1回の行列の掛け算 = 1レイヤーの線形変換||
Q2. LoRAがSVDと関連する理由は? ||SVDは大きな行列を小さな行列の積に分解。LoRAは重み行列の変化量(ΔW)を低ランク行列2つ(A, B)の積で近似し、パラメータを大幅に削減||
Q3. 逆伝播(Backpropagation)の数学的基礎は? ||連鎖律(Chain Rule)。合成関数の微分を各段階の微分の積に分解。Lossから各パラメータまで勾配を逆方向に伝播||
Q4. Softmax関数の役割と数値安定性のトリックは? ||実数ベクトル(logits)を確率分布に変換(合計=1、すべて正)。トリック:入力から最大値を引く — expのオーバーフロー防止||
Q5. クロスエントロピーが損失関数として優れている理由は? ||正解の確率が1に近づけばloss → 0、0に近づけばloss → ∞。誤った予測に強いペナルティを与え、学習が効率的||
Q6. Diffusion Modelでガウス分布が使われる理由は? ||Forwardプロセスで画像にガウスノイズを段階的に追加。ガウスは数学的に扱いやすく(閉形式解)、中心極限定理により自然なノイズモデル||
Q7. Temperatureが高いとGPT出力のエントロピーはどうなる? ||増加。logitsをTで割るとsoftmax分布が平坦になり(均等分布に近づく)、不確実性が増加 → 多様な出力を生成||
Q8. RLHFにおけるKL Divergenceペナルティの目的は? ||強化学習で更新されたモデル(π_new)が元のモデル(π_ref)から離れすぎないよう制約。報酬ハッキング防止 + 既存能力の保持||
関連シリーズとおすすめ記事
- 自分だけのGPTを作る — nanoGPT — この数学が実際に使われる場所
- GPTシリーズ論文完全分析 — GPT-1からGPT-4まで
- torchvision完全ガイド — CNN/ViT(線形代数の実践)
- torchaudio完全ガイド — フーリエ変換の実践
- セキュリティ完全ガイド — 暗号化(数学のセキュリティ応用)
参考資料
- 3Blue1Brown — Essence of Linear Algebra — 線形代数の直感(必見!)
- 3Blue1Brown — Neural Networks — ニューラルネットワーク可視化
- StatQuest — Machine Learning — 統計/MLのわかりやすい説明
- Mathematics for Machine Learning (book) — 無料教材