機械学習に必要なテイラー展開・マクローリン展開をおさえる

Posted: , Category: 可視化 , 数学 , 解析学

機械学習の理論や論文を勉強していると、時々テイラー展開 (Taylor Expansion)やマクローリン展開(Maclaurin Expansion)に遭遇します。

正直テイラー展開なんて知らないよ … と思う人も多いと思いますが、実際私も大学1年生の時に学んで以来さっぱりで、実務で触れるにあたって学び直しています。

しかし非常に登場頻度も高く、勉強する価値は高いのでテイラー展開とマクローリン展開について学んでいきましょう。

非常に登場頻度も高く、これらを学ぶことは非常に重要です。

テイラー展開の概要

まず、テイラー展開がどのようなものかについて理解しましょう。

テイラー展開は、任意の関数$f(x)$を多項式を用いて表現しようとするものです。

証明は少し手間がかかるので、結論だけでもおさえておくと良いでしょう。

テイラー展開

無限回微分可能な関数$f(x)$が、 次のように表現できる時、

\begin{equation}
\begin{split}
f(x) &= f(a) + f'(a)(x-a) + \frac{f''(a)}{2!}(x-a)^2 + \dots + \frac{f^{(n)}(a)}{n!} (x-a)^n + \dots \\
&=  \sum_{n=0}^{\infin} \frac{f^{(n)}(a)}{n!}(x-a)^n
\end{split}
\end{equation}

(1)式を、$x=a$におけるテイラー展開という。

テイラー展開は、次のように定義されます。

一方、$x=0$におけるテイラー展開をマクローリン展開と言います。

マクローリン展開

$x=0$近傍で、関数$f(x)$が無限回微分可能な関数の時、

\begin{equation}
\begin{split}
f(x) & = f(0) + f'(0)(x) + \frac{f''(0)}{2!}(x)^2 + \dots + \frac{f^{(n)}(0)}{n!} (x)^n + \dots \\
&=  \sum_{n=0}^{\infin} \frac{f^{(n)}(0)}{n!}(x)^n
\end{split}
\end{equation}

(2)式を、マクローリン展開と呼ぶ。

実用上よく登場するマクローリン展開

(2)式を利用することで、$x=0$近傍で無限回微分可能な関数は、一般的に表現できることがわかります。

一方で、特に次の関数におけるマクローリン展開は非常に多く登場するので、いつでも思い出せるようにしておくと良いでしょう。

よく登場するマクローリン展開
e^x = 1 + \frac{1}{1!}x + \frac{1}{2!}x^2 + \dots + \frac{1}{n!}x^n + \dots 
log(1+x) = \frac{1}{x} -   \frac{1}{x^2} +  \frac{1}{x^3}   -  \dots + (-1)^{n+1}  \frac{x^n}{n}  + \dots
sinx = x -  \frac{x^3}{3!} +  \frac{x^5}{5!} -  \frac{x^7}{7!}  \dots + (-1)^{n}\frac{x^{2n+1}}{(2n+1)!} + \dots
cosx = 1 - \frac{x^2}{2!} +  \frac{x^4}{4!}  -  \frac{x^6}{6!}  + \dots + (-1)^n\frac{x^{2n}}{2n!} + \dots

機械学習におけるテイラー展開・マクローリン展開

機械学習分野では、テイラー展開やマクローリン展開は比較的よく登場します。

特に、損失関数などの関数を最小化するための勾配を探索する際に、テイラー展開が利用されたりします。

テイラー展開を実際に実装して確かめる

テイラー展開やマクローリン展開の数式を、具体例を通してみていきましょう。

テイラー展開は一般的な形ですが、マクローリン展開の方が数式が簡単なので、今回はマクローリン展開を扱ってみます。

今回題材として、関数$sinx$をマクローリン展開を考えてみます。

$sin(x)$のマクローリン展開

$sin(x)$のグラフをまずは書いてみましょう。

import numpy as np
import math
import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(10, 3), dpi=120)

x = np.linspace(-20, 20, 1000)
y = np.sin(x)

ax.plot(x, y)

sin(x)の関数はこのようになっています。

ここで、$sinx$のマクローリン展開は次のようになるのでした。

sinx = x -  \frac{x^3}{3!} +  \frac{x^5}{5!} -  \frac{x^7}{7!}  \dots + (-1)^{n}\frac{x^{2n+1}}{(2n+1)!} + \dots

まず、$sinx$の3次のマクローリン展開はこのようになっています。

sinx = x -  \frac{x^3}{3!}

これを描写してみましょう。コードは次のようになります。

fig, ax = plt.subplots(figsize=(10, 3), dpi=120)
ax.set_ylim([-2, 2])

x = np.linspace(-10, 10, 1000)
y = np.sin(x)
y_maclaurin3 = x - pow(x, 3) / 3 * 2 * 1

ax.plot(x, y, label="y = sin(x)")
ax.plot(x, y_maclaurin3, label=r"$y = x - \frac{x^3}{3!}$")

ax.legend()

$x=0$近傍ではいい感じに近似できていますが、それ以外では当てはまっていないことがわかります。

では、マクローリン展開の次数$n$を増やしてみます。次数$n$に対する$sin(x)$のマクローリン展開を実装した関数を次のように実装し、可視化します。

def sin_maclaurin(x, n):
    t = np.zeros(len(x))
    
    for i in range(n):
        deg = i + 1
        if deg % 2 != 0:
            t +=  (-1) ** ((deg - 1) // 2) * (pow(x, deg)  / math.factorial(deg))
            
    return t

次数を1から17まで変化させて、グラフ化してみます。

fig, ax = plt.subplots(figsize=(10, 4), dpi=120)

ax.set_ylim([-2, 2])

x = np.linspace(-10, 10, 200)
y = np.sin(x)
sin_mac_3 = sin_maclaurin(x, 11)

dims = [i for i in range(0, 18) if i%2 != 0 ]

ax.plot(x, y, label="sin(x)")
for idx, dim in enumerate(dims):
    data = sin_maclaurin(x, dim)
    ax.plot(x, data, label="dim={}".format(dim))
    
ax.legend()

結果はこのようになりました。多すぎてみにくいですが、水色の線が$n=17$でマクローリン展開したもので、ある程度の範囲まではよく近似できていることがわかります。

このように、$sin(x)$の場合は、マクローリン展開の次数を増やすことで、より広い範囲で関数を近似できることがわかりました。

【広告】
統計学的にあなたの悩みを解決します。
仕事やプライベートでお悩みの方は、ベテラン占い師 蓮若菜にご相談ください。

機械学習と情報技術