ラグランジュの未定乗数法を分かりやすく解説して実装する

機械学習や物理学の最適化問題では、ある関数を最大化・最小化したいが、同時に制約条件を満たさなければならない場面が頻繁に登場します。このような制約付き最適化問題を解くための古典的かつ強力な手法が、ラグランジュの未定乗数法です。

本記事では、ラグランジュの未定乗数法について、幾何学的な直感から数学的な定式化、そしてPythonでの実装までを丁寧に解説します。

本記事の内容

  • ラグランジュの未定乗数法の直感的な理解
  • 数学的な定式化と導出
  • 複数の制約条件への拡張
  • Pythonでの具体的な実装と可視化

ラグランジュの未定乗数法とは

ラグランジュの未定乗数法とは、等式制約付きの最適化問題を解く手法です。

大雑把に言うと、「制約条件がある状況で関数の極値を見つけたいとき、ラグランジュ乗数という補助変数を導入して、制約なしの問題に帰着させる」テクニックです。

問題設定

目的関数 $f(\bm{x})$ を制約条件 $g(\bm{x}) = 0$ のもとで最適化する問題を考えます。

$$ \begin{align} \text{maximize (or minimize)} \quad & f(\bm{x}) \\ \text{subject to} \quad & g(\bm{x}) = 0 \end{align} $$

ここで、$\bm{x} = (x_1, x_2, \dots, x_n)^\top \in \mathbb{R}^n$ です。

幾何学的な直感

ラグランジュの未定乗数法がなぜ機能するのか、2変数の場合で幾何学的に理解しましょう。

$f(x_1, x_2)$ の等高線($f = c$ となる曲線)と、制約曲線 $g(x_1, x_2) = 0$ を同じ平面上に描くことを考えます。

制約条件のもとでの $f$ の極値は、$f$ の等高線が制約曲線に接する点で実現されます。なぜなら、等高線と制約曲線が交差している点では、制約曲線に沿って移動することで $f$ の値を増加(または減少)できるからです。

等高線が制約曲線に接するとき、両者の法線ベクトルは平行です。$f$ の等高線の法線ベクトルは $\nabla f$、制約曲線 $g = 0$ の法線ベクトルは $\nabla g$ ですから、接する条件は次のように書けます。

$$ \nabla f = \lambda \nabla g $$

ここで、$\lambda$ はスカラー定数(ラグランジュ乗数)です。

数学的な定式化

ラグランジュ関数

ラグランジュ関数(ラグランジアン)$L$ を次のように定義します。

$$ L(\bm{x}, \lambda) = f(\bm{x}) – \lambda g(\bm{x}) $$

ここで、$\lambda$ をラグランジュ乗数(未定乗数)と呼びます。

停留条件の導出

$L$ の停留点(偏微分が全てゼロになる点)を求めます。

$\bm{x}$ に関する偏微分をゼロとおくと、

$$ \frac{\partial L}{\partial \bm{x}} = \nabla f(\bm{x}) – \lambda \nabla g(\bm{x}) = \bm{0} $$

これは $\nabla f = \lambda \nabla g$ と同値であり、幾何学的な議論と一致します。

$\lambda$ に関する偏微分をゼロとおくと、

$$ \frac{\partial L}{\partial \lambda} = -g(\bm{x}) = 0 $$

これは制約条件そのものです。

したがって、ラグランジュ関数の停留条件は以下の連立方程式になります。

$$ \begin{cases} \nabla f(\bm{x}) = \lambda \nabla g(\bm{x}) \\ g(\bm{x}) = 0 \end{cases} $$

これは $n + 1$ 個の未知数($x_1, \dots, x_n, \lambda$)に対して $n + 1$ 本の方程式であり、一般的に解くことができます。

具体例

$f(x, y) = x + y$ を制約条件 $g(x, y) = x^2 + y^2 – 1 = 0$ のもとで最大化する問題を解いてみましょう。

ラグランジュ関数は次のようになります。

$$ L(x, y, \lambda) = x + y – \lambda(x^2 + y^2 – 1) $$

停留条件を求めます。

$$ \begin{align} \frac{\partial L}{\partial x} &= 1 – 2\lambda x = 0 \quad \Rightarrow \quad x = \frac{1}{2\lambda} \\ \frac{\partial L}{\partial y} &= 1 – 2\lambda y = 0 \quad \Rightarrow \quad y = \frac{1}{2\lambda} \\ \frac{\partial L}{\partial \lambda} &= -(x^2 + y^2 – 1) = 0 \end{align} $$

1つ目と2つ目の式から $x = y$ がわかります。これを制約条件に代入すると、

$$ 2x^2 = 1 \quad \Rightarrow \quad x = \pm \frac{1}{\sqrt{2}} $$

