9.3 Határérték mint közelítési folyamat

9.3.1 Cél és konkrét helyzet

A data scientist munkában gyakori, hogy egy függvény értékét egy közeli pontból közelítjük: például a veszteségfüggvény meredekségét egy kis lépésközzel becsüljük, vagy egy modellpredikció simaságát ellenőrizzük. A kérdés az, hogy meddig érdemes csökkenteni a lépésközt. Ebben az alfejezetben az f(x)=exf(x)=e^x függvényt vizsgáljuk az x0=1x_0=1 pont körül, és két közelítést számolunk:

A bemenet a h∈{10−1,10−2,…,10−16}h \in \{10^{-1},10^{-2},\ldots,10^{-16}\} lépésköz-sorozat, a megfigyelési egység egy-egy függvénykiértékelés pár, a kimenet pedig a közelítés abszolút hibája. Előzetes becslés: a különbségi hányados hibája nagy hh-ra körülbelül e2h≈1.36h\frac{e}{2}h \approx 1.36h; nagyon kis hh-ra viszont a lebegőpontos kerekítési hiba nőni fog, így az optimális lépésköz 10−810^{-8} nagyságrendű lesz. A cél annak felismerése, hogy a véges float64 pontosság hol szab határt a matematikai közelítésnek.

9.3.2 Fogalmi magyarázat

9.3.2.1 Sorozat és lépésköz

A lépésköz (step size, increment) egy pozitív valós szám, amellyel az x0x_0 pontból elmozdulunk: x0+hx_0+h. A hh értékekből sorozatot képezhetünk, például hn=10−nh_n=10^{-n} alakban. Az ana_n sorozat konvergenciája azt jelenti, hogy van olyan LL határérték, hogy az eltérés |an−L||a_n-L| minden ε>0\varepsilon>0 hibakorláthoz található NN küszöbtől kezdve kisebb marad. Képletben:

limn→∞an=L⇔∀ε>0∃N:n≥N⇒|an−L|<ε.\lim_{n\to\infty}a_n=L \quad\Longleftrightarrow\quad \forall \varepsilon>0\ \exists N:\ n\ge N \Rightarrow |a_n-L|<\varepsilon.

A h→0h\to0 függvényhatárérték hasonló, csak folytonos változóval fogalmaz: limh→0B(h)=L\lim_{h\to0}B(h)=L azt jelenti, hogy minden ε\varepsilon-hoz van δ\delta, hogy 0<|h|<δ0<|h|<\delta esetén |B(h)−L|<ε|B(h)-L|<\varepsilon. Numerikusan ez egy közelítési folyamat: a hiba addig csökken, amíg el nem érjük a számábrázolás határát.

9.3.2.2 Konvergencia a különbségi hányadoson

A példánkban az

B(h)=e1+h−e1hB(h)=\frac{e^{1+h}-e^1}{h}

kifejezésre limh→0B(h)=e1\lim_{h\to0}B(h)=e^1. Az exponenciális függvény Taylor-közelítéséből eh=1+h+h22+⋯e^h=1+h+\frac{h^2}{2}+\cdots, ezért

$$B(h)=e^1\cdot\frac{e^h-1}{h}=e^1\Bigl(1+\frac{h}{2}+\frac{h^2}{6}+\cdots\Bigr).$$

A matematikai közelítési hiba tehát nagy hh-nál dominánsan

|B(h)−e1|≈e12h,|B(h)-e^1|\approx \frac{e^1}{2}h,

ami lineárisan csökken, ahogy hh-t csökkentjük. A Lebegőpont, hiányzó érték és stabil számítás alfejezetben bevezetett float64 azonban közbeszól.

9.3.2.3 Kerekítési hiba

A float64 relatív hibája ϵm≈2.22×10−16\epsilon_m\approx2.22\times10^{-16} (gépi epszilon). A e1+h−e1e^{1+h}-e^1 kivonás numerikusan érzékeny: a számláló nagysága körülbelül e1he^1h, a kivonás abszolút kerekítési hibája pedig ϵme1\epsilon_m e^1 nagyságrendű. A hányados numerikus hibája:

δnum≈ϵme1h.\delta_{\text{num}}\approx\frac{\epsilon_m e^1}{h}.

Ez hh csökkenésével nő. A teljes hiba két ellentétes irányú tag összege: a matematikai hiba O(h)O(h), a kerekítési hiba O(1/h)O(1/h). Az optimum ott van, ahol a két tag egyenlő:

e1h2≈ϵme1h⇒hopt≈2ϵm≈1.7×10−8.\frac{e^1 h}{2}\approx\frac{\epsilon_m e^1}{h}\quad\Rightarrow\quad h_{\text{opt}}\approx\sqrt{2\epsilon_m}\approx1.7\times10^{-8}.

