D’on surt una funció de pèrdua: versemblança, no convenció
Tres rectes traçades a ull sobre les mateixes vint mesures, i tres regles de puntuació que coronen tres guanyadores diferents.
En aquesta pàgina
La fulla que talla les peces es desgasta. Durant un torn de deu hores perd prou tall perquè les peces surtin de la cinta una fracció de mil·límetre més amples que al principi, i quan passen de 23,5 mil·límetres la inspecció les rebutja. Ningú de la planta sap quan passa això. El que tenen és un peu de rei, una llibreta i vint lectures del dimarts passat: les hores des que es va canviar la fulla i l’amplada de la peça mesurada en aquell moment.
Algú dibuixa una recta entre els punts. Algú altre en dibuixa una de lleugerament diferent. Una tercera persona en dibuixa una tercera. Totes tres semblen raonables sobre el paper, i discrepen en diverses hores sobre quan cal canviar la fulla: en aquesta planta, la diferència entre una setmana tranquil·la i un lot llençat.
Quina recta és millor?
Tal com està formulada, aquesta pregunta no té resposta. No una resposta difícil: cap resposta. «Millor» no és una propietat d’una recta com ho és el seu pendent; és una propietat d’una recta juntament amb una regla per puntuar rectes, i fins que algú no escrigui la regla no hi ha res a calcular. Aquest capítol es pren aquesta frase seriosament, i acaba amb el descobriment que la regla més comuna en machine learning no és una convenció sinó la conseqüència d’una afirmació sobre el món: una que pots posar a prova, i una que de vegades és falsa.
Una confessió abans de la primera línia de codi. Aquestes vint lectures no provenen d’una fàbrica real: les vaig generar a partir d’una recta que vaig triar, , més soroll aleatori amb una dispersió d’aproximadament una dècima de mil·límetre. Això importa, perquè tot el que segueix tracta de si un mètode recupera una veritat, i l’única manera de comprovar-ho és conèixer la veritat per endavant. Així doncs: 0,30 mil·límetres per hora és la resposta del final del llibre. No la pots fer servir, només comparar-t’hi.
Tres regles, tres guanyadores
Enllaç a la secció: Tres regles, tres guanyadoresAquí tens les lectures i les tres rectes, puntuades de tres maneres: error quadràtic, que és allò a què tothom recorre; error absolut, que podria triar un estadístic; i pitjor error, que triaria el maquinista, perquè a l’inspector no li importa la teva mitjana: rebutja la peça individual que queda fora de tolerància.
NumPy arriba aquí, un capítol després del perceptró en Python pur, per una raó: al final d’aquest capítol avaluarem quatre-centes mil rectes candidates contra vint lectures cadascuna, i un bucle de Python és l’eina equivocada per a això. També és la notació en què estan escrites totes les fonts citades més avall.
import numpy as np
# Hours since the blade was changed, and the width of the part measured then.
SHIFT = np.array([
(0.5, 20.17), (1.0, 20.28), (1.5, 20.53), (2.0, 20.61), (2.5, 20.69),
(3.0, 20.94), (3.5, 21.21), (4.0, 21.31), (4.5, 21.27), (5.0, 21.35),
(5.5, 21.58), (6.0, 21.80), (6.5, 21.67), (7.0, 22.07), (7.5, 22.10),
(8.0, 22.31), (8.5, 22.48), (9.0, 22.66), (9.5, 22.90), (10.0, 23.13),
])
h, y = SHIFT[:, 0], SHIFT[:, 1]
LINES = {"A": (20.10, 0.26), "B": (20.20, 0.28), "C": (20.30, 0.26)}
for name, (a, b) in LINES.items():
r = y - (a + b * h)
print(f"{name} mean square {np.mean(r**2):.5f}"
f" mean absolute {np.mean(np.abs(r)):.5f}"
f" worst {np.max(np.abs(r)):.3f}") La quantitat de les línies ressaltades és el residu: el que deia la recta menys el que deia el peu de rei, un nombre per lectura. Tota regla de puntuació d’aquest capítol, i tota loss function dels vint-i-vuit capítols posteriors, és alguna manera d’aixafar una llista de residus fins a convertir-la en un únic nombre. Només difereixen en com l’aixafen.
A mean square 0.02699 mean absolute 0.12600 worst 0.430
B mean square 0.02524 mean absolute 0.13700 worst 0.350
C mean square 0.03179 mean absolute 0.15000 worst 0.320Llegeix les columnes, no les files. L’error quadràtic diu B, l’error absolut diu A, el pitjor error diu C: tres regles, tres guanyadores, sobre els mateixos vint punts.
Vaig triar aquestes tres rectes perquè discrepassin, i ho he de dir clarament. La qüestió és com de fàcil va ser: uns minuts de cerca entre interceptes i pendents d’aspecte raonable produeixen centenars de triples així. El rànquing és una propietat de la regla que has triat, no un fet sobre les rectes, de manera que la regla no és un detall d’implementació: és la definició del problema. Això planteja la pregunta que aquest capítol existeix per respondre: amb quin criteri la tries?
Un paràmetre i una vall
Enllaç a la secció: Un paràmetre i una vallPrimer una qüestió més petita, perquè no hi ha tres rectes sinó infinites. Prenem per ara l’error quadràtic, ja que és el que tothom pren, i reduïm el problema a un sol nombre amb el truc que va estalviar al perceptró onze mil èpoques al capítol 1: restar la mitjana de totes dues columnes. Un cop el núvol de punts està centrat a l’origen, la millor recta sota error quadràtic passa exactament per l’origen; per tant, l’intercepte queda resolt i només resta triar el pendent.
u, v = h - h.mean(), y - y.mean() # 5.25 hours, 21.553 mm
def mse(theta):
return np.mean((v - theta * u) ** 2)
grid = np.arange(0.0, 0.6001, 0.001)
curve = np.array([mse(t) for t in grid])
print(grid.size, "candidates ->", f"theta={grid[curve.argmin()]:.3f}", f"mse={curve.min():.6f}")601 candidates -> theta=0.293 mse=0.010115Sis-cents un pendents candidats, un guanyador: 0,293 mil·límetres per hora contra una veritat de 0,300. Vint lectures sorolloses i un for-loop han arribat a menys d’una centèsima de mil·límetre per hora: un dos coma tres per cent.
La part interessant no és el guanyador, sinó la forma de la cerca. Imprimeix tota la corba, girada perquè la pèrdua vagi d’esquerra a dreta:
ts = np.arange(0.0, 0.6001, 0.04)
ls = np.array([mse(t) for t in ts])
for t, l in zip(ts, ls):
col = round(l / ls.max() * 50)
print(f"theta={t:.2f} |{' ' * col}*{' ' * (50 - col)}| mse={l:7.4f}")theta=0.00 | * | mse= 0.7244
theta=0.04 | * | mse= 0.5428
theta=0.08 | * | mse= 0.3878
theta=0.12 | * | mse= 0.2593
theta=0.16 | * | mse= 0.1575
theta=0.20 | * | mse= 0.0822
theta=0.24 | * | mse= 0.0336
theta=0.28 | * | mse= 0.0116
theta=0.32 | * | mse= 0.0161
theta=0.36 | * | mse= 0.0473
theta=0.40 | * | mse= 0.1050
theta=0.44 | * | mse= 0.1894
theta=0.48 | * | mse= 0.3004
theta=0.52 | * | mse= 0.4379
theta=0.56 | * | mse= 0.6021
theta=0.60 | *| mse= 0.7928Això és una vall, vista de costat. Té un únic fons, les parets pugen suaument a tots dos costats i —aquesta és la part que l’escala del capítol 1 no podia oferir— en cada punt hi ha una direcció ben definida de «baixada». Recorda aquesta forma. El capítol 3 tracta íntegrament de caminar-hi avall sense visitar els sis-cents un punts, i de què canvia quan una vall té més d’un fons.
Per què al quadrat, doncs?
Enllaç a la secció: Per què al quadrat, doncs?Tenim una vall perquè hem elevat al quadrat. L’error absolut li hauria donat un angle al fons; el pitjor error li hauria donat trams plans en què moure la recta no canviaria res. Elevar al quadrat és innegablement còmode, i la comoditat és aproximadament la raó que donen la majoria de cursos, disfressada de quatre maneres: fa positius els errors (el valor absolut també); penalitza més els errors grans (per què ho hauria de fer?); és diferenciable (la quarta potència també); és el que fa servir tothom (ho és, i això no és cap argument).
Aquesta és la posició honesta. L’error quadràtic ha seleccionat la recta B i l’error absolut ha seleccionat la recta A. Una d’aquestes és correcta per a aquesta fàbrica i l’altra és equivocada, i res del que s’ha dit fins ara no et pot dir quina. Per triar la regla has de saber alguna cosa sobre com les lectures han arribat a diferir de la recta, i això és una pregunta sobre el món, no sobre les matemàtiques. Respondre-la necessita una petita peça de maquinària.
La versemblança d’una recta
Enllaç a la secció: La versemblança d’una rectaAquesta és l’afirmació que converteix «quina recta és millor» en una pregunta amb resposta.
Suposa que l’amplada d’una peça és la recta més un error aleatori, i suposa que aquest error s’extreu d’una gaussiana —la corba de campana— amb mitjana zero i desviació estàndard :
La densitat de la gaussiana és
Ara fes una cosa que el perceptró no podia fer. Per a un pendent candidat donat , cada lectura té un residu, i la fórmula anterior converteix aquest residu en un nombre: com de plausible és un error exactament d’aquesta mida, si aquest pendent és la veritat? Una lectura sobre la recta obté un nombre gran; una lectura mig mil·límetre desviada, un de petit.
Les lectures són independents —el peu de rei no recorda l’última peça—, així que la regla del producte diu que la plausibilitat de la llibreta sencera és el producte de les densitats individuals. Aquest producte és la versemblança de .1 Fixa’t en la direcció, perquè és la direcció de què tracta la regla de Bayes: les dades són fixes i conegudes, i el que varia és el paràmetre. Això no és «la probabilitat del pendent». És la probabilitat que el model assigna a les dades que realment has obtingut, llegida com una funció del pendent.
SIGMA = 0.12
def gaussian(r, sigma):
return np.exp(-r ** 2 / (2 * sigma ** 2)) / (sigma * np.sqrt(2 * np.pi))
def likelihood(theta):
return np.prod(gaussian(v - theta * u, SIGMA))
for t in (0.25, 0.293, 0.35):
print(f"theta={t} likelihood = {likelihood(t):.6g}")theta=0.25 likelihood = 521.952
theta=0.293 likelihood = 2.42028e+07
theta=0.35 likelihood = 0.190312Un pendent de 0,293 fa aquesta llibreta quaranta-sis mil vegades més plausible que 0,25, i cent vint-i-set milions de vegades més plausible que 0,35. La màxima versemblança és el principi segons el qual tries el paràmetre que fa que allò que realment has observat sigui tan poc sorprenent com sigui possible. No és un teorema, sinó una proposta sobre què hauria de voler dir «millor»: una proposta amb contingut, perquè t’obliga a declarar la teva suposició sobre el soroll abans que se’t permeti puntuar res.
El producte es trenca
Enllaç a la secció: El producte es trencaExecuta les mateixes tres línies de codi sobre un mes de torns en lloc d’un de sol, i el mètode cau.
rng = np.random.default_rng(7)
u_big = rng.uniform(-5.25, 5.25, 2000) # 2000 readings, not 20
v_big = 0.30 * u_big + 0.12 * rng.standard_normal(2000)
print("2000 readings, sigma = 0.12 mm :", np.prod(gaussian(v_big - 0.30 * u_big, 0.12)))
noisy = 0.30 * u_big + 2.0 * rng.standard_normal(2000)
print("2000 readings, sigma = 2.00 mm :", np.prod(gaussian(noisy - 0.30 * u_big, 2.0)))
print("largest float64 :", np.finfo(np.float64).max)RuntimeWarning: overflow encountered in reduce
2000 readings, sigma = 0.12 mm : inf
2000 readings, sigma = 2.00 mm : 0.0
largest float64 : 1.7976931348623157e+308Dues mil multiplicacions i la resposta és inf. Canvia una constant —un peu de rei més barroer, de manera que les densitats surtin més petites que 1 en lloc de més grans— i el mateix codi retorna 0.0. Totes dues respostes són incorrectes, en direccions oposades, cap no llança una excepció que puguis capturar, i la segona ni tan sols imprimeix un avís.
No hi ha res malament en les matemàtiques. La versemblança amb aquests paràmetres és un nombre finit perfectament ben definit: el seu logaritme natural és 1400,91, de manera que el nombre mateix és aproximadament . El problema és que el teu ordinador no té aquest nombre, i val la pena entendre exactament quins nombres sí que té, perquè aquesta no serà l’última vegada que decidirà el resultat.
D’on ve el quadrat
Enllaç a la secció: D’on ve el quadratLa solució per al producte que explota és l’habitual: prendre logaritmes. El logaritme converteix productes en sumes, és estrictament creixent i per tant no pot moure la ubicació del màxim, i una suma de dos mil nombres moderats és una cosa que float64 gestiona sense queixar-se. Per convenció prenem el logaritme negatiu de la versemblança, de manera que millor vol dir més petit. Ara substitueix la densitat gaussiana i mira què passa.
-
Comença pel producte. La versemblança és , amb la densitat gaussiana anterior.
-
Pren-ne menys el logaritme. El producte es converteix en una suma, i l’exponencial de la densitat es cancel·la directament amb el logaritme:
- Llença tot el que no contingui . El primer terme és una constant. El davant de la suma és una constant positiva, i escalar una funció per una constant positiva no pot moure on és el seu mínim. El que queda és
que és la suma dels residus al quadrat: allò amb què havíem començat el capítol perquè era el primer que se li acut a qualsevol.
Aquest és el resultat pel qual existeix el capítol, i mereix ser enunciat sense matisos: l’error quadràtic no és una convenció. És el logaritme negatiu de la versemblança d’una gaussiana, amb les constants eliminades. Minimitzar l’error quadràtic és exactament el mateix acte que afirmar que els teus errors són gaussians i preguntar quin paràmetre fa les teves dades menys sorprenents. Feies aquesta afirmació des del principi; simplement no t’ho havien dit.
L’equivalència es pot comprovar, així que comprova-la: recorre els mateixos sis-cents un pendents amb el logaritme negatiu complet de la versemblança, constants incloses, i amb l’error quadràtic simple.
N = v.size
def nll(theta):
r = v - theta * u
return N * np.log(SIGMA * np.sqrt(2 * np.pi)) + np.sum(r ** 2) / (2 * SIGMA ** 2)
nlls = np.array([nll(t) for t in grid])
mses = np.array([mse(t) for t in grid])
print(f"argmin of the negative log-likelihood : theta={grid[nlls.argmin()]:.3f} nll={nlls.min():.6f}")
print(f"argmin of the mean squared error : theta={grid[mses.argmin()]:.3f} mse={mses.min():.6f}")
print("same index:", nlls.argmin() == mses.argmin())argmin of the negative log-likelihood : theta=0.293 nll=-17.001977
argmin of the mean squared error : theta=0.293 mse=0.010115
same index: TrueNombres diferents a l’eix vertical, i un d’ells és negatiu, cosa que una suma de quadrats no és mai: un logaritme negatiu de la versemblança pot baixar de zero, perquè una densitat pot superar 1. El mateix fons de la mateixa vall, fins a l’últim punt de la graella.
Mostra la deducció completa
Quins descartaments són segurs, exactament? La mateixa maniobra apareix en cada capítol que deriva una pèrdua, i no sempre és innocent.
Descartar una constant additiva és segur sempre que no depengui del paràmetre que estàs optimitzant, i descartar una constant multiplicativa positiva és segur perquè per a qualsevol . Totes dues coses fallen en el moment que també s’està ajustant: aleshores no és cap constant, és el terme que impedeix al model afirmar i plausibilitat infinita. Això és exactament la secció següent.
Tornen a fallar d’una altra manera al capítol 3: una constant multiplicativa no mou el mínim, però sí que escala el gradient, i el gradient es multiplica per la taxa d’aprenentatge. Dividir per per obtenir l’error quadràtic mitjà en lloc de la suma és invisible per a la resposta i molt visible per a l’entrenament: amb la suma, doblar la mida del batch dobla cada pas que fas.
Sigma tampoc és gratuïta
Enllaç a la secció: Sigma tampoc és gratuïtaHem fixat a 0,12 per decret, i ningú de la planta coneix la dispersió de l’error del seu peu de rei. Tracta-la com una segona incògnita i deixa que la màxima versemblança també la decideixi. Aquí el terme constant que acabem de descartar torna, perquè és l’única cosa que s’interposa entre el model i una afirmació de precisió perfecta.
r = v - 0.293 * u
sigmas = np.arange(0.01, 1.0001, 0.0001)
nll_sigma = N * np.log(sigmas * np.sqrt(2 * np.pi)) + np.sum(r ** 2) / (2 * sigmas ** 2)
print("best sigma on the grid :", round(float(sigmas[nll_sigma.argmin()]), 4))
print("sqrt(mean squared residual) :", round(float(np.sqrt(np.mean(r ** 2))), 4))best sigma on the grid : 0.1006
sqrt(mean squared residual) : 0.1006Les dues coincideixen fins a quatre decimals, i no per accident: derivar aquesta expressió i igualar-la a zero dona exactament. Així doncs, l’error quadràtic mitjà no és simplement com una variància. Sota aquest model és l’estimació de màxima versemblança de la variància del soroll: el nombre que has estat minimitzant tot aquest temps era una estimació de com de sorollós és el teu sensor.
Un matís, barat d’enunciar i car de redescobrir més endavant: aquesta estimació està esbiaixada a la baixa, perquè els residus s’han mesurat contra un ajust que ell mateix s’ha triat per fer-los petits. Simula-ho: dues-centes mil llibretes de vint lectures cadascuna, extretes d’una distribució la variància real de la qual és exactament 1, amb l’únic paràmetre de l’ajust estimat a partir de les lectures mateixes. Dividir la suma de quadrats per dona una mitjana de 0,9501; dividir-la per dona 1,0001; i és 0,95 clavat. Cada paràmetre que ajustes costa un grau de llibertat, i aquest és el cas visible més petit d’un problema molt més gran: un model sempre sembla millor sobre les dades amb què s’ha ajustat. El capítol 4 converteix això en la disciplina de reservar dades, i el capítol 6 dona nom a l’efecte.
Una pèrdua és una afirmació sobre el soroll
Enllaç a la secció: Una pèrdua és una afirmació sobre el sorollSi l’error quadràtic afirma que el soroll és gaussià, la següent pregunta és què passa quan l’afirmació és falsa. No lleugerament falsa: falsa de la manera com ho són les mesures reals.
Al taller, la majoria de lectures del peu de rei són bones fins a una dècima de mil·límetre, i una o dues vegades per torn un encenall queda sota la mordassa i la lectura s’equivoca de diversos mil·límetres. Errors així tenen cues pesades: petits la major part del temps, de tant en tant enormes, i enormes molt més sovint del que permet una corba de campana. La distribució de Cauchy és el model net estàndard d’aquest comportament, i la seva densitat és tan simple com la de la gaussiana:
La diferència és la cua: la gaussiana cau com , brutalment ràpid, i la Cauchy com , gairebé gens. La conseqüència és més fàcil de veure que de dir:
rng = np.random.default_rng(3)
g = 0.12 * rng.standard_normal(10 ** 6) # Gaussian noise
c = 0.12 * rng.standard_cauchy(10 ** 6) # Cauchy noise, same scale
for k in (10 ** 2, 10 ** 3, 10 ** 4, 10 ** 5, 10 ** 6):
print(f"{k:>9,} samples gaussian var {g[:k].var():.4f} cauchy var {c[:k].var():10.2f}") 100 samples gaussian var 0.0164 cauchy var 0.26
1,000 samples gaussian var 0.0146 cauchy var 59.88
10,000 samples gaussian var 0.0145 cauchy var 358.17
100,000 samples gaussian var 0.0144 cauchy var 3097.98
1,000,000 samples gaussian var 0.0144 cauchy var 32886.10La variància mostral de la gaussiana s’estabilitza en 0,0144, que és , i s’hi queda. La de la Cauchy puja, i continua pujant mentre continuïs mostrejant, perquè no hi ha res cap a què convergeixi: la distribució de Cauchy no té variància, ni tampoc mitjana. L’error quadràtic, que es dedica a minimitzar una mitjana de quadrats, està demanant una quantitat que no existeix.
Així que aquí tens un torn en què el peu de rei ha estat enganyat. Les mateixes vint hores, la mateixa fulla, el mateix desplaçament de 0,30 mil·límetres per hora: només que ara el soroll és de Cauchy. Ajusta-ho dues vegades: una minimitzant residus al quadrat, una minimitzant el logaritme negatiu de la versemblança del soroll que realment ha generat les dades. El truc de centrar no ajuda aquí —només fixa l’intercepte per a l’error quadràtic—, així que tots dos ajustos es fan per força bruta sobre una graella d’interceptes i pendents, ja que encara no tenim cap manera de trobar el fons d’una vall llevat de visitar-lo.
SWARF = np.array([
(0.5, 20.08), (1.0, 21.95), (1.5, 20.86), (2.0, 27.51), (2.5, 20.64),
(3.0, 20.75), (3.5, 21.01), (4.0, 21.03), (4.5, 21.37), (5.0, 20.60),
(5.5, 22.03), (6.0, 21.95), (6.5, 21.98), (7.0, 22.01), (7.5, 21.73),
(8.0, 22.97), (8.5, 22.60), (9.0, 22.66), (9.5, 22.44), (10.0, 22.78),
])
hs, ys = SWARF[:, 0], SWARF[:, 1]
A = np.arange(18.0, 22.001, 0.005) # 801 intercepts
B = np.arange(-0.20, 0.8001, 0.002) # 501 slopes
R = ys - (A[:, None, None] + B[None, :, None] * hs) # every line against every point
SCALE = 0.12
square = np.sum(R ** 2, axis=2) # least squares
cauchy = np.sum(np.log(1 + (R / SCALE) ** 2), axis=2) # Cauchy likelihood
for name, surface in (("least squares", square), ("Cauchy likelihood", cauchy)):
i, j = np.unravel_index(surface.argmin(), surface.shape)
print(f"{name:>18}: width = {A[i]:.3f} + {B[j]:.4f} * hours"
f" -> 23.5 mm at hour {(23.5 - A[i]) / B[j]:.2f}")
print(f"{'the truth':>18}: width = 20.000 + 0.3000 * hours"
f" -> 23.5 mm at hour {(23.5 - 20.0) / 0.30:.2f}")
print(f"{A.size * B.size:,} candidate lines evaluated")Les dues línies ressaltades són tota la diferència entre els ajustos. Pren el logaritme de la densitat de Cauchy, descarta les constants exactament com abans, i és el que sobreviu. Mateixa recepta, afirmació diferent sobre el soroll.
least squares: width = 21.380 + 0.1080 * hours -> 23.5 mm at hour 19.63
Cauchy likelihood: width = 19.935 + 0.3020 * hours -> 23.5 mm at hour 11.80
the truth: width = 20.000 + 0.3000 * hours -> 23.5 mm at hour 11.67
401,301 candidate lines evaluatedEls mínims quadrats informen d’un desplaçament de 0,108 mil·límetres per hora, aproximadament un terç de la taxa real, i conclouen que la fulla és bona fins a l’hora 19,6. La resposta real és l’hora 11,7. Actuant segons aquest ajust, la planta manté la premsa en marxa vuit hores extra fabricant peces fora de tolerància, sota l’autoritat de la loss function més estàndard del camp. L’ajust de Cauchy, amb les mateixes vint lectures, la mateixa graella i una sola línia de diferència en el codi, cau a l’hora 11,8.
Dues objeccions mereixen resposta, perquè totes dues són el primer que diu un bon enginyer.
El valor atípic és obvi: esborra’l. Pots fer-ho, i ajuda, però no n’hi ha prou. Esborrar l’única pitjor lectura mou el pendent de mínims quadrats de 0,108 a 0,239, cosa que encara situa el canvi de fulla a l’hora 13,1, una hora i mitja tard; esborrar la pitjor, tornar a ajustar i esborrar la que ara és pitjor et porta a 0,286, i fixa’t que això ja és un procediment, no una observació: esborra en canvi els dos residus més grans de l’ajust original i acabes a 0,223. Però ara has pres decisions de criteri que no pots escriure ni defensar, i automatitzar la regla no la rescata: «elimina el residu més gran i torna a ajustar», executat sobre mil torns simulats, té un error de pendent medià de 0,0177 contra el 0,0100 de l’ajust per versemblança, i s’equivoca en més de 0,05 en el 14,7% dels torns contra l’1,3%. L’eliminació és un pedaç sobre una suposició equivocada. La versemblança no necessita cap pedaç, perquè mai no ha suposat que el valor atípic fos impossible.
Has triat un conjunt de dades afortunat. Aquesta objecció és exactament correcta, i per això l’últim experiment simula mil torns independents i reajusta de totes dues maneres en cadascun.
A = np.arange(18.0, 22.001, 0.02) # a coarser grid: a thousand fits to do
B = np.arange(-0.20, 0.8001, 0.005)
lines = A[:, None, None] + B[None, :, None] * hs
rng = np.random.default_rng(2026)
err_sq, err_ca = [], []
for _ in range(1000): # 1000 independent shifts
ys = 20.00 + 0.30 * hs + SCALE * rng.standard_cauchy(hs.size)
R = ys - lines
_, j = np.unravel_index(np.sum(R ** 2, axis=2).argmin(), (A.size, B.size))
_, q = np.unravel_index(np.sum(np.log1p((R / SCALE) ** 2), axis=2).argmin(), (A.size, B.size))
err_sq.append(abs(B[j] - 0.30))
err_ca.append(abs(B[q] - 0.30))
err_sq, err_ca = np.array(err_sq), np.array(err_ca)
for name, e in (("least squares", err_sq), ("Cauchy likelihood", err_ca)):
print(f"{name:>18}: median slope error {np.median(e):.4f} mm/h"
f" off by more than 0.05 in {100 * np.mean(e > 0.05):4.1f}% of shifts"
f" worst {e.max():.3f}")
print(f"the likelihood fit is the closer of the two in {100 * np.mean(err_ca < err_sq):.1f}% of shifts") least squares: median slope error 0.0350 mm/h off by more than 0.05 in 40.4% of shifts worst 0.500
Cauchy likelihood: median slope error 0.0100 mm/h off by more than 0.05 in 1.3% of shifts worst 0.090
the likelihood fit is the closer of the two in 75.6% of shiftsMediana, no mitjana, pel mateix motiu que tot en aquesta secció: els errors de mínims quadrats estan impulsats per una Cauchy, de manera que la seva mitjana no és una cosa estable per informar. Els mínims quadrats s’equivoquen greument en dos torns de cada cinc; l’ajust per versemblança s’equivoca greument en un torn de cada setanta-set, i el seu pitjor fracàs en mil torns és inferior a una cinquena part del pitjor dels mínims quadrats.
Res d’això fa dolent l’error quadràtic. El fa específic, i l’aritmètica diu exactament per què. Pren un residu de 0,1 mm i un de 7 mm. Elevat al quadrat, la lectura dolenta contribueix 4.900 vegades més al total que la bona, de manera que la recta és arrossegada sencera cap a ella; sota el logaritme negatiu de la versemblança de Cauchy, els mateixos dos residus contribueixen 0,527 i 8,133, una ràtio de 15,4. La lectura dolenta encara compta, simplement no decideix. Aquest és el començament de l’estadística robusta, on la pèrdua de Huber de 1964 parteix la diferència comportant-se quadràticament per als residus petits i linealment per als grans,7 i on Tukey ja havia mostrat com de poca contaminació cal perquè la variància mostral sigui una eina pitjor que la desviació absoluta mitjana.8
Una nota històrica, massa bona per deixar-la fora. Els mínims quadrats es van publicar primer, per Legendre el 1805, com un dispositiu algebraic convenient sense cap justificació més enllà que funcionava.9 Quatre anys després Gauss va recórrer l’argument a l’inrevés: va donar per fet que la mitjana aritmètica és la manera correcta de combinar mesures repetides, va preguntar quina distribució d’errors fa que la mitjana sigui el valor més probable, i va demostrar que essencialment només n’hi ha una: la que ara porta el seu nom.10 La derivació d’aquest capítol és la seva, té més de dos segles, i encara és la part que la majoria de cursos deixen fora.
Què pots dir ara, i què encara no pots fer
Enllaç a la secció: Què pots dir ara, i què encara no pots ferGuanyat. Una loss function és una regla de puntuació, i el rànquing que produeix és una propietat de la regla, no dels candidats. Tota pèrdua d’aquest curs és el logaritme negatiu de la versemblança d’alguna suposició sobre el soroll, amb les constants llençades: la gaussiana dona error quadràtic aquí, Bernoulli dona entropia creuada al capítol 4, i una distribució categòrica sobre un vocabulari dona la pèrdua de next-token al capítol 8. La recepta no canvia mai: declara el soroll, escriu la versemblança, pren-ne menys el logaritme. I quan la suposició és equivocada el model no és només imprecís: és equivocat en una direcció que pots predir.
Encara falta. Hem trobat el fons de la vall visitant-hi cada punt. Això ha funcionat per a un paràmetre i sis-cents candidats, i ha sobreviscut a dos paràmetres amb 401.301 candidats en una cinquena part de segon. Tres paràmetres a la mateixa resolució són 201.051.801 candidats i ja no caben en un sol array; una xarxa petita del capítol 5 té milers de paràmetres, i els models als quals el capítol 10 posa preu en tenen milers de milions. La força bruta aquí no és lenta, és aritmèticament impossible, i res d’aquest capítol no suggereix cap alternativa.
Torna a mirar la vall, però. Dempeus a amb una pèrdua de 0,0822, la direcció de «baixada» no és cap misteri: la pots veure a la pàgina, la corba baixa cap a la dreta. Si poguessis preguntar a la loss function cap a quin costat fa pendent en el punt on ets, sense avaluar-la enlloc més, podries fer un pas en aquella direcció, preguntar de nou i repetir fins que el terra fos pla.
Aquesta pregunta té un nom. El pendent d’una funció en un punt és la seva derivada, i per a una funció de molts paràmetres la col·lecció de pendents en totes les direccions alhora és el gradient. El capítol 1 no en podia fer servir cap, perquè l’error del perceptró era una escala sense pendent sobre el qual preguntar. Aquest capítol ha construït una cosa millor: una pèrdua suau a tot arreu i que prové d’una suposició declarada, no d’una preferència.
Així que la pregunta per al capítol 3 ja no és si existeix un pendent. És com calcular-lo, per què moure’s en contra seu baixa en lloc de pujar —un signe que gairebé tots els cursos et demanen que acceptis per fe—, i quina distància cal recórrer abans de tornar a preguntar, que resulta ser l’únic nombre que decideix si un entrenament convergeix, oscil·la al voltant de la resposta per sempre o fuig cap a l’infinit.
Fonts i mètode
Enllaç a la secció: Fonts i mètodeTambé val la pena llegir, juntament amb aquest capítol: Prince, Understanding Deep Learning §5.1–5.2 i apèndix C, que construeix totes les pèrdues del llibre a partir de la màxima versemblança en l’ordre emprat aquí; Goodfellow, Bengio i Courville, Deep Learning §3.1–3.11 i §5.5, la secció de màxima versemblança dels quals també deriva la divergència KL que necessita el capítol 4; Murphy, Probabilistic Machine Learning: An Introduction capítol 2 i §4.2, sobre què garanteix i què no garanteix la màxima versemblança; Deisenroth, Faisal i Ong, Mathematics for Machine Learning §6.1–6.4 per a la regla de la suma, la regla del producte i la regla de Bayes fetes com cal; la nota breu de Tom Mitchell per a la CMU Estimating Probabilities: MLE and MAP (2016); i §22.7 de Dive into Deep Learning, que arriba al mateix resultat en codi executable.
Referències
Enllaç a la secció: Referències-
Fisher, R. A. On the mathematical foundations of theoretical statistics. Philosophical Transactions of the Royal Society A 222, pp. 309–368 (1922). On la versemblança s’estableix com a mètode general, juntament amb «parameter», «statistic», suficiència i eficiència. El nom mateix, i la separació respecte de la probabilitat, és d’un any abans: Fisher, R. A., On the “probable error” of a coefficient of correlation deduced from a small sample, Metron 1, pp. 3–32 (1921), pp. 24–25. ↩
-
IEEE Standard for Floating-Point Arithmetic, IEEE 754-2019. Defineix binary32 i binary16, i les regles d’arrodoniment que fan que l’experiment de suma surti com surt. ↩
-
Kalamkar, D. et al. A Study of BFLOAT16 for Deep Learning Training. arXiv:1905.12322 (2019). Els paràmetres del format, i el cas a favor d’intercanviar bits de mantissa per bits d’exponent. ↩
-
Micikevicius, P. et al. Mixed Precision Training. ICLR 2018, arXiv:1710.03740. L’escalat de la pèrdua, i les magnituds de gradient mesurades que el fan necessari en float16. ↩
-
Goldberg, D. What Every Computer Scientist Should Know About Floating-Point Arithmetic. ACM Computing Surveys 23(1), pp. 5–48 (1991). Encara és la millor explicació única de per què els dos ordres de suma discrepen. ↩
-
Kahan, W. Pracniques: further remarks on reducing truncation errors. Communications of the ACM 8(1), p. 40 (1965). Suma compensada en mitja pàgina. ↩
-
Huber, P. J. Robust estimation of a location parameter. The Annals of Mathematical Statistics 35(1), pp. 73–101 (1964). La pèrdua que és quadràtica prop de zero i lineal a les cues, derivada en lloc de pedaçada. ↩
-
Tukey, J. W. A survey of sampling from contaminated distributions, a Contributions to Probability and Statistics (Stanford University Press, 1960), pp. 448–485. ↩
-
Legendre, A. M. Nouvelles méthodes pour la détermination des orbites des comètes (París, 1805), apèndix Sur la méthode des moindres quarrés. La primera publicació dels mínims quadrats, com a dispositiu computacional. ↩
-
Gauss, C. F. Theoria Motus Corporum Coelestium (Hamburg, 1809), llibre II, §§175–179. L’argument de la mitjana aritmètica a la llei d’errors normal, i d’aquí als mínims quadrats. ↩