用電腦算微分
前情提要: 用電腦算極限
這裡我們要講的是用數值計算來算函數的微分值.
已知一個函數 $f(x)$ 在某個點 $a$ 的微分值定義是 $$ f'(a) = \lim_{h\to 0} \frac{f(a+h)-f(a)}{h}. $$
我們用一個簡單的例子試試看. 假設我們想求 $f(x)=x^2$ 在 $x=\pi$ 的微分. 根據定義我們有
$$ f'(\pi) = \lim_{h\to 0} \frac{(\pi+h)^2-\pi^2}{h}. $$
接著我們將 $h$ 取靠近 $0$ 的 $11$ 的點並帶入上列這個式子試著來算其極限值. Julia
程式如下
h = range(0, 0.01, length=11); h = h[11: -1 : 2];
fp = ((pi.+h).^2 .- pi^2)./h;
hcat(h, fp, fp.-2*pi)
結果如下:
$h$ | $f'$ | $f'-2\pi$ |
---|---|---|
0.01 | 6.29319 | 0.01 |
0.009 | 6.29219 | 0.009 |
0.008 | 6.29119 | 0.008 |
0.007 | 6.29019 | 0.007 |
0.006 | 6.28919 | 0.006 |
0.005 | 6.28819 | 0.005 |
0.004 | 6.28719 | 0.004 |
0.003 | 6.28619 | 0.003 |
0.002 | 6.28519 | 0.002 |
0.001 | 6.28419 | 0.001 |
上列數字最左邊是 $h$ 值, 中間為估計的微分值. 我們發現的確這個數字會越來越接近真實的解, 也就是 $2\pi$, 約等於 $6.283185307179586$. 最右邊為這個估算值與真實值 $2\pi$ 之間的差. 的確, 當 $h$ 越接近零, 這個估計出來的微分值離 $2\pi$ 的距離越來越小.
Question: 用數值計算微分能有多精確? 這個誤差能不能一直遞減下去?
接著我們取更多靠近 $0$ 的點來計算微分的極限值, 我們列出其與真實值 $2\pi$ 之間的差, 並且把它畫出來.
h = range(1, 16, length=16); h = 10.0.^(-h[1: 16]);
fp = ((pi.+h).^2 .- pi^2)./h;
hcat(h, fp, abs.(fp.-2*pi))
結果如下:
$h$ | $f'$ | $abs(f'-2\pi)$ |
---|---|---|
0.1 | 6.38319 | 0.1 |
0.01 | 6.29319 | 0.01 |
0.001 | 6.28419 | 0.001 |
0.0001 | 6.28329 | 0.0001 |
1.0e-5 | 6.2832 | 9.99998e-6 |
1.0e-6 | 6.28319 | 1.00006e-6 |
1.0e-7 | 6.28319 | 9.5898e-8 |
1.0e-8 | 6.28319 | 4.26073e-8 |
1.0e-9 | 6.28319 | 2.20243e-7 |
1.0e-10 | 6.28319 | 1.9966e-6 |
1.0e-11 | 6.28315 | 3.35305e-5 |
1.0e-12 | 6.28297 | 0.000211166 |
1.0e-13 | 6.27054 | 0.0126457 |
1.0e-14 | 6.39488 | 0.111699 |
1.0e-15 | 5.32907 | 0.954115 |
1.0e-16 | 0.0 | 6.28319 |
觀察最後一下發現, 當 $h$ 很小時微分竟然與真實質差更多, 更不準了!! 比如說當 $h=10^{-14}$ 時, 誤差竟然大到約是 $10^{-1}$.
我們把它畫出來看看, Julia
code 如下:
using Plots
plot(log10.(h), log10.(abs.(fp.-2*pi)),label="Error")
xlabel!("log10(h)")
ylabel!("log10(Error)")
發現雖然誤差在 $h$ 大的時候遞減, 不過當 $h$ 接近零的時候卻又遞增上去了.
那誤差最小值出現在什麼時候呢?
我們發現當 當 $h=1.0*10^{-8}$ 時, 其估計出來的微分值離真實值誤差最小, 其誤差為 $4.26 *10^{-8}$.
不過, WHY?? 為什麼誤差不會一直往下遞減? 其實這也是因為 捨入誤差(rounding-error) 的關係.
觀察一下我們的式子 $$ \frac{f(a+h)-f(a)}{h} $$ 當我們在用數值計算這個式子的時候其實並不完全是這樣子, 在分子應該會有捨入誤差在, 也就是說, 其實我們看到的數字應該是以下這個式子算出來的 $$ \frac{f(a+h)-f(a) + \epsilon}{h} $$ 其中的 $\epsilon$ 就是捨入誤差. 所以, 我們計算的時候會多出了 $\frac{\epsilon}{h}$ 這麼多.
泰勒展開式
再深一點來說, 我們可以利用泰勒展開式知道 $$ \frac{f(a+h)-f(a)}{h} = f'(a) + \frac{h}{2}f''(\xi), \quad a\leq \xi \leq a+h. $$ 這個式子告訴我們, 用這方式算微分誤差應該是 $\frac{h}{2}f''(\xi) = O(h)$, 誤差會隨著 $h$ 減少而線性變小.
數學上我們有以上這個等式, 而數值計算上則是有以下這個等式 $$ \frac{f(a+h)-f(a) + \epsilon}{h} = f'(a) + \frac{h}{2}f''(\xi) + \frac{\epsilon}{h}, \quad a\leq \xi \leq a+h. $$ 也就是說, 真正的誤差公式應該是 $$ \frac{h}{2}f''(\xi) + \frac{\epsilon}{h}, $$ 當 $h$ 非常小的時候 $\frac{\epsilon}{h}$ 這項就會變很大.
比如說, 依我們之前所算的 $\epsilon\approx 10^{-16}$, 那當 $h=10^{-8}$ 時, 算出來的數字會多了大約 $\frac{10^{-16}}{10^{-8}} = 10^{-8}$.
而當 $h=10^{-14}$ 時, 算出來的數字會多了大約 $\frac{10^{-16}}{10^{-14}} = 10^{-2}$. 跟我們之前所發現的完全吻合!! 而這也就是為什麼當 $h$ 很靠近零的時候誤差會上升的原因.
Optimal $h$
那給定一個微分公式, 要怎麼知道 $h$ 能小到什麼程度呢? 一個簡單的感覺是這樣的, 由於誤差的第一項 $\frac{h}{2}f''(\xi)$ 會隨著 $h$ 變小而變小, 第二項 $\frac{\epsilon}{h}$ 則會變大, 因此整體最小值約會發生在兩項交叉時, 也就是當 $$ h \sim \frac{\epsilon}{h}, $$ (由於我們不知道 $f''(\xi)/2$ 是多少, 簡單起見設成 1). 上式稍微計算一下發現誤差最小值約發生在 $h=10^{-8}$, 誤差最小值則約為 $10^{-8}$.
Summary:
最後總結一下:
-
我們可以用數值計算來估計一個函數在某點的微分值 $$ f'(a) \approx \frac{f(a+h)-f(a)}{h}. $$ 這樣的做法稱為有限差分法 (finite difference method).
-
不過計算時 $h$ 值不能無限取小, 需考慮到捨入誤差的影響.