偏微分は1つの変数だけを変化させたときの変化率でした。しかし、実際の問題では複数の変数が同時に変化します。全微分は、すべての変数が微小変化したときの関数の変化量を表す概念であり、偏微分を統合したものです。
さらに、合成関数を微分する際の連鎖律(チェインルール)は、多変数関数の場合にも自然に拡張されます。これは物理学での座標変換や、機械学習での誤差逆伝播法など、至るところで使われる重要な道具です。
本記事の内容
- 全微分の定義と直感的な意味
- 多変数の連鎖律
- 陰関数の微分
- 全微分の近似への応用
- Pythonでの可視化
前提知識
全微分の定義
1変数の場合の復習
1変数関数 $y = f(x)$ の微分は:
$$ dy = f'(x)\,dx $$
これは「$x$ が $dx$ だけ変化したとき、$y$ は近似的に $f'(x)\,dx$ だけ変化する」ことを意味します。
2変数関数の全微分
2変数関数 $z = f(x, y)$ において、$x$ が $dx$、$y$ が $dy$ だけ変化したとき、$z$ の変化量を考えます。
$f$ が点 $(x, y)$ で全微分可能であるとき、全微分 $df$ は:
$$ \boxed{df = \frac{\partial f}{\partial x}dx + \frac{\partial f}{\partial y}dy} $$
すなわち、$x$ 方向の偏微分による寄与と $y$ 方向の偏微分による寄与の和です。
全微分可能の意味
関数 $f(x, y)$ が点 $(a, b)$ で全微分可能とは、以下の条件を満たすことです:
$$ \Delta f = f(a + \Delta x, b + \Delta y) – f(a, b) = f_x(a,b)\Delta x + f_y(a,b)\Delta y + \epsilon_1 \Delta x + \epsilon_2 \Delta y $$
ここで $\epsilon_1, \epsilon_2 \to 0$($\Delta x, \Delta y \to 0$ のとき)です。
つまり、関数の変化量が偏微分を用いた1次式でよく近似できることを意味します。
偏微分が存在するだけでは全微分可能とは限りませんが、偏微分が連続($C^1$ 級)ならば全微分可能であることが保証されます。
$n$ 変数への一般化
$f(x_1, x_2, \dots, x_n)$ の全微分は:
$$ \boxed{df = \sum_{k=1}^{n}\frac{\partial f}{\partial x_k}dx_k = \frac{\partial f}{\partial x_1}dx_1 + \frac{\partial f}{\partial x_2}dx_2 + \cdots + \frac{\partial f}{\partial x_n}dx_n} $$
全微分の幾何学的意味
$z = f(x, y)$ の全微分は、接平面上での $z$ の変化量を表します。
接平面の方程式は:
$$ z – z_0 = f_x(x_0, y_0)(x – x_0) + f_y(x_0, y_0)(y – y_0) $$
$dx = x – x_0$, $dy = y – y_0$ とすれば、接平面上の $z$ の変化量が $df = f_x\,dx + f_y\,dy$ です。
つまり、全微分は「曲面上の変化量を接平面上の変化量で近似する」ことに他なりません。
多変数の連鎖律
基本形
$z = f(x, y)$ において、$x = x(t)$, $y = y(t)$ がパラメータ $t$ の関数であるとき、合成関数 $z(t) = f(x(t), y(t))$ の $t$ に関する導関数は:
$$ \boxed{\frac{dz}{dt} = \frac{\partial f}{\partial x}\frac{dx}{dt} + \frac{\partial f}{\partial y}\frac{dy}{dt}} $$
導出
全微分 $df = f_x\,dx + f_y\,dy$ の両辺を $dt$ で割ると:
$$ \frac{df}{dt} = f_x \frac{dx}{dt} + f_y \frac{dy}{dt} $$
これが連鎖律です。
2変数パラメータの場合
$z = f(x, y)$ で $x = x(s, t)$, $y = y(s, t)$ のとき:
$$ \boxed{\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}} $$
$$ \boxed{\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}} $$
具体例:極座標変換
$f(x, y)$ を極座標 $x = r\cos\theta$, $y = r\sin\theta$ で書き直すとき、連鎖律を適用します。
$$ \frac{\partial f}{\partial r} = \frac{\partial f}{\partial x}\frac{\partial x}{\partial r} + \frac{\partial f}{\partial y}\frac{\partial y}{\partial r} = \frac{\partial f}{\partial x}\cos\theta + \frac{\partial f}{\partial y}\sin\theta $$
$$ \frac{\partial f}{\partial \theta} = \frac{\partial f}{\partial x}\frac{\partial x}{\partial \theta} + \frac{\partial f}{\partial y}\frac{\partial y}{\partial \theta} = -\frac{\partial f}{\partial x}r\sin\theta + \frac{\partial f}{\partial y}r\cos\theta $$
連鎖律の樹形図
多変数の連鎖律は樹形図(ツリーダイアグラム)で理解すると間違いにくくなります。
$z$ が $x, y$ を通じて $s, t$ に依存する構造を、上から下に描きます:
z
/ \
x y
/ \ / \
s t s t
$z$ から $s$ への「道」は2本あります: 1. $z \to x \to s$:寄与は $\frac{\partial z}{\partial x} \cdot \frac{\partial x}{\partial s}$ 2. $z \to y \to s$:寄与は $\frac{\partial z}{\partial y} \cdot \frac{\partial y}{\partial s}$
これらの和が $\partial z / \partial s$ です。
陰関数の微分
陰関数定理の応用
$F(x, y) = 0$ で定まる陰関数 $y = y(x)$ の導関数を全微分で求めます。
$F(x, y) = 0$ の全微分をとると:
$$ dF = \frac{\partial F}{\partial x}dx + \frac{\partial F}{\partial y}dy = 0 $$
$$ \boxed{\frac{dy}{dx} = -\frac{\partial F / \partial x}{\partial F / \partial y} = -\frac{F_x}{F_y}} $$
(ただし $F_y \neq 0$)
具体例
例1: 円 $x^2 + y^2 = r^2$
$F(x, y) = x^2 + y^2 – r^2 = 0$ とおくと:
$$ F_x = 2x, \quad F_y = 2y $$
$$ \frac{dy}{dx} = -\frac{2x}{2y} = -\frac{x}{y} $$
例2: $e^{xy} + x + y = 1$
$F(x, y) = e^{xy} + x + y – 1 = 0$ とおくと:
$$ F_x = ye^{xy} + 1, \quad F_y = xe^{xy} + 1 $$
$$ \frac{dy}{dx} = -\frac{ye^{xy} + 1}{xe^{xy} + 1} $$
多変数の陰関数
$F(x, y, z) = 0$ で $z = z(x, y)$ が定まるとき:
$$ \frac{\partial z}{\partial x} = -\frac{F_x}{F_z}, \quad \frac{\partial z}{\partial y} = -\frac{F_y}{F_z} $$
全微分の近似への応用
近似公式
全微分は、微小な変化に対する線形近似を与えます:
$$ \boxed{f(x + \Delta x, y + \Delta y) \approx f(x, y) + \frac{\partial f}{\partial x}\Delta x + \frac{\partial f}{\partial y}\Delta y} $$
これは、曲面の変化を接平面で近似することと同じです。
具体例:誤差の伝播
物理量 $Q = Q(a, b, c)$ が複数の測定値 $a, b, c$ から計算される場合、測定誤差 $\delta a, \delta b, \delta c$ が $Q$ に与える影響(誤差伝播)は全微分で評価できます:
$$ \delta Q \approx \left|\frac{\partial Q}{\partial a}\right|\delta a + \left|\frac{\partial Q}{\partial b}\right|\delta b + \left|\frac{\partial Q}{\partial c}\right|\delta c $$
より正確には、誤差が独立なとき、二乗和の平方根で評価します:
$$ \delta Q \approx \sqrt{\left(\frac{\partial Q}{\partial a}\delta a\right)^2 + \left(\frac{\partial Q}{\partial b}\delta b\right)^2 + \left(\frac{\partial Q}{\partial c}\delta c\right)^2} $$
例: 直方体の体積 $V = abc$
$$ \frac{\partial V}{\partial a} = bc, \quad \frac{\partial V}{\partial b} = ac, \quad \frac{\partial V}{\partial c} = ab $$
$$ \frac{\delta V}{V} \approx \sqrt{\left(\frac{\delta a}{a}\right)^2 + \left(\frac{\delta b}{b}\right)^2 + \left(\frac{\delta c}{c}\right)^2} $$
相対誤差は各変数の相対誤差の二乗和の平方根となります。
Pythonでの可視化
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# ============================
# 全微分と連鎖律の可視化
# ============================
fig = plt.figure(figsize=(18, 6))
# === (1) 全微分による近似 ===
ax1 = fig.add_subplot(131, projection='3d')
def f(x, y):
return np.sin(x) * np.cos(y)
x = np.linspace(-2, 2, 100)
y = np.linspace(-2, 2, 100)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
# 曲面
ax1.plot_surface(X, Y, Z, alpha=0.4, cmap='viridis')
# 接平面(全微分による近似)
x0, y0 = 0.5, 0.3
z0 = f(x0, y0)
fx = np.cos(x0) * np.cos(y0) # ∂f/∂x
fy = -np.sin(x0) * np.sin(y0) # ∂f/∂y
x_tp = np.linspace(x0-1.2, x0+1.2, 20)
y_tp = np.linspace(y0-1.2, y0+1.2, 20)
X_tp, Y_tp = np.meshgrid(x_tp, y_tp)
Z_tp = z0 + fx*(X_tp - x0) + fy*(Y_tp - y0)
ax1.plot_surface(X_tp, Y_tp, Z_tp, alpha=0.5, color='orange')
ax1.scatter([x0], [y0], [z0], color='red', s=100, zorder=5)
ax1.set_xlabel('$x$'); ax1.set_ylabel('$y$'); ax1.set_zlabel('$z$')
ax1.set_title('Total differential\nas tangent plane', fontsize=12)
ax1.view_init(elev=25, azim=-50)
# === (2) 近似誤差の可視化 ===
ax2 = fig.add_subplot(132)
# f(x,y) = sin(x)*cos(y) に対して (x0,y0) = (0.5, 0.3) からの距離と近似誤差
n_pts = 1000
np.random.seed(42)
dx_arr = np.random.uniform(-1.5, 1.5, n_pts)
dy_arr = np.random.uniform(-1.5, 1.5, n_pts)
dist = np.sqrt(dx_arr**2 + dy_arr**2)
exact_change = f(x0 + dx_arr, y0 + dy_arr) - z0
approx_change = fx * dx_arr + fy * dy_arr
error = np.abs(exact_change - approx_change)
scatter = ax2.scatter(dist, error, c=dist, cmap='plasma', s=5, alpha=0.6)
plt.colorbar(scatter, ax=ax2, label='Distance')
ax2.set_xlabel('Distance from $(x_0, y_0)$', fontsize=11)
ax2.set_ylabel('Approximation error $|\\Delta f - df|$', fontsize=11)
ax2.set_title('Total differential\napproximation error', fontsize=12)
ax2.grid(True, alpha=0.3)
# === (3) 連鎖律の数値検証 ===
ax3 = fig.add_subplot(133)
# z = f(x,y) = x^2*y, x = cos(t), y = sin(t)
t = np.linspace(0, 2*np.pi, 500)
x_t = np.cos(t)
y_t = np.sin(t)
z_t = x_t**2 * y_t # z(t) = cos^2(t)*sin(t)
# 解析的な dz/dt
# dz/dt = ∂f/∂x * dx/dt + ∂f/∂y * dy/dt
# = 2xy * (-sin(t)) + x^2 * cos(t)
dz_dt_chain = 2*x_t*y_t*(-np.sin(t)) + x_t**2 * np.cos(t)
# 直接微分 d/dt[cos^2(t)*sin(t)]
# = -2cos(t)sin(t)*sin(t) + cos^2(t)*cos(t)
# = cos(t)(cos^2(t) - 2sin^2(t))
dz_dt_direct = np.cos(t) * (np.cos(t)**2 - 2*np.sin(t)**2)
# 数値微分
h = 1e-7
z_t_plus = np.cos(t+h)**2 * np.sin(t+h)
dz_dt_num = (z_t_plus - z_t) / h
ax3.plot(t, dz_dt_chain, 'b-', lw=2, label='Chain rule (analytical)')
ax3.plot(t, dz_dt_num, 'r--', lw=2, label='Numerical $dz/dt$')
ax3.plot(t, dz_dt_direct, 'g:', lw=3, label='Direct differentiation')
ax3.set_xlabel('$t$', fontsize=12)
ax3.set_ylabel('$dz/dt$', fontsize=12)
ax3.set_title('Chain rule verification\n'
'$z = x^2 y$, $x = \\cos t$, $y = \\sin t$', fontsize=12)
ax3.legend(fontsize=9)
ax3.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('total_differential_chain_rule.png', dpi=150, bbox_inches='tight')
plt.show()
# === (4) 誤差伝播の可視化 ===
fig2, axes2 = plt.subplots(1, 2, figsize=(14, 6))
# 直方体の体積 V = a*b*c の誤差伝播
a0, b0, c0 = 5.0, 3.0, 2.0
V0 = a0 * b0 * c0
# 相対誤差のシミュレーション
N_samples = 10000
np.random.seed(0)
relative_errors = [0.01, 0.03, 0.05, 0.10]
colors = ['blue', 'green', 'orange', 'red']
for rel_err, color in zip(relative_errors, colors):
da = np.random.normal(0, a0*rel_err, N_samples)
db = np.random.normal(0, b0*rel_err, N_samples)
dc = np.random.normal(0, c0*rel_err, N_samples)
# 真の体積変化
V_actual = (a0+da) * (b0+db) * (c0+dc)
# 全微分近似
V_approx = V0 + b0*c0*da + a0*c0*db + a0*b0*dc
axes2[0].hist(V_actual, bins=50, alpha=0.5, color=color, density=True,
label=f'{int(rel_err*100)}% error')
axes2[0].axvline(V0, color='k', ls='--', lw=2, label=f'True $V_0 = {V0}$')
axes2[0].set_xlabel('Volume $V$', fontsize=12)
axes2[0].set_ylabel('Density', fontsize=12)
axes2[0].set_title('Volume distribution\nunder measurement errors', fontsize=12)
axes2[0].legend(fontsize=9)
axes2[0].grid(True, alpha=0.3)
# 全微分近似 vs 実際の誤差
rel_err = 0.05
da = np.random.normal(0, a0*rel_err, N_samples)
db = np.random.normal(0, b0*rel_err, N_samples)
dc = np.random.normal(0, c0*rel_err, N_samples)
dV_actual = (a0+da)*(b0+db)*(c0+dc) - V0
dV_approx = b0*c0*da + a0*c0*db + a0*b0*dc
axes2[1].scatter(dV_approx, dV_actual, s=2, alpha=0.3, color='blue')
lim = max(abs(dV_actual.max()), abs(dV_actual.min())) * 1.1
axes2[1].plot([-lim, lim], [-lim, lim], 'r--', lw=2, label='Perfect approx.')
axes2[1].set_xlabel('$\\Delta V$ (total differential approx.)', fontsize=11)
axes2[1].set_ylabel('$\\Delta V$ (actual)', fontsize=11)
axes2[1].set_title(f'Total differential approximation\n({int(rel_err*100)}% measurement error)', fontsize=12)
axes2[1].legend(fontsize=10)
axes2[1].set_aspect('equal')
axes2[1].grid(True, alpha=0.3)
axes2[1].set_xlim(-lim, lim)
axes2[1].set_ylim(-lim, lim)
plt.tight_layout()
plt.savefig('error_propagation.png', dpi=150, bbox_inches='tight')
plt.show()
上段左の図は、$z = \sin x \cos y$ の曲面と接平面を3Dで描いたもので、全微分が接平面上の変化量に対応することを示しています。中央の図は、接点からの距離と全微分近似の誤差の関係を散布図で示しており、距離が大きいほど近似誤差が増大することが確認できます。右の図は、合成関数 $z = x^2 y$($x = \cos t$, $y = \sin t$)の連鎖律による微分が、数値微分および直接微分と一致することを検証しています。
下段の図は、直方体の体積 $V = abc$ の誤差伝播を示しています。左の図は測定誤差の大きさごとの体積分布、右の図は全微分による近似と実際の変化量の比較です。測定誤差が小さいうちは全微分近似が非常に良い精度を持つことがわかります。
まとめ
本記事では、全微分と多変数の連鎖律について解説しました。
- 全微分 $df = f_x\,dx + f_y\,dy$ は、すべての変数が変化したときの関数の変化量
- 幾何学的には接平面上の変化量に対応する
- 連鎖律: $dz/dt = (\partial f/\partial x)(dx/dt) + (\partial f/\partial y)(dy/dt)$ — 樹形図で理解すると間違いにくい
- 陰関数の微分: $F(x,y) = 0$ のとき $dy/dx = -F_x/F_y$
- 誤差伝播: 全微分を使って測定誤差が計算結果に与える影響を評価できる
次のステップとして、以下の記事も参考にしてください。