9.3.2.4 Folytonosság szemlélete

A folytonosság azt jelenti, hogy kis bemeneti változás kis kimeneti változást okoz. Képletben:

limh→0ex0+h=ex0.\lim_{h\to0}e^{x_0+h}=e^{x_0}.

Numerikusan: h=10−1h=10^{-1}-nél e1.1−e1≈0.286e^{1.1}-e^1\approx0.286; h=10−8h=10^{-8}-nál e1+10−8−e1≈2.718×10−8e^{1+10^{-8}}-e^1\approx2.718\times10^{-8}. A hiba arányos hh-val. A float64-ben azonban 1+10−161+10^{-16} pontosan 1.01.0, mert a mantissza nem tud különbséget tenni; ekkor a közelítés hibája nullára ugrik, de nem azért, mert a függvény tökéletesebb lett, hanem mert a gépi bemenet már nem változott. A folytonossági határátmenet tehát befagy a véges pontosságnál.

9.3.3 Teljes minimális munkapélda

A következő kód a két közelítést számolja ki, és ábrázolja a különbségi hányados hibáját. A kód a lab projekt Python 3.12 környezetében futtatható; csak numpy és matplotlib szükséges, adatfájl nem.

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

x0 = 1.0
exact = math.exp(x0)          # e^1: határérték és meredekség is

# Logaritmikusan csökkenő lépésköz: 1e-1, 1e-2, ..., 1e-16
hs = np.geomspace(1e-1, 1e-16, 16)   # shape: (16,)

# 1) Függvényérték-közelítés: e^(x0+h) közelítse e^x0-t
continuity_err = np.abs(np.exp(x0 + hs) - exact)   # shape: (16,)

# 2) Előremutató különbségi hányados naiv kivonással
fd = (np.exp(x0 + hs) - exact) / hs
fd_err = np.abs(fd - exact)

# 3) Stabil változat: expm1(h) = e^h - 1 pontosan kiszámítva
fd_stable = exact * np.expm1(hs) / hs
fd_stable_err = np.abs(fd_stable - exact)

print("h                |e^(x0+h)-e|      |fd-e|          |fd_stable-e|")
for h, c, f, fs in zip(hs, continuity_err, fd_err, fd_stable_err):
    print(f"{h:8.1e} {c:15.6e} {f:15.6e} {fs:15.6e}")

plt.figure(figsize=(7, 4))
plt.loglog(hs, fd_err, "o-", label="naiv (exp(x+h)-exp(x))/h")
plt.loglog(hs, fd_stable_err, "s--", label="stabil expm1(h)/h")
plt.xlabel("h lépésköz")
plt.ylabel("abszolút hiba")
plt.title("Különbségi hányados hibája: a túl kis lépésköz árt")
plt.grid(True, which="both", ls="--", alpha=0.5)
plt.legend()
plt.tight_layout()
plt.savefig("s035_step_error.png", dpi=150)
plt.show()

A kimenet gépenként kissé eltérhet, de a trend minden IEEE-754 float64 környezetben azonos. Szemléltető várt sorok:

h                |e^(x0+h)-e|      |fd-e|          |fd_stable-e|
 1.0e-01        2.9e-01        1.4e-01        1.4e-01
 1.0e-04        2.7e-04        1.4e-04        1.4e-04
 1.0e-08        2.7e-08        9.1e-08        1.4e-08
 1.0e-12        2.7e-12        6.0e-04        1.4e-12
 1.0e-16        0.0e+00        2.7e+00        0.0e+00

A naiv változat hibája 10−810^{-8} körül a legkisebb, majd nő; a stabil expm1 változat a kivonási kerekítést elkerülve a matematikai O(h)O(h) szinten marad, amíg a lépésköz ábrázolása nem csorbul. Az alábbi chart a naiv hiba log10\log_{10}-transzformált pontjait mutatja:

Naiv különbségi hányados hibája - A Python-kód képletéből számított szemléltető pontok; nem futtatási mérés.

A pontok a csökkenő, majd növekvő hibát mutatják; a tanuló futtatása adja a tényleges, gépen mért értékeket.

9.3.4 Eredmény értelmezése

A függvényérték-közelítés hibája a folytonosság miatt monoton csökken, majd h=10−16h=10^{-16}-nál nulla lesz, mert a gépen 1+10−16=11+10^{-16}=1. A különbségi hányados hibája ezzel szemben U alakú:

