ニュートン法とは?アルゴリズムの仕組みをわかりやすく解説して実装する

ニュートン法(Newton’s method)は、非線形方程式 $f(x) = 0$ の解(根)を反復的に近似する古典的なアルゴリズムです。テイラー展開に基づく単純な原理でありながら、2次収束という高速な収束性を持つ強力な手法です。

数値解析の基本中の基本であり、最適化問題や機械学習のパラメータ推定にも応用されます。

本記事の内容

  • ニュートン法の幾何学的な直感
  • テイラー展開からの数学的導出
  • 収束性の解析
  • Pythonでの実装と可視化

ニュートン法の直感

ニュートン法のアイデアは非常にシンプルです。

  1. 現在の近似解 $x_n$ における関数 $f(x)$ の接線を引く
  2. その接線が $x$ 軸と交わる点を次の近似解 $x_{n+1}$ とする
  3. 収束するまで繰り返す

接線は関数の局所的な線形近似なので、$f(x) = 0$ の解に十分近い点から出発すれば、接線の零点は真の解により近くなります。

数学的導出

テイラー展開からの導出

関数 $f(x)$ の $x = x_n$ まわりの1次テイラー展開は、

$$ f(x) \approx f(x_n) + f'(x_n)(x – x_n) $$

です。この線形近似の零点、すなわち $f(x_n) + f'(x_n)(x – x_n) = 0$ を解くと、

