偏微分 -- 多変数関数を個別に微分
これまでの微分は一変数関数 f(x) を対象としていた。ニューラルネットワークには数百万ものパラメータがあり、各パラメータについて微分する必要がある。
偏微分 = 多変数関数において、1つの変数だけを微分し、残りは定数とみなす。
概念の解説
これまで我々は一変数関数 f(x) の微分のみを扱ってきた。しかし現実世界では、物事の結果は通常、複数の要因によって共同で決まる。
例えば、住宅価格は面積・立地・階数・築年数などの複数の要因に依存する。「面積が1平方メートル増えたら、住宅価格はいくら上がるか」を知りたい場合、他の要因を固定する必要がある。
これが偏微分の核となる考え方である:一度に1つの変数だけを変え、その結果への影響を観察し、残りの変数は一時的に固定する。
\( f(x, y) = x^2 + xy + y^2 \) について:
- x について偏微分する(y を定数とみなし、y² は定数なので微分すると 0、xy では y を定数とみなし、x の微分は 1):\( \frac{\partial f}{\partial x} = 2x + y + 0 \)
- y について偏微分する(x を定数とみなす、同様に):\( \frac{\partial f}{\partial y} = 0 + x + 2y \)
記号 \( \partial \)(「ラウンドディー」または「パーシャル」と読む)は偏微分を表し、通常の微分の d と区別する。
二階偏微分
偏微分をさらに偏微分すると、二階偏微分が得られる:
- \( \frac{\partial^2 f}{\partial x^2} \):x について偏微分した後、さらに x について偏微分する(x 方向の曲率を測る)
- \( \frac{\partial^2 f}{\partial x \partial y} \):まず x について偏微分し、次に y について偏微分する(交差偏微分、2つの変数の交互作用を測る)
ニューラルネットワーク訓練の本質:損失関数を各パラメータについて偏微分し、負の勾配方向に更新する。
100万パラメータのモデルでは、勾配は100万个の偏微分値からなるベクトルである。
身近な例
鍋いっぱいのスープの味
スープの味は塩・醤油・酢などの複数の調味料に依存する。「塩をスプーン1杯多く入れたら、味はどれだけ変わるか」知りたいとする。
他の調味料の量を固定し、塩の影響だけを見る——これが偏微分の考え方である:一度に1つの変数だけを変える。
数学的定義
\[ \frac{\partial f}{\partial x} = \lim_{h \to 0} \frac{f(x+h, y) - f(x, y)}{h} \]y はそのままに、x だけを変化させる。
Python で実際に試す
実例
x, y = sp.symbols('x y')
f = x**2 + x*y + y**2
print(f"f(x,y) = {f}")
print(f"∂f/∂x = {sp.diff(f, x)}") # 2x + y
print(f"∂f/∂y = {sp.diff(f, y)}") # x + 2y
# 二階偏微分
print(f"∂²f/∂x² = {sp.diff(f, x, 2)}") # 2
print(f"∂²f/∂x∂y = {sp.diff(f, x, y)}") # 1
# 線形モデルの損失のパラメータに対する偏微分
w, b, xi, yi = sp.symbols('w b x_i y_i')
loss = (w*xi + b - yi)**2
print(f"\nloss=(w·xi+b-yi)^2")
print(f"∂L/∂w = {sp.diff(loss, w)}")
print(f"∂L/∂b = {sp.diff(loss, b)}")
出力は:
f(x,y) = x**2 + x*y + y**2 ∂f/∂x = 2*x + y ∂f/∂y = x + 2*y ∂²f/∂x² = 2 ∂²f/∂x∂y = 1 loss=(w·xi+b-yi)^2 ∂L/∂w = 2*x_i*(b + w*x_i - y_i) ∂L/∂b = 2*b + 2*w*x_i - 2*y_i
AIでの応用シーン
ニューラルネットワーク訓練 = 百万回の偏微分計算
100万パラメータのモデルでは、損失は100万个の変数に関する多変数関数である。各トレーニングラウンドで、自動微分エンジンは各パラメータについて偏微分し、100万个の偏微分値を連結して勾配ベクトルを作り、負の勾配方向にすべてのパラメータを更新する。
誤差逆伝播における局所偏微分
計算グラフの各ノードは局所偏微分を計算する必要がある:加算ノード \( \partial/\partial x = 1 \)(勾配はそのまま伝播)、乗算ノード \( \partial(xy)/\partial x = y \)(勾配に相手の値を掛けて伝播)。これらの局所偏微分を計算グラフに沿って連鎖のに掛け合わせることで、最終のなパラメータ勾配が得られる。
パラメータを凍結する転移学習
転移学習ではしばしば事前学習済み層を「凍結」する——これらの層のパラメータは偏微分を計算せず、更新もしない。PyTorch で requires_grad=False を設定すると、対応するパラメータの偏微分計算がスキップされ、GPUメモリと計算量を大幅に節約できる。
その他の拡張