Az optimum körülbelül hopt≈2ϵm≈1.7×10−8h_{\text{opt}}\approx\sqrt{2\epsilon_m}\approx1.7\times10^{-8}, amit a táblázat is tükröz: 10−810^{-8}-nál a naiv hiba 9.1×10−89.1\times10^{-8}, míg 10−1610^{-16}-nál már e≈2.7e\approx2.7. A stabil expm1 változat azért pontosabb, mert a eh−1e^h-1 értéket közvetlenül, a kivonási kerekítés nélkül számolja, így a hibája 10−1210^{-12}-nél is 1.4×10−121.4\times10^{-12} marad. A véges pontosság határa tehát nem maga a határérték, hanem az adott számítási út érzékenysége.

9.3.5 Feladatok

  1. Értelmezés. Miért ad a függvényérték-közelítés h=10−16h=10^{-16}-nál nulla hibát, és miért helytelen ebből azt állítani, hogy a valós exponenciális függvény gépi kiértékelése hiba nélkül folytonos?

  2. Implementáció. Írd át a kódot a szimmetrikus különbségi hányadosra: ex0+h−ex0−h2h\frac{e^{x_0+h}-e^{x_0-h}}{2h}. Számold ki a hibát 10−110^{-1} és 10−1610^{-16} között, és ábrázold. Mekkora az optimum nagyságrendje? (Segítség: a matematikai hiba most O(h2)O(h^2), a numerikus hiba továbbra is ϵm/h\epsilon_m/h nagyságrendű.)

  3. Hibadiagnózis. Egy kolléga azt írja: „A derivált közelítésnél h=10−14h=10^{-14}-nel a hiba nagyobb, mint h=10−6h=10^{-6}-nál, ezért a kód hibás.” Melyik jelenség magyarázza ezt, és hogyan ellenőriznéd a naiv kivonás helyett expm1-gyel?

  4. Megváltoztatott feltétel. Végezd el ugyanezt a mérést f(x)=lnxf(x)=\ln x függvénnyel az x0=2x_0=2 pontban, naiv különbségi hányadossal, h=10−8h=10^{-8} mellett. A pontos derivált 1/21/2. Körülbelül mekkora hibát vársz, és miért dominál itt már a kerekítés jobban, mint az exponenciális esetben?

  5. Transzfer. A Northstar distance_km értékekből egy szállítási időre vonatkozó jellemző meredekségét szeretnéd numerikusan közelíteni. A távolságok 5 és 300 km közöttiek, a függvényértékeket lebegőpontos kilométerben tároljuk. Milyen lépésköz-nagyságrendet javasolnál a numerikus differenciához, és miért nem érdemes 10−1210^{-12} km-t használni?

9.3.6 Megoldások és indoklás

  1. 1+10−161+10^{-16} a float64-ben pontosan 1.01.0, ezért np.exp(1 + 1e-16) az np.exp(1.0) értékét adja, a különbség nulla. Ez az ábrázolás tulajdonsága, nem a valós függvényé: valós számokkal e1+10−16−e1≈2.718×10−16e^{1+10^{-16}}-e^1\approx2.718\times10^{-16} lenne. A nulla hiba tehát a bemenet eldurvulásából fakad, nem a folytonosság tökéletes gépi reprodukciójából.

  2. A szimmetrikus hányadosra ex0+h−ex0−h≈2hex0+O(h3)e^{x_0+h}-e^{x_0-h}\approx2h e^{x_0}+O(h^3), ezért a matematikai hiba e6h2\frac{e}{6}h^2 nagyságrendű. A numerikus hiba továbbra is ϵmeh\frac{\epsilon_m e}{h} nagyságrendű. Az optimum: eh26≈ϵmeh\frac{e h^2}{6}\approx\frac{\epsilon_m e}{h}, azaz hopt≈(6ϵm)1/3≈10−5h_{\text{opt}}\approx(6\epsilon_m)^{1/3}\approx10^{-5}. A szimmetrikus hányados tehát nagyobb lépésközzel is pontosabb, mint az előremutató, de a túl kis hh itt is ront. A kódban fd = (np.exp(x0 + hs) - np.exp(x0 - hs)) / (2 * hs) átírást kell elvégezni.

  3. A jelenség a kivonási kerekítés. h=10−14h=10^{-14}-nél a számláló e1+10−14−e1e^{1+10^{-14}}-e^1 abszolút kerekítési hibája ϵme\epsilon_m e nagyságrendű, a számláló maga pedig 2.7×10−142.7\times10^{-14}; a hányados hibája ϵmeh≈2.7×10−1610−14=0.027\frac{\epsilon_m e}{h}\approx\frac{2.7\times10^{-16}}{10^{-14}}=0.027, ami nagyobb, mint a h=10−6h=10^{-6}-nál várható 10−610^{-6} matematikai hiba. Ellenőrzés: ugyanazon hh-ra a stabil fd_stable = exact * np.expm1(h) / h hibája 10−1410^{-14}-nél is 10−1410^{-14} nagyságrendű marad, tehát ha a naiv hiba nagy, a kivonási kerekítés okozza, nem a kód logikája.

  4. f(x)=lnxf(x)=\ln x esetén f′(2)=1/2f'(2)=1/2, f″(2)=−1/4f''(2)=-1/4. A forward diff matematikai hibája |f″(ξ)|2h≈h8=1.25×10−9\frac{|f''(\xi)|}{2}h\approx\frac{h}{8}=1.25\times10^{-9}. A kerekítési hiba ϵm|ln2|h≈2.2×10−16⋅0.6910−8≈1.5×10−8\frac{\epsilon_m|\ln 2|}{h}\approx\frac{2.2\times10^{-16}\cdot0.69}{10^{-8}}\approx1.5\times10^{-8}, tehát h=10−8h=10^{-8}-nál a kerekítési hiba már egy nagyságrenddel nagyobb a matematikai hibánál. A logaritmus lassabb változása miatt a hasznos jel kisebb, így a kerekítés hamarabb elnyomja.

  5. A derivált közelítéséhez az x0x_0 abszolút nagyságrendje szabja a kivonási problémát. Az optimális hh körülbelül ϵm|x0|\sqrt{\epsilon_m}|x_0| nagyságrendű, azaz 5 km-nél 7.5×10−87.5\times10^{-8} km, 300 km-nél 4.5×10−64.5\times10^{-6} km. Gyakorlati mérési bizonytalanság mellett érdemes 10−310^{-3}–10−510^{-5} km nagyságrendű lépésközt használni, és ellenőrizni, hogy a hiba hh-val arányosan csökken-e. A 10−1210^{-12} km lépésköz a kivonási kerekítési hibát a hasznos jel fölé emeli, ezért nem javasolt.