$$ x = x_n – \frac{f(x_n)}{f'(x_n)} $$

が得られます。この $x$ を次の近似解 $x_{n+1}$ とします。

ニュートン法の反復公式

$$ x_{n+1} = x_n – \frac{f(x_n)}{f'(x_n)} $$

この式がニュートン法の更新則です。$f'(x_n) \neq 0$ である限り、反復を続けることができます。

収束性の解析

2次収束

ニュートン法の大きな特長は、2次収束(quadratic convergence)です。真の解を $x^*$ とし、誤差を $e_n = x_n – x^*$ とすると、$f(x^*) = 0$ のまわりでテイラー展開すると、

$$ f(x_n) = f(x^* + e_n) = f(x^*) + f'(x^*) e_n + \frac{1}{2} f”(x^*) e_n^2 + O(e_n^3) $$

$f(x^*) = 0$ なので、

$$ f(x_n) = f'(x^*) e_n + \frac{1}{2} f”(x^*) e_n^2 + O(e_n^3) $$

同様に、

$$ f'(x_n) = f'(x^*) + f”(x^*) e_n + O(e_n^2) $$

これらをニュートン法の更新則に代入すると、

$$ \begin{align} e_{n+1} &= x_{n+1} – x^* = e_n – \frac{f(x_n)}{f'(x_n)} \\ &= e_n – \frac{f'(x^*) e_n + \frac{1}{2} f”(x^*) e_n^2}{f'(x^*) + f”(x^*) e_n} + O(e_n^3) \end{align} $$

分子・分母を $f'(x^*)$ で割り、$e_n$ について整理すると、

$$ e_{n+1} \approx \frac{f”(x^*)}{2 f'(x^*)} e_n^2 $$

したがって、誤差は各ステップで2乗に比例して減少します。これが2次収束です。例えば、ある反復で誤差が $10^{-3}$ であれば、次の反復では $10^{-6}$ 程度になります。

収束の条件

ニュートン法が収束するためには、以下の条件が必要です。

  • $f'(x^*) \neq 0$(単根であること)
  • 初期値 $x_0$ が解 $x^*$ に十分近いこと
  • $f(x)$ が解の近傍で2回微分可能であること

具体例

$f(x) = x^2 – 2 = 0$ を解いて $\sqrt{2}$ を求めてみましょう。

$f'(x) = 2x$ なので、更新式は

$$ x_{n+1} = x_n – \frac{x_n^2 – 2}{2x_n} = \frac{x_n}{2} + \frac{1}{x_n} $$

初期値 $x_0 = 2$ から出発すると、

$$ \begin{align} x_0 &= 2 \\ x_1 &= \frac{2}{2} + \frac{1}{2} = 1.5 \\ x_2 &= \frac{1.5}{2} + \frac{1}{1.5} = 1.41\overline{6} \\ x_3 &= 1.41421568… \\ x_4 &= 1.41421356… \end{align} $$

わずか4回の反復で、$\sqrt{2} = 1.41421356…$ にほぼ一致しています。

Pythonでの実装

ニュートン法を実装し、収束の様子を可視化します。

import numpy as np
import matplotlib.pyplot as plt

def newton_method(f, df, x0, tol=1e-12, max_iter=50):
    """ニュートン法で f(x)=0 の根を求める"""
    history = [x0]
    x = x0
    for i in range(max_iter):
        fx = f(x)
        dfx = df(x)
        if abs(dfx) < 1e-15:
            print("導関数がゼロに近いため停止")
            break
        x_new = x - fx / dfx
        history.append(x_new)
        if abs(x_new - x) < tol:
            break
        x = x_new
    return x, history

# f(x) = x^2 - 2 の根を求める(sqrt(2))
f = lambda x: x**2 - 2
df = lambda x: 2 * x

root, history = newton_method(f, df, x0=2.0)
print(f"求めた根: {root:.15f}")
print(f"真の値:   {np.sqrt(2):.15f}")
print(f"反復回数: {len(history) - 1}")

# 収束の可視化
fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# 左: 関数と接線の描画
x_plot = np.linspace(0.5, 2.5, 300)
axes[0].plot(x_plot, f(x_plot), 'b-', linewidth=2, label='$f(x) = x^2 - 2$')
axes[0].axhline(y=0, color='k', linewidth=0.5)

colors = plt.cm.Reds(np.linspace(0.3, 0.9, min(4, len(history))))
for i in range(min(4, len(history) - 1)):
    xi = history[i]
    # 接線: y = f(xi) + f'(xi)(x - xi)
    tangent = f(xi) + df(xi) * (x_plot - xi)
    axes[0].plot(x_plot, tangent, '--', color=colors[i], alpha=0.7,
                 label=f'Tangent at $x_{i}$={xi:.4f}')
    axes[0].plot(xi, f(xi), 'o', color=colors[i], markersize=8)

axes[0].set_xlim(0.5, 2.5)
axes[0].set_ylim(-2, 3)
axes[0].set_xlabel('x')
axes[0].set_ylabel('f(x)')
axes[0].set_title("Newton's Method: Tangent Lines")
axes[0].legend(fontsize=8)
axes[0].grid(True, alpha=0.3)

# 右: 誤差の対数プロット(2次収束の確認)
errors = [abs(h - np.sqrt(2)) for h in history]
errors = [e for e in errors if e > 0]  # ゼロを除外
axes[1].semilogy(range(len(errors)), errors, 'ro-', linewidth=2, markersize=8)
axes[1].set_xlabel('Iteration')
axes[1].set_ylabel('Error $|x_n - \\sqrt{2}|$')
axes[1].set_title('Convergence Rate (log scale)')
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

左のグラフでは、各反復で引かれる接線が関数の零点に近づいていく様子が見えます。右のグラフでは、誤差が対数スケールでほぼ直線的に減少し、2次収束の特徴を確認できます。

多変数への拡張

ニュートン法は多変数の連立非線形方程式 $\bm{F}(\bm{x}) = \bm{0}$ にも拡張できます。

$$ \bm{x}_{n+1} = \bm{x}_n – \bm{J}(\bm{x}_n)^{-1} \bm{F}(\bm{x}_n) $$

ここで、$\bm{J}$ はヤコビ行列で、$J_{ij} = \frac{\partial F_i}{\partial x_j}$ です。実際の計算では逆行列を直接計算するのではなく、連立1次方程式 $\bm{J}(\bm{x}_n) \bm{d} = -\bm{F}(\bm{x}_n)$ を解いて $\bm{d}$ を求め、$\bm{x}_{n+1} = \bm{x}_n + \bm{d}$ とするのが効率的です。

まとめ

本記事では、ニュートン法のアルゴリズムについて解説しました。

  • ニュートン法は関数の接線の零点を反復的に求めることで $f(x) = 0$ の解を近似する
  • テイラー展開の1次近似に基づいた単純な原理で、更新式は $x_{n+1} = x_n – f(x_n)/f'(x_n)$
  • 解の近傍では2次収束し、各反復で有効桁数がほぼ倍増する
  • 多変数への拡張ではヤコビ行列を用いる