Rでテイラー展開

テイラー展開とは

テイラー展開とは、ある関数 \(f(x)\) を、特定の点 \(x=a\) における関数の情報(その点での値と各階微分係数)だけを使って、多項式の無限級数として表現する方法です。

\[
f(x) = f(a) + f'(a)(x-a) + \dfrac{f''(a)}{2!}(x-a)^2 + \dfrac{f'''(a)}{3!}(x-a)^3 + \cdots = \sum_{n=0}^{\infty} \dfrac{f^{(n)}(a)}{n!}(x-a)^n
\]

特に \(a=0\) の場合はマクローリン展開と呼ばれます。

直感的な意味は次の通りです。

  • 0次の項\(f(a)\)

    • その点での値そのもの
  • 1次の項\(f'(a)(x-a)\)

    • 接線による近似(傾きを考慮)
  • 2次の項

    • 曲がり具合(曲率)を考慮した補正
  • 高次の項

    • 加算するほど、\(a\) の近くでの近似精度が上がっていく

つまり「多項式(足し算と掛け算だけでできる簡単な関数)を使って、複雑な関数(\(\sin x\), \(\cos x\), \(e^x\) など)を近似する」というのがテイラー展開の本質です。

以下のシミュレーションでは、\(\sin(x)\)\(e^x\) を例にとり、次数を増やしながらテイラー多項式が真の関数にどう近づいていくかを可視化して確認します。

テイラー多項式を計算する関数

taylor_sin, taylor_exp は、それぞれの関数の \(x=0\) 周りのマクローリン級数を有限項で打ち切って計算する関数です。

以下はそれぞれのマクローリン展開式です。

\[
\sin(x) = \sum_{k=0}^{n-1} (-1)^k \dfrac{x^{2k+1}}{(2k+1)!} \dfrac{x^{k}}{k!}\quad,\quad e^x = \sum_{k=0}^{n-1} \dfrac{x^{k}}{k!}
\]

library(ggplot2)
library(dplyr)
library(purrr)

# sin(x) = Σ_{k=0}^{n-1} (-1)^k * x^(2k+1) / (2k+1)!
taylor_sin <- function(x, n_terms) {
  out <- rep(0, length(x))
  for (k in 0:(n_terms - 1)) {
    out <- out + (-1)^k * x^(2 * k + 1) / factorial(2 * k + 1)
  }
  out
}

# exp(x) = Σ_{k=0}^{n-1} x^k / k!
taylor_exp <- function(x, n_terms) {
  out <- rep(0, length(x))
  for (k in 0:(n_terms - 1)) {
    out <- out + x^k / factorial(k)
  }
  out
}

シミュレーションによる可視化

次数を増やしながら近似曲線を計算し、真の関数と重ねて可視化します。

\(\sin(x)\) の場合

x <- seq(-2 * pi, 2 * pi, length.out = 400)
orders <- c(1, 3, 5, 7, 11, 15) # 使用する項数(次数+1)

df_approx <- map_dfr(orders, function(n) {
  data.frame(x = x, y = taylor_sin(x, n), order = n)
})

df_true <- data.frame(x = x, y = sin(x))

ggplot() +
  geom_line(data = df_true, aes(x = x, y = y), color = "gray50", linewidth = 1) +
  geom_line(data = df_approx, aes(x = x, y = y), color = "tomato", linewidth = 0.8) +
  facet_wrap(~order, labeller = label_both) +
  coord_cartesian(ylim = c(-3, 3)) +
  labs(
    title = "sin(x) のテイラー近似:項数ごとの比較",
    subtitle = "灰色 = 真の関数 sin(x)  赤 = テイラー多項式",
    x = "x", y = "y"
  ) +
  theme_bw()

cat("=== x = pi/3 における sin(x) の近似精度 ===\n")
cat("真値       :", sin(pi / 3), "\n")
cat("3項近似    :", taylor_sin(pi / 3, 3), "\n")
cat("10項近似   :", taylor_sin(pi / 3, 10), "\n\n")
=== x = pi/3 における sin(x) の近似精度 ===
真値       : 0.8660254 
3項近似    : 0.8662953 
10項近似   : 0.8660254 
Figure 1

項数を増やすほど近似曲線(赤)が真の関数(灰色)に「原点付近から外側へ」フィットしていく様子が確認できます。

これはテイラー展開が展開点の近くで最も精度が良く、遠ざかるほど誤差が大きくなるという性質を表しています。

\(e^x\) の場合

x2 <- seq(-3, 3, length.out = 300)
orders2 <- c(1, 2, 4, 6, 10)

df_exp_approx <- map_dfr(orders2, function(n) {
  data.frame(x = x2, y = taylor_exp(x2, n), order = n)
})
df_exp_true <- data.frame(x = x2, y = exp(x2))

ggplot() +
  geom_line(data = df_exp_true, aes(x = x, y = y), color = "gray50", linewidth = 1) +
  geom_line(data = df_exp_approx, aes(x = x, y = y), color = "tomato", linewidth = 0.8) +
  facet_wrap(~order, labeller = label_both) +
  coord_cartesian(ylim = c(-5, 25)) +
  labs(
    title = "exp(x) のテイラー近似:項数ごとの比較",
    subtitle = "灰色 = 真の関数 exp(x)  赤 = テイラー多項式",
    x = "x", y = "y"
  ) +
  theme_bw()

cat("=== x = 2 における exp(x) の近似精度 ===\n")
cat("真値       :", exp(2), "\n")
cat("5項近似    :", taylor_exp(2, 5), "\n")
cat("15項近似   :", taylor_exp(2, 15), "\n")
=== x = 2 における exp(x) の近似精度 ===
真値       : 7.389056 
5項近似    : 7 
15項近似   : 7.389056 
Figure 2

続いて、誤差の収束をログスケールで確認します。

x_fixed <- 2 # exp(2) で誤差収束を確認
n_seq <- 1:15

df_error <- data.frame(
  n = n_seq,
  abs_error = sapply(n_seq, function(n) abs(taylor_exp(x_fixed, n) - exp(x_fixed)))
)

ggplot(df_error, aes(x = n, y = abs_error)) +
  geom_line() +
  geom_point(size = 2) +
  scale_y_log10() +
  labs(
    title = paste0("x = ", x_fixed, " における exp(x) の近似誤差収束(対数スケール)"),
    x = "使用項数 n", y = "絶対誤差 |近似値 - 真値| (log10)"
  ) +
  theme_minimal()
Figure 3

Figure 3 の誤差収束のグラフ(対数スケール)では、項数 \(n\) が増えるごとに誤差が \(\dfrac{|x|^{n}}{n!}\) のオーダーで急激に(階乗的に)減っていく様子が確認できます。

以上です。