9.3.7 Gyakori tévedés ellenpéldával

A leggyakoribb tévedés: „minél kisebb a lépésköz, annál pontosabb a numerikus közelítés.” Ellenpélda: h=10−16h=10^{-16}-nál a naiv különbségi hányados hibája e≈2.718e\approx2.718, miközben h=10−8h=10^{-8}-nál a hiba csak 9.1×10−89.1\times10^{-8}. Ennek oka a kivonási kerekítés, amelyet a Lebegőpont, hiányzó érték és stabil számítás alfejezetben a float64 relatív hibájánál vezettünk be. A hibát a lépésköz csökkentése két oldalról befolyásolja: a matematikai közelítési hiba csökken, a kerekítési hiba nő. Az optimum ott van, ahol a kettő egyensúlyba kerül. A függvényérték-közelítésnél a túl kis hh nem ront, hanem a bemenet befagy; a különbségi hányadosnál viszont a kivonás felnagyítja a hibát. A konvergencia matematikai fogalma tetszőleges pontosságot ígér, de a float64 csak ennek közelítését tudja szolgáltatni.

9.3.8 Önellenőrzés

Rövid válaszok: a sorozat elemei egy diszkrét hnh_n mentén közelítenek, a függvényhatárérték h→0h\to0 folytonos változóval fogalmaz; a nagy hh-s szakaszon a hiba O(h)O(h), kis hh-nál O(1/h)O(1/h); a kerekítési dominanciát a hiba növekedése vagy zajossága jelzi; az expm1 a eh−1e^h-1 kivonást elkerüli, de maga hh is kerekített; a 10−1210^{-12} km lépésköz a kivonási hibát a hasznos jel fölé emeli.

A numerikus különbségi hányados hibája nem feltétlenül csökken monoton a lépésköz csökkentésével. A csonkítási hiba és a lebegőpontos kerekítés közötti kompromisszumot például középső differenciával, több lépésközt összehasonlítva lehet megfigyelni.

9.3.9 Rövid összefoglaló

A határérték közelítési folyamat: a sorozat vagy függvényérték hibáját egyre kisebb lépésközzel csökkentjük, és a matematikai konvergencia azt ígéri, hogy a hiba tetszőlegesen kicsi lehet. A float64 véges pontossága azonban a lépésköz csökkentését megfordítja: a kivonási kerekítés a különbségi hányados hibáját egy pont után növeli. Az optimális lépésköz ott van, ahol a matematikai és a kerekítési hiba egyensúlyba kerül; az expm1-féle stabil átírás kitolja ezt a határt. A folytonosság szemlélete szerint kis bemeneti változás kis kimeneti változást ad, de ha a bemenet maga már nem változtatható a gépen, a határátmenet befagy. A következő alfejezetben ezt a meredekséget numerikus deriváltként használjuk, ahol a Meredekség és numerikus derivált a hibaképletet és a stabil alternatívákat mélyíti el.