1変数関数 $y = f(x)$ の世界では、微分は「$x$ が少し変化したとき $y$ がどれだけ変化するか」を表していました。しかし、現実の多くの現象は複数の変数に依存しています。たとえば、山の標高は経度と緯度の2つの変数で決まりますし、気体の圧力は温度と体積の2つの変数で決まります。機械学習の損失関数は、数千から数百万のパラメータに依存する多変数関数です。
こうした多変数関数に対して、「ある一つの変数だけを動かしたときの変化率」を求めるのが偏微分であり、「全ての変数を同時に動かしたときの線形近似」を与えるのが全微分です。さらに、「任意の方向に動いたときの変化率」を求めるのが方向微分です。
多変数の微分を理解すると、以下のような応用が開けます。
- 機械学習: 勾配降下法は損失関数の勾配ベクトル(偏微分のベクトル)を使ってパラメータを更新する
- 物理学: 温度場の勾配は熱が流れる方向を示し、フーリエの熱伝導法則の基盤となる
- 最適化: ラグランジュの未定乗数法は偏微分の条件から制約付き最適化問題を解く
- 工学: 有限要素法(FEM)は偏微分方程式を離散化して解く数値手法
本記事の内容
- 多変数関数と偏微分の直感的な理解
- 偏微分の数学的定義と計算方法
- 全微分の定義と微分可能性
- 勾配ベクトルと方向微分
- 連鎖律(チェーンルール)
- Pythonによる可視化
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
- 微分の定義と計算方法 — 1変数の微分の基礎
- ベクトルの基本 — ベクトルの内積
多変数関数とは
日常の中の多変数関数
私たちの身の回りには多変数関数があふれています。天気予報を考えてみましょう。ある地点の気温 $T$ は、経度 $x$、緯度 $y$、標高 $z$、時刻 $t$ の4つの変数に依存します。つまり $T = T(x, y, z, t)$ という4変数関数です。
もっと身近な例として、体感温度を考えましょう。体感温度は気温 $T$ と風速 $v$ の2つに大きく依存します。気温が同じでも風が強ければ寒く感じますし、風がなければ暖かく感じます。これは体感温度が $T$ と $v$ の2変数関数であることを意味しています。
数学的に表現すると、$n$ 変数関数とは、$\mathbb{R}^n$ の部分集合 $D$ から $\mathbb{R}$ への写像 $f: D \to \mathbb{R}$ のことです。
$$ z = f(x_1, x_2, \ldots, x_n) $$
2変数関数 $z = f(x, y)$ の場合、そのグラフは3次元空間内の曲面になります。山の地形図のように、$(x, y)$ の各点に高さ $z$ を対応させたものです。
なぜ多変数の微分が必要か
1変数関数の微分 $f'(x) = \lim_{h \to 0} \frac{f(x+h) – f(x)}{h}$ では、$x$ が動く方向は正の方向か負の方向かの1通りしかありません。しかし、2変数関数では $(x, y)$ が動ける方向は無限にあります。$x$ 方向だけ動く、$y$ 方向だけ動く、斜め45度の方向に動く、など様々です。
この「複数の方向に動ける」という事実が、多変数の微分を1変数よりも豊かで複雑なものにしています。偏微分は「特定の1方向だけに動いたときの変化率」を取り出す道具であり、全微分はそれらを統合して「全ての方向への変化率」を一度に記述する道具です。
それでは、最も基本的な偏微分から始めましょう。
偏微分の定義と計算
偏微分の直感
山をハイキングしていると想像してください。あなたが立っている地点から、東に一歩踏み出したときの傾斜と、北に一歩踏み出したときの傾斜は一般に異なります。東に向かうと上り坂でも、北に向かうと下り坂かもしれません。
偏微分は、このような「特定の方向だけに注目した傾斜」を数学的に表します。$f(x, y)$ の $x$ に関する偏微分 $\frac{\partial f}{\partial x}$ は「$y$ を固定して $x$ だけを動かしたときの変化率」であり、$y$ に関する偏微分 $\frac{\partial f}{\partial y}$ は「$x$ を固定して $y$ だけを動かしたときの変化率」です。
数学的定義
2変数関数 $f(x, y)$ の $x$ に関する偏微分は
$$ \begin{equation} \frac{\partial f}{\partial x}(a, b) = \lim_{h \to 0} \frac{f(a + h, b) – f(a, b)}{h} \end{equation} $$
$y$ に関する偏微分は
$$ \begin{equation} \frac{\partial f}{\partial y}(a, b) = \lim_{h \to 0} \frac{f(a, b + h) – f(a, b)}{h} \end{equation} $$
と定義されます。記法として $f_x$、$\partial_x f$、$D_x f$ なども使われます。
この定義から明らかなように、$x$ に関する偏微分を計算するときは $y$ を定数とみなして $x$ の関数として微分すればよく、$y$ に関する偏微分を計算するときは $x$ を定数とみなして $y$ の関数として微分すればよいのです。つまり、偏微分の計算自体は1変数の微分と同じルールで行えます。
計算例
例1: $f(x, y) = x^2 y + 3xy^3 – 2y$ の偏微分を求めます。
$x$ で偏微分($y$ は定数扱い):
$$ \frac{\partial f}{\partial x} = 2xy + 3y^3 $$
$y$ で偏微分($x$ は定数扱い):
$$ \frac{\partial f}{\partial y} = x^2 + 9xy^2 – 2 $$
例2: $f(x, y) = e^{x^2 + y^2}$ の偏微分を求めます。
合成関数の微分法を使います。$u = x^2 + y^2$ として $f = e^u$ とおくと
$$ \frac{\partial f}{\partial x} = e^u \cdot \frac{\partial u}{\partial x} = e^{x^2+y^2} \cdot 2x = 2x e^{x^2+y^2} $$
$$ \frac{\partial f}{\partial y} = e^u \cdot \frac{\partial u}{\partial y} = e^{x^2+y^2} \cdot 2y = 2y e^{x^2+y^2} $$
高階偏微分
偏微分を繰り返し適用することで、高階偏微分が得られます。
$$ \frac{\partial^2 f}{\partial x^2} = \frac{\partial}{\partial x}\left(\frac{\partial f}{\partial x}\right), \quad \frac{\partial^2 f}{\partial y \partial x} = \frac{\partial}{\partial y}\left(\frac{\partial f}{\partial x}\right) $$
ここで重要な結果が、シュワルツの定理(クレローの定理とも呼ばれる)です。
定理: $f$ の2階偏導関数 $f_{xy}$ と $f_{yx}$ がともに連続ならば、偏微分の順序は交換可能である。
$$ \frac{\partial^2 f}{\partial y \partial x} = \frac{\partial^2 f}{\partial x \partial y} $$
この定理は、ヘッセ行列が対称行列であることの根拠となります。実用上、ほとんどの関数で偏微分の順序は入れ替え可能と考えてよいでしょう。
偏微分は「座標軸方向だけの変化率」ですが、関数の全体的な変化を理解するには不十分です。次に、全ての方向への変化を一度に記述する「全微分」の概念を導入しましょう。
全微分と微分可能性
全微分の直感
偏微分が存在するだけでは、関数が「滑らか」であるとは限りません。たとえば、2変数関数
$$ f(x, y) = \begin{cases} \frac{xy}{x^2 + y^2} & (x, y) \neq (0, 0) \\ 0 & (x, y) = (0, 0) \end{cases} $$
は原点で両方の偏微分が存在します($f_x(0,0) = f_y(0,0) = 0$)。しかし、この関数は原点で連続ですらありません($y = x$ に沿って近づくと $f \to 1/2$ ですが、$y = 0$ に沿って近づくと $f \to 0$)。
1変数では「微分可能 → 連続」が自動的に成り立ちましたが、多変数では偏微分が存在しても連続とは限らないのです。これは「座標軸方向だけの情報では、全方向の振る舞いを捉えきれない」ことを意味しています。
「全方向で滑らかに振る舞う」ことを保証するのが全微分可能性(微分可能性)です。
全微分の定義
関数 $f(x, y)$ が点 $(a, b)$ で全微分可能(differentiable)であるとは、次の条件を満たす定数 $A$, $B$ が存在することをいいます。
$$ \begin{equation} f(a + \Delta x, b + \Delta y) = f(a, b) + A \Delta x + B \Delta y + o\left(\sqrt{\Delta x^2 + \Delta y^2}\right) \end{equation} $$
ここで $o(\cdot)$ はランダウの小さい $o$ 記号であり、$\sqrt{\Delta x^2 + \Delta y^2} \to 0$ のとき、$o$ の項を $\sqrt{\Delta x^2 + \Delta y^2}$ で割ったものが $0$ に収束することを意味します。
この条件を満たすとき、必然的に $A = f_x(a,b)$、$B = f_y(a,b)$ となります。
全微分を $df$ と書くと
$$ \begin{equation} df = \frac{\partial f}{\partial x} dx + \frac{\partial f}{\partial y} dy \end{equation} $$
これは、関数値の微小変化 $df$ が、$x$ 方向の変化 $dx$ と $y$ 方向の変化 $dy$ による影響の線形結合であることを表しています。
$n$ 変数関数の場合は
$$ df = \sum_{i=1}^{n} \frac{\partial f}{\partial x_i} dx_i $$
微分可能性の十分条件
実用上、偏導関数が連続($C^1$ 級)であれば全微分可能であることが知られています。
定理: $f_x$ と $f_y$ が点 $(a, b)$ の近傍で存在し、$(a, b)$ で連続ならば、$f$ は $(a, b)$ で全微分可能である。
これは非常に使いやすい判定条件です。多くの実用的な関数(多項式、指数関数、三角関数の合成など)は $C^\infty$ 級(無限回連続微分可能)なので、全微分可能性を心配する必要はほとんどありません。
全微分は関数の「最良の線形近似」を与えますが、具体的にある方向への変化率を知りたい場合はどうすればよいでしょうか。それが次に紹介する方向微分と勾配ベクトルです。
勾配ベクトルと方向微分
勾配ベクトルの定義
偏微分の情報をまとめたベクトルが勾配ベクトル(gradient vector)です。
$$ \begin{equation} \nabla f(x, y) = \left(\frac{\partial f}{\partial x}, \frac{\partial f}{\partial y}\right) = \text{grad}\, f \end{equation} $$
$n$ 変数関数の場合は
$$ \nabla f(\bm{x}) = \left(\frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, \ldots, \frac{\partial f}{\partial x_n}\right) $$
勾配ベクトルは、関数値が最も急速に増加する方向を指します。これは山の地形で「最急勾配方向」に対応します。勾配の大きさ $\|\nabla f\|$ は、その方向での変化率の大きさです。
勾配ベクトルの幾何学的意味
2変数関数 $z = f(x, y)$ の等高線(contour lines)は $f(x, y) = c$($c$ は定数)で定義される曲線です。勾配ベクトルは、等高線に常に直交します。
これは直感的にも理解できます。等高線上では $f$ の値は変わらないので、等高線の接線方向への変化率はゼロです。勾配ベクトルは変化率が最大の方向を指すので、変化率がゼロの方向(等高線の接線)とは垂直になるのです。
この性質は、機械学習の勾配降下法で非常に重要です。損失関数の等高線を想像すると、勾配ベクトルは等高線を横切る方向(最も急に下る方向)を指します。勾配降下法は、この方向にパラメータを更新することで、損失を効率的に減らします。
方向微分の定義
勾配ベクトルを使うと、任意の方向への変化率を簡単に計算できます。単位ベクトル $\bm{u} = (u_1, u_2)$($\|\bm{u}\| = 1$)方向の方向微分は
$$ \begin{equation} D_{\bm{u}} f = \lim_{t \to 0} \frac{f(\bm{a} + t\bm{u}) – f(\bm{a})}{t} = \nabla f \cdot \bm{u} \end{equation} $$
つまり、方向微分は勾配ベクトルと方向ベクトルの内積で計算できます。
この式から、方向微分の最大値は $\|\nabla f\|$($\bm{u}$ が $\nabla f$ と同じ方向のとき)であり、最小値は $-\|\nabla f\|$($\bm{u}$ が $\nabla f$ と逆方向のとき)であることがわかります。$\bm{u}$ が $\nabla f$ と直交するときは $D_{\bm{u}} f = 0$ であり、等高線方向に対応します。
具体例
$f(x, y) = x^2 + 2y^2$ の点 $(1, 1)$ での勾配と方向微分を求めます。
偏微分を計算すると $f_x = 2x$、$f_y = 4y$ なので
$$ \nabla f(1, 1) = (2, 4) $$
勾配ベクトルの大きさは $\|\nabla f\| = \sqrt{4 + 16} = \sqrt{20} = 2\sqrt{5} \approx 4.47$ です。
方向 $\bm{u} = (1/\sqrt{2}, 1/\sqrt{2})$(45度方向)への方向微分は
$$ D_{\bm{u}} f = (2, 4) \cdot \left(\frac{1}{\sqrt{2}}, \frac{1}{\sqrt{2}}\right) = \frac{2}{\sqrt{2}} + \frac{4}{\sqrt{2}} = \frac{6}{\sqrt{2}} = 3\sqrt{2} \approx 4.24 $$
次に、多変数関数の合成関数の微分法(連鎖律)を見てみましょう。
連鎖律(チェーンルール)
多変数の連鎖律
1変数の場合の連鎖律 $(f \circ g)'(x) = f'(g(x)) \cdot g'(x)$ は、多変数に拡張できます。
$z = f(x, y)$ であり、$x = x(t)$, $y = y(t)$ がパラメータ $t$ の関数であるとき
$$ \begin{equation} \frac{dz}{dt} = \frac{\partial f}{\partial x}\frac{dx}{dt} + \frac{\partial f}{\partial y}\frac{dy}{dt} \end{equation} $$
これは全微分 $df = f_x dx + f_y dy$ の両辺を $dt$ で「割った」ものと考えることもできます。
より一般的な場合
$z = f(x, y)$ であり、$x = x(s, t)$, $y = y(s, t)$ が2つのパラメータの関数であるとき
$$ \frac{\partial z}{\partial s} = \frac{\partial f}{\partial x}\frac{\partial x}{\partial s} + \frac{\partial f}{\partial y}\frac{\partial y}{\partial s} $$
$$ \frac{\partial z}{\partial t} = \frac{\partial f}{\partial x}\frac{\partial x}{\partial t} + \frac{\partial f}{\partial y}\frac{\partial y}{\partial t} $$
これを行列の形で書くと
$$ \begin{pmatrix} \frac{\partial z}{\partial s} \\ \frac{\partial z}{\partial t} \end{pmatrix} = \begin{pmatrix} \frac{\partial x}{\partial s} & \frac{\partial y}{\partial s} \\ \frac{\partial x}{\partial t} & \frac{\partial y}{\partial t} \end{pmatrix} \begin{pmatrix} \frac{\partial f}{\partial x} \\ \frac{\partial f}{\partial y} \end{pmatrix} $$
右辺の行列はヤコビ行列の転置であり、連鎖律がヤコビ行列の積として表されることを示しています。この視点は、次の記事「ヤコビ行列」で詳しく扱います。
計算例
$f(x, y) = x^2 + xy$ で、$x = \cos t$, $y = \sin t$ のとき、$\frac{dz}{dt}$ を求めます。
連鎖律を使って
$$ \frac{dz}{dt} = (2x + y)(-\sin t) + x \cdot \cos t $$
$x = \cos t$, $y = \sin t$ を代入すると
$$ \frac{dz}{dt} = (2\cos t + \sin t)(-\sin t) + \cos t \cdot \cos t = -2\sin t\cos t – \sin^2 t + \cos^2 t $$
二倍角の公式を使えば $\frac{dz}{dt} = -\sin 2t + \cos 2t$ と簡潔に書けます。
理論的な道具が揃ったところで、Pythonで偏微分と勾配ベクトルを可視化してみましょう。
Pythonでの実装と可視化
偏微分と勾配ベクトルの可視化
2変数関数の等高線と勾配ベクトル場を描画し、勾配が等高線に直交する様子を確認します。
import numpy as np
import matplotlib.pyplot as plt
# 2変数関数: f(x, y) = x^2 + 2y^2(楕円の等高線を持つ)
def f(x, y):
return x**2 + 2 * y**2
def grad_f(x, y):
return 2 * x, 4 * y # (df/dx, df/dy)
# グリッドの作成
x = np.linspace(-3, 3, 200)
y = np.linspace(-3, 3, 200)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig, axes = plt.subplots(1, 3, figsize=(16, 5))
# (a) 3D曲面
ax = fig.add_subplot(131, projection='3d')
ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8, edgecolor='none')
ax.set_xlabel('x', fontsize=11)
ax.set_ylabel('y', fontsize=11)
ax.set_zlabel('z', fontsize=11)
ax.set_title(r'$f(x,y) = x^2 + 2y^2$', fontsize=13)
ax.view_init(elev=25, azim=135)
axes[0].set_visible(False)
# (b) 等高線 + 勾配ベクトル
ax = axes[1]
contour = ax.contour(X, Y, Z, levels=15, cmap='viridis')
ax.clabel(contour, inline=True, fontsize=8)
# 勾配ベクトル場(間引いて描画)
xq = np.linspace(-2.5, 2.5, 12)
yq = np.linspace(-2.5, 2.5, 12)
Xq, Yq = np.meshgrid(xq, yq)
Gx, Gy = grad_f(Xq, Yq)
# 正規化して見やすくする
magnitude = np.sqrt(Gx**2 + Gy**2)
magnitude = np.maximum(magnitude, 1e-10)
Gx_norm = Gx / magnitude
Gy_norm = Gy / magnitude
ax.quiver(Xq, Yq, Gx_norm, Gy_norm, magnitude, cmap='Reds',
scale=25, width=0.004, alpha=0.8)
ax.set_xlabel('x', fontsize=11)
ax.set_ylabel('y', fontsize=11)
ax.set_title('Contour + Gradient Field', fontsize=13)
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
# (c) 特定点での方向微分
ax = axes[2]
contour = ax.contour(X, Y, Z, levels=15, cmap='viridis', alpha=0.5)
point = np.array([1.0, 1.0])
grad = np.array(grad_f(*point))
# 勾配方向
ax.annotate('', xy=point + 0.5 * grad / np.linalg.norm(grad),
xytext=point,
arrowprops=dict(arrowstyle='->', color='red', lw=2.5))
ax.text(point[0] + 0.6, point[1] + 0.8, r'$\nabla f$', color='red',
fontsize=14, fontweight='bold')
# いくつかの方向の方向微分を表示
angles = np.linspace(0, 2*np.pi, 8, endpoint=False)
for angle in angles:
u = np.array([np.cos(angle), np.sin(angle)])
dir_deriv = np.dot(grad, u)
# 方向微分の大きさで色を変える
color = plt.cm.coolwarm((dir_deriv / np.linalg.norm(grad) + 1) / 2)
ax.annotate('', xy=point + 0.4 * u, xytext=point,
arrowprops=dict(arrowstyle='->', color=color, lw=1.5))
ax.plot(*point, 'ko', markersize=8)
ax.set_xlabel('x', fontsize=11)
ax.set_ylabel('y', fontsize=11)
ax.set_title('Directional Derivatives at (1,1)', fontsize=13)
ax.set_xlim(-0.5, 3)
ax.set_ylim(-0.5, 3)
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('multivariable_gradient.png', dpi=150, bbox_inches='tight')
plt.show()
このグラフから、多変数の微分に関する重要な性質が視覚的に確認できます。
-
中央図(等高線と勾配ベクトル場): 赤い矢印(勾配ベクトル)が、等高線に対して常に直交していることが確認できます。関数値が大きい領域(等高線の間隔が密な場所)では勾配ベクトルの大きさ(色の濃さ)も大きくなっており、「変化が急な場所ほど勾配が大きい」ことが視覚的にわかります。
-
右図(方向微分): 点 $(1,1)$ から8つの方向に矢印を出し、色で方向微分の値を表しています。赤い方向は勾配と同じ方向(方向微分が最大)、青い方向は勾配と逆方向(方向微分が最小=負の最大値)です。勾配に直交する方向(等高線方向)では方向微分がほぼゼロになります。
偏微分の数値計算
偏微分を数値的に計算し、解析解と比較します。
import numpy as np
import matplotlib.pyplot as plt
# 数値偏微分(中心差分)
def numerical_partial_x(f, x, y, h=1e-7):
return (f(x + h, y) - f(x - h, y)) / (2 * h)
def numerical_partial_y(f, x, y, h=1e-7):
return (f(x, y + h) - f(x, y - h)) / (2 * h)
# テスト関数
def g(x, y):
return np.sin(x) * np.exp(y)
# 解析的な偏微分
def g_x_exact(x, y):
return np.cos(x) * np.exp(y)
def g_y_exact(x, y):
return np.sin(x) * np.exp(y)
# 比較
test_points = [(1.0, 0.5), (0.5, 1.0), (2.0, -1.0), (np.pi/4, 0.0)]
print("偏微分の比較: f(x,y) = sin(x) * exp(y)")
print("-" * 65)
print(f"{'Point':>12s} {'Exact df/dx':>12s} {'Numerical':>12s} {'Error':>12s}")
print("-" * 65)
for x0, y0 in test_points:
exact = g_x_exact(x0, y0)
numerical = numerical_partial_x(g, x0, y0)
print(f"({x0:.2f},{y0:.2f}) {exact:12.8f} {numerical:12.8f} {abs(exact-numerical):12.2e}")
# 刻み幅と誤差の関係
h_values = np.logspace(-1, -14, 50)
errors_forward = []
errors_central = []
x0, y0 = 1.0, 0.5
exact_val = g_x_exact(x0, y0)
for h in h_values:
# 前進差分
fwd = (g(x0 + h, y0) - g(x0, y0)) / h
errors_forward.append(abs(fwd - exact_val))
# 中心差分
ctr = (g(x0 + h, y0) - g(x0 - h, y0)) / (2 * h)
errors_central.append(abs(ctr - exact_val))
fig, ax = plt.subplots(figsize=(10, 6))
ax.loglog(h_values, errors_forward, 'r-', linewidth=2, label='Forward difference')
ax.loglog(h_values, errors_central, 'b-', linewidth=2, label='Central difference')
ax.loglog(h_values, h_values, 'r--', alpha=0.3, label=r'$O(h)$')
ax.loglog(h_values, h_values**2, 'b--', alpha=0.3, label=r'$O(h^2)$')
ax.set_xlabel('Step size h', fontsize=12)
ax.set_ylabel('Error', fontsize=12)
ax.set_title('Numerical Differentiation Error vs Step Size', fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3, which='both')
ax.set_xlim(1e-14, 1e-1)
ax.set_ylim(1e-14, 1)
plt.tight_layout()
plt.savefig('numerical_partial.png', dpi=150, bbox_inches='tight')
plt.show()
このグラフから、数値偏微分の精度について重要な知見が得られます。前進差分(赤)は $O(h)$ の精度であり、中心差分(青)は $O(h^2)$ の精度です。しかし、$h$ を小さくしすぎると丸め誤差の影響で精度が劣化します。前進差分は $h \approx 10^{-8}$ で、中心差分は $h \approx 10^{-5}$ で最良の精度を達成しています。実用的には中心差分で $h = 10^{-5}$ から $10^{-7}$ 程度を使うのが良いでしょう。
全微分による線形近似の可視化
全微分が関数の「接平面」を与えることを可視化します。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def f(x, y):
return np.sin(x) * np.cos(y)
# 接平面: z = f(a,b) + fx(a,b)(x-a) + fy(a,b)(y-b)
a, b = 1.0, 0.5
f_ab = f(a, b)
fx = np.cos(a) * np.cos(b) # df/dx at (a,b)
fy = -np.sin(a) * np.sin(b) # df/dy at (a,b)
x = np.linspace(-1, 3, 100)
y = np.linspace(-1.5, 2.5, 100)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
Z_tangent = f_ab + fx * (X - a) + fy * (Y - b)
fig = plt.figure(figsize=(12, 5))
ax1 = fig.add_subplot(121, projection='3d')
ax1.plot_surface(X, Y, Z, cmap='viridis', alpha=0.6, edgecolor='none')
ax1.plot_surface(X, Y, Z_tangent, color='red', alpha=0.3, edgecolor='none')
ax1.scatter([a], [b], [f_ab], color='black', s=50, zorder=10)
ax1.set_xlabel('x', fontsize=11)
ax1.set_ylabel('y', fontsize=11)
ax1.set_zlabel('z', fontsize=11)
ax1.set_title('Function and Tangent Plane', fontsize=13)
ax1.view_init(elev=25, azim=135)
# 近似誤差のヒートマップ
ax2 = fig.add_subplot(122)
error = np.abs(Z - Z_tangent)
im = ax2.pcolormesh(X, Y, error, cmap='hot_r', shading='auto')
ax2.plot(a, b, 'k*', markersize=15)
plt.colorbar(im, ax=ax2, label='|f - tangent plane|')
ax2.set_xlabel('x', fontsize=11)
ax2.set_ylabel('y', fontsize=11)
ax2.set_title('Linear Approximation Error', fontsize=13)
ax2.set_aspect('equal')
plt.tight_layout()
plt.savefig('total_differential.png', dpi=150, bbox_inches='tight')
plt.show()
このグラフから、全微分(接平面)による近似の性質がわかります。左図では赤い平面(接平面)が曲面に点 $(1, 0.5)$ で接している様子が確認できます。右図の誤差のヒートマップでは、接点の周りでは誤差がほぼゼロ(暗い色)であり、接点から離れるほど誤差が大きくなる(明るい色)ことがわかります。これは全微分が局所的な線形近似であることを反映しています。
まとめ
本記事では、多変数関数の微分の基礎について解説しました。
- 偏微分は、他の変数を固定して一つの変数だけで微分する操作であり、計算は1変数の微分と同じルールで行える
- 全微分は、全ての方向への変化を線形近似として一度に記述する概念であり、偏微分が存在するだけでは全微分可能とは限らない
- 勾配ベクトル $\nabla f$ は偏微分をまとめたベクトルであり、関数値が最も急速に増加する方向を指す。等高線に常に直交する
- 方向微分 $D_{\bm{u}} f = \nabla f \cdot \bm{u}$ は、勾配ベクトルと方向の内積で計算できる
- 連鎖律は多変数にも拡張でき、ヤコビ行列の積として表現される
次のステップとして、以下の記事も参考にしてください。
- ヤコビ行列とヤコビアンの意味を理解する — 連鎖律のヤコビ行列による表現
- ヘッセ行列と多変数の極値問題 — 2階偏微分の行列と極値判定
- ラグランジュの未定乗数法を完全理解する — 偏微分を使った制約付き最適化