Ez a III. ellenőrző pont nem vezet be új statisztikai fogalmat. A 9–11. fejezet jelölés-, tömb-, gradiens- és optimalizálási eszköztárát kapcsolja össze a Terület, összeg és numerikus integrál–Várható érték és Monte Carlo közelítés integrál-, sűrűség- és Monte Carlo fogalmaival egyetlen veszteségfüggvényen. Az II. ellenőrző pont: adatból ellenőrzött feature-tábla alfejezetben a feature-táblát kontrollösszeggel és keret-összehasonlítással zártuk; itt ugyanazt a szerződést alkalmazzuk matematikai függvényre: legyen kézi invariáns, numerikus integrál, gradiensellenőrzés és Monte Carlo kontroll.
A Northstar kezdőprojekt rendelésszintű kérdése: a rendelés pillanatában becsülni a kézbesítési időt a távolságból. Ez az ellenőrző pont egy szándékosan mesterséges, zajmentes sokaságot használ:
Mielőtt bármit futtatnál, adj előzetes becslést: a modellcsalád tartalmazza a egyenest, ezért a minimum várható hiba , az optimum pedig . A paraméternél a veszteség tehát a kézi kontrollérték . Ezt az alábbi kódnak függetlenül vissza kell adnia.
A korábbi fejezetekből már ismertek a tömbök, az integrál, a derivált és a Monte Carlo átlag. Itt csak a kapcsolatukat írjuk fel egy veszteségfüggvényre.
A predikció vektoros alakban:
Egy megfigyelés hibája , a vesztesége pedig . A sokasági kockázat a sűrűséggel súlyozott integrál:
A négyzetet kifejtve:
A gradiens a két parciális derivált:
Az optimum a stacionárius pont: megoldása , , és mivel nemnegatív négyzetes kifejezés összege, ez globális minimum.
A shape-szerződés:
| Objektum | Alak | Egység / szerep |
|---|---|---|
| (2,) | jellemzővektor | |
| (2,) | nap, nap | |
| skalár | előrejelzett nap | |
| egy veszteség | skalár | nap² |
| skalár | nap² | |
| (2,) | nap / paraméterkomponens |
A Monte Carlo közelítés független mintát használ, értékkel:
A becslés standard hibája a mintabeli veszteségek szórásából:
A a Várható érték és Monte Carlo közelítés alfejezetből ismert tulajdonság: a Monte Carlo hiba tipikus nagysága a minta elemszámának négyzetgyökével csökken.
A gradiensellenőrzés a Meredekség és numerikus derivált numerikus deriváltját használja, de most komponensenként és kétoldali differenciával:
A következő szkript a notebooks/s048_risk_checkpoint.py
fájl tartalma. A kimeneteket a fenti képletekből számoltuk, ezért az itt
látható számok elméletileg várt, nem futtatott értékek.
Futtatás után a saját lab környezetedben válik ellenőrzött
kimenetté.
"""
s048_risk_checkpoint.py
III. ellenőrző pont: veszteségfüggvény teljes numerikus értelmezése.
A kimeneti kommentek a képletekből számított elméletileg várt értékek;
futtatott jegyzék nélkül nem ellenőrzött mérési eredmények.
"""
import numpy as np
from scipy.integrate import quad
from scipy.optimize import minimize
import matplotlib.pyplot as plt
rng = np.random.default_rng(20261020)
def risk_closed(w):
a, b = w
return a*a + a*b + b*b/3.0 - 7.0*a - 4.0*b + 13.0
def risk_quad(w):
a, b = w
return quad(lambda x: (2.0 + 3.0*x - a - b*x)**2, 0.0, 1.0)[0]
def grad_closed(w):
a, b = w
return np.array([2.0*a + b - 7.0, a + 2.0*b/3.0 - 4.0])
def numerical_gradient(fun, w, h=1e-6):
g = np.zeros_like(w, dtype=float)
for j in range(w.size):
e = np.zeros_like(w, dtype=float)
e[j] = 1.0
g[j] = (fun(w + h*e) - fun(w - h*e)) / (2.0*h)
return g
def monte_carlo_loss(w, rng, n):
x = rng.uniform(0.0, 1.0, n) # shape (n,)
y = 2.0 + 3.0*x # shape (n,) nap
losses = (y - w[0] - w[1]*x)**2 # shape (n,) nap^2
return losses.mean(), losses.std(ddof=1) / np.sqrt(n)
w00 = np.array([0.0, 0.0])
wopt = np.array([2.0, 3.0])
# Elméletileg várt: 13, 13.0, [-7. -4.], [-7.000000 -4.000000]
print("risk_closed(0,0) =", risk_closed(w00))
print("risk_quad(0,0) =", risk_quad(w00))
print("grad_closed(0,0) =", grad_closed(w00))
print("central grad =", numerical_gradient(risk_closed, w00))
# Elméletileg várt: True (1e-12 tolerancia mellett)
print("quad-zart egyezes =", abs(risk_closed(w00) - risk_quad(w00)) < 1e-12)
# Elméletileg várt: True (1e-6 abszolút és relatív tolerancia mellett)
print("gradiens-egyezes =",
np.allclose(numerical_gradient(risk_closed, w00),
grad_closed(w00), atol=1e-6, rtol=1e-6))
res = minimize(risk_closed, w00, jac=grad_closed, method="BFGS",
options={"gtol": 1e-10})
# Elméletileg várt: x = [2. 3.], fun = 0.0, success = True
print("BFGS x, fun, success =", res.x, res.fun, res.success)
n = 100_000
mean0, se0 = monte_carlo_loss(w00, rng, n)
# Elméletileg várt: mean0 ≈ 13, 2*se0 ≈ 0.039
print(f"MC at (0,0): {mean0:.4f} +/- {2*se0:.4f} (2 SE), populacios R=13")
meanp, sep = monte_carlo_loss(wopt, rng, n)
# Elméletileg várt: meanp = 0, sep = 0
print(f"MC at (2,3): {meanp:.4f} +/- {2*sep:.4f}")
# Ábra: R szintvonalai és az optimum
A = np.linspace(-1.0, 5.0, 200)
B = np.linspace(-2.0, 7.0, 200)
A, B = np.meshgrid(A, B)
Z = A*A + A*B + B*B/3.0 - 7.0*A - 4.0*B + 13.0
plt.contourf(A, B, Z, levels=20, cmap="viridis")
plt.colorbar(label="R(a,b) [nap^2]")
plt.plot([2.0], [3.0], "r*", markersize=12, label="optimum (2,3)")
plt.plot([0.0], [0.0], "wo", label="kézi kontroll (0,0)")
plt.xlabel("a (nap)")
plt.ylabel("b (nap / távolságegység)")
plt.title("III. ellenőrző pont: négyzetes veszteség")
plt.legend()
plt.tight_layout()
plt.savefig("s048_risk_contour.png", dpi=150)Futtatás a lab projekt gyökeréből:
# Linux/macOS, a könyvtár a lab projekt gyökere:
cd lab
uv run --locked python notebooks/s048_risk_checkpoint.py# Windows PowerShell, a könyvtár a lab projekt gyökere:
cd lab
uv run --locked python notebooks\s048_risk_checkpoint.pyA --locked kapcsoló a korábbi fejezetben készített
uv.lock egyezését ellenőrzi. Ha még nincs feloldott lock,
először uv lock, majd uv sync kell.
A kézi kontroll egyetlen számpárja:
.
A numerikus quad eredménynek
hibahatáron belül egyeznie kell vele, mert a zárt alak egzakt, a
quad pedig determinisztikus numerikus közelítés. A gradiens
kézi értéke
;
ezt a központi differencia
lépéssel
tolerancián belül közelíti.
A BFGS futás ugyanazt a jac gradiensfüggvényt kapja,
mint amit ellenőriztünk, ezért az optimum ellenőrzése Optimalizáló választás és konvergenciaellenőrzés
szellemében itt kétrétegű: a solver stacionárius pontot talál, és a
stacionárius pont a zárt gradiense nulla. A várt eredmény
,
.
A Monte Carlo kontrollnak nem az a célja, hogy „pontosan” eltalálja a 13-at; a 2 SE sáv mutatja a szimulációs bizonytalanságot. A jelen példában és a per-sample veszteség szórása ezért , és mellett . Ha a futásod sávon belül van, az a kontroll szempontjából elfogadható. A pontban minden egyes veszteség pontosan , ezért ott a MC szórása is ; ez nem statisztikai „bizonyítás”, hanem a számítás sajátossága.
A veszteségfüggvény optimalizálási sikere és a statisztikai prediktív érvényesség külön állítás. A szintetikus, zajmentes példa analitikus invariánsai a numerikus implementációt ellenőrzik; valós generalizációs következtetést nem igazolnak.
1. feladat — kézi értelmezés. Tekintsük a pontot a fenti veszteségfüggvényen.
2. feladat — implementálás és gradiensellenőrzés. Készíts függvényeket a fenti példához, majd:
seed=7 mellett a
és a
pontokban. A 2 SE sávot is írd ki.Milyen toleranciákat adsz meg, és miért?
3. feladat — hibadiagnózis. Egy kolléga az alábbi függvényt használja a Monte Carlo bizonytalanság becslésére:
def monte_carlo_se_bad(w, rng, n):
x = rng.uniform(0.0, 1.0, n)
y = 2.0 + 3.0*x
losses = (y - w[0] - w[1]*x) ** 2
return losses.mean(), losses.std() / n # figyelj a nevezőre!A kolléga mintánál a pontban ezt kapja: „átlag , 2 SE ”, és ebből arra következtet, hogy a sokasági veszteség pontosan lett beszorítva egy rendkívül szűk sávba.
4. feladat — megváltoztatott feltétel. Változtassuk meg a sokasági igaz kapcsolatot -re, miközben továbbra is .
seed=42 mellett a
és az optimum pontokban. Milyen elméletileg várt értékeket hasonlítasz
össze?1. megoldás.
; a hiba ; a veszteség .
. A zárt formula mellett .
. Az első komponens azt mondja, hogy kicsiny növelése csökkenti a veszteséget; a második hasonlóan csökkentést jelez növelésére. Ez konzisztens azzal, hogy , , tehát a jelenlegi pont az optimum alatt van.
, mert a pontban a predikció minden -re megegyezik az igazi értékkel.
2. megoldás.
A gradiensellenőrzés várt kimenete:
w12 = np.array([1.0, 2.0])
ng = numerical_gradient(risk_closed, w12, h=1e-5)
ag = grad_closed(w12)
# ng ≈ [-3.0, -1.6666667]; ag = [-3.0, -1.6666667]A np.allclose(ng, ag, atol=1e-6, rtol=1e-6) elvártan
True. A
tolerancia indoklása: a kétoldali differencia hibatagjai
és kerekítési hiba;
-nél
ez a jelen függvényskálán jóval a tolerancia alatt van.
A BFGS futás elvártan a
pontot adja vissza,
értékkel. A gtol=1e-10 a gradiensnormára vonatkozó
megállási feltétel; a stacionárius pont ellenőrzése tehát a megállási
ok, nem a kimeneti egyetlen szám.
A MC seed=7,
mellett elméletileg várt:
A bemeneteket a feladat mind megadja; a seedelt generátor reprodukálható, de numerikus könyvtárverziótól függő apró eltérés nem sérti a MC sávok stabilitását.
3. megoldás.
A kód losses.std() / n értékkel oszt, nem
np.sqrt(n) értékkel. Ezzel a bizonytalanságot
-szeresével
alulbecsli.
, mellett . A kolléga által kiírt hibasáv tehát irreálisan szűk; a valós MC bizonytalanság nagyságrendileg a 2 SE sávban.
Helyes függvény:
def monte_carlo_se_fixed(w, rng, n):
x = rng.uniform(0.0, 1.0, n)
y = 2.0 + 3.0*x
losses = (y - w[0] - w[1]*x) ** 2
return losses.mean(), losses.std(ddof=1) / np.sqrt(n)A SE sáv közelítőleg az ismételt MC futások 95%-ában tartalmazza a sokasági értéket; ez heurisztikus, a formális indoklást később a normális közelítés és a centrális határeloszlás adja. A sáv nem jelenti azt, hogy a sokasági érték a becsült átlagtól maximálisan ennyire van.
4. megoldás.
A gradiens:
A egyenletrendszer megoldása , , tehát . Mivel nemnegatív négyzetes forma, ez globális minimum, és .
Elméletileg várt kézi értékek:
A feladat ellenőrző invariantja tehát az kézi értéke, a gradiens komponensei és az optimum koordinátái.
„Ha egy ponton numerikusan egyezik a gradiens, akkor a gradiensfüggvény mindenütt rendben van.” A numerikus egyezés csak a vizsgált tartományra és toleranciára vonatkozik. A központi differencia pontossága a függvény nagyságától és a véges pontosságtól függ: a kerekítési hibakorlát nagyságrendileg , ahol .
Ellenpéldaként próbáld ki a pontot, ahol , a zárt gradiens
Ha valaki itt lépéssel ellenőriz, a kerekítési hibakorlát nagyobb lehet, mint a gradiens maga, ezért a központi differencia nem egyezik a zárt deriválttal a megszokott tolerancián belül. A javítás nem a gradiensképlet cseréje, hanem a skálázott, stabilabb ellenőrzés vagy az analitikus gradiens használata. Ugyanígy a Monte Carlo kontroll sem igazol „minden -re” semmit: egyetlen ponton mért átlag és SE csak azt a pontot és azt a generátorfeltételt ellenőrzi.
quad és a zárt formula egyezése teljesül-e
hibahatáron belül?A III. ellenőrző pont egyetlen veszteségfüggvényen zárta le a
matematikai eszköztárat. A négyzetes hiba sűrűséggel súlyozott
integrálként írható fel, zárt formulája és gradiense kézzel
ellenőrizhető. A scipy.integrate.quad, a központi
differencia, a BFGS és a seedelt Monte Carlo ugyanazt az optimumot
támasztja alá:
,
minimum
.
A numerikus egyezés azonban mindig csak a vizsgált pontra, tartományra
és toleranciára vonatkozik. A MC bizonytalanságot
-es
SE-vel kell becsülni. Következő lépésként a Sokaság,
minta és adatfelvételi folyamat a minta és az adatfelvétel fogalmát
vezeti be, ahol a sokasági
helyébe a mintából számolt átlag és annak bizonytalansága lép.