したがって、最大値は $x = y = \frac{1}{\sqrt{2}}$ のとき $f = \sqrt{2}$、最小値は $x = y = -\frac{1}{\sqrt{2}}$ のとき $f = -\sqrt{2}$ です。

複数の制約条件への拡張

制約条件が複数ある場合にも、ラグランジュの未定乗数法は自然に拡張できます。

$$ \begin{align} \text{maximize} \quad & f(\bm{x}) \\ \text{subject to} \quad & g_1(\bm{x}) = 0, \quad g_2(\bm{x}) = 0, \quad \dots, \quad g_k(\bm{x}) = 0 \end{align} $$

この場合、ラグランジュ関数は制約の数だけ乗数を導入して、

$$ L(\bm{x}, \lambda_1, \dots, \lambda_k) = f(\bm{x}) – \sum_{i=1}^{k} \lambda_i g_i(\bm{x}) $$

と定義します。停留条件は、

$$ \nabla f(\bm{x}) = \sum_{i=1}^{k} \lambda_i \nabla g_i(\bm{x}), \quad g_i(\bm{x}) = 0 \quad (i = 1, \dots, k) $$

となります。

Pythonでの実装

先ほどの具体例をPythonで解き、等高線と制約曲線を可視化します。

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import fsolve

# 目的関数 f(x, y) = x + y
def f(x, y):
    return x + y

# ラグランジュ条件の連立方程式
def lagrange_equations(vars):
    x, y, lam = vars
    # dL/dx = 1 - 2*lam*x = 0
    eq1 = 1 - 2 * lam * x
    # dL/dy = 1 - 2*lam*y = 0
    eq2 = 1 - 2 * lam * y
    # 制約条件: x^2 + y^2 - 1 = 0
    eq3 = x**2 + y**2 - 1
    return [eq1, eq2, eq3]

# 初期値を変えて2つの停留点を求める
sol_max = fsolve(lagrange_equations, [1, 1, 1])
sol_min = fsolve(lagrange_equations, [-1, -1, -1])

print(f"最大点: x={sol_max[0]:.4f}, y={sol_max[1]:.4f}, lambda={sol_max[2]:.4f}")
print(f"最大値: f={f(sol_max[0], sol_max[1]):.4f}")
print(f"最小点: x={sol_min[0]:.4f}, y={sol_min[1]:.4f}, lambda={sol_min[2]:.4f}")
print(f"最小値: f={f(sol_min[0], sol_min[1]):.4f}")

# 可視化
fig, ax = plt.subplots(figsize=(8, 8))

# 等高線の描画
x_grid = np.linspace(-1.5, 1.5, 300)
y_grid = np.linspace(-1.5, 1.5, 300)
X, Y = np.meshgrid(x_grid, y_grid)
Z = f(X, Y)

contour = ax.contour(X, Y, Z, levels=15, cmap='coolwarm', alpha=0.7)
ax.clabel(contour, inline=True, fontsize=8)

# 制約曲線(単位円)の描画
theta = np.linspace(0, 2 * np.pi, 200)
ax.plot(np.cos(theta), np.sin(theta), 'k-', linewidth=2, label='$x^2+y^2=1$')

# 停留点の描画
ax.plot(sol_max[0], sol_max[1], 'ro', markersize=10, label=f'Max: f={f(sol_max[0], sol_max[1]):.2f}')
ax.plot(sol_min[0], sol_min[1], 'bs', markersize=10, label=f'Min: f={f(sol_min[0], sol_min[1]):.2f}')

# 勾配ベクトルの描画
scale = 0.3
ax.arrow(sol_max[0], sol_max[1], scale*1, scale*1, head_width=0.05, color='red', alpha=0.7)
ax.arrow(sol_max[0], sol_max[1], scale*2*sol_max[2]*sol_max[0], scale*2*sol_max[2]*sol_max[1],
         head_width=0.05, color='green', alpha=0.7)

ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Lagrange Multiplier Method')
ax.legend()
ax.set_aspect('equal')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

このコードを実行すると、等高線(目的関数 $f = x + y$ の値)と制約曲線(単位円)が描画され、最大点と最小点が等高線と制約曲線が接する位置にあることが確認できます。

まとめ

本記事では、ラグランジュの未定乗数法について解説しました。

  • ラグランジュの未定乗数法は、等式制約付き最適化問題を解くための基本手法である
  • 幾何学的には、目的関数の等高線と制約曲線が接する点が最適解に対応する
  • ラグランジュ関数 $L = f – \lambda g$ を定義し、その停留条件を解くことで最適解が得られる
  • 複数の制約条件がある場合も、制約の数だけ乗数を導入して自然に拡張できる

ラグランジュの未定乗数法は、サポートベクターマシン(SVM)やエントロピー最大化など、機械学習の多くのアルゴリズムの基礎となる重要な手法です。