De onde vén unha función de perda: verosimilitude, non convención
Tres rectas sobre as mesmas vinte medidas e tres regras que dan tres gañadoras distintas. O erro cadrático é unha elección.
Nesta páxina
A coitela que corta as pezas desgástase. Ao longo dunha quenda de dez horas perde fío dabondo para que as pezas saian da cinta unhas décimas de milímetro máis anchas que ao comezo, e cando pasan de 23,5 milímetros a inspección rexéitaas. Ninguén na planta sabe cando acontece iso. O que teñen é un calibre, un caderno e vinte lecturas do martes pasado: as horas desde que se cambiou a coitela e a anchura da peza medida nese intre.
Alguén debuxa unha recta a través dos puntos. Outra persoa debuxa unha lixeiramente distinta. Unha terceira debuxa unha terceira. As tres parecen razoables no papel, e discrepan en varias horas sobre cando cambiar a coitela; nesta planta, a diferenza entre unha semana tranquila e un lote estragado.
Que recta é mellor?
Tal como está formulada, esa pregunta non ten resposta. Non unha resposta difícil: ningunha resposta en absoluto. «Mellor» non é unha propiedade dunha recta como o é a súa pendente; é unha propiedade dunha recta xunto cunha regra para puntuar rectas, e ata que alguén escriba a regra non hai nada que calcular. Este capítulo toma esa frase en serio, e remata co descubrimento de que a regra máis habitual en machine learning non é unha convención senón a consecuencia dunha afirmación sobre o mundo: unha que podes poñer a proba, e unha que ás veces é falsa.
Unha confesión antes da primeira liña de código. Estas vinte lecturas non veñen dunha fábrica real: xereinas a partir dunha recta que escollín, , máis ruído aleatorio cunha dispersión duns dez centésimos de milímetro. Iso importa, porque todo o que segue trata de se un método recupera unha verdade, e a única forma de comprobalo é coñecer a verdade de antemán. Así que: 0,30 milímetros por hora é a resposta ao final do libro. Non tes permiso para usala, só para contrastar con ela.
Tres regras, tres gañadoras
Ligazón á sección: Tres regras, tres gañadorasAquí están as lecturas e as tres rectas, puntuadas de tres formas: erro cadrático, ao que todo o mundo recorre; erro absoluto, ao que podería recorrer unha estatística; e peor erro, ao que recorrería a maquinista, porque ao inspector non lle importa a túa media: rexeita a única peza que está fóra de tolerancia.
NumPy chega aquí, un capítulo despois do perceptrón en Python puro, por unha razón: ao final deste capítulo avaliamos catrocentas mil rectas candidatas contra vinte lecturas cada unha, e un bucle de Python é a ferramenta incorrecta para iso. Tamén é a notación na que está escrita cada fonte citada máis abaixo.
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}") A cantidade nas liñas destacadas é o residual: o que dicía a recta menos o que dicía o calibre, un número por lectura. Cada regra de puntuación deste capítulo, e cada función de perda dos vinte e oito capítulos posteriores, é algunha maneira de esmagar unha lista de residuais ata convertela nun único número. Só difiren en como esmagan.
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.320Le as columnas, non as filas. O erro cadrático di B, o erro absoluto di A, o peor erro di C: tres regras, tres gañadoras, nos mesmos vinte puntos.
Escollín estas tres rectas para que discrepasen, e convén dicilo sen rodeos. O punto é o doado que foi: uns minutos buscando entre interceptos e pendentes de aspecto razoable dan centos de tríos así. A clasificación é unha propiedade da regra que escolliches, non un feito sobre as rectas, así que a regra non é un detalle de implementación: é a definición do problema. O que suscita a pregunta que este capítulo existe para responder: con que fundamento a escolles?
Un parámetro, e un val
Ligazón á sección: Un parámetro, e un valPrimeiro unha cuestión máis pequena, porque non hai tres rectas senón infinitas. Toma por agora o erro cadrático, xa que é o que toma todo o mundo, e reduce o problema a un só número usando o truco que lle aforrou ao perceptrón once mil épocas no Capítulo 1: restar a media das dúas columnas. Unha vez que a nube de puntos está centrada na orixe, a mellor recta baixo erro cadrático pasa exactamente pola orixe; así que o intercepto queda resolto e só resta escoller a pendente.
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.010115Seiscentas unha pendentes candidatas, unha gañadora: 0,293 milímetros por hora fronte a unha verdade de 0,300. Vinte lecturas con ruído e un for-loop chegaron a unha centésima de milímetro por hora: dous coma tres por cento.
A parte interesante non é a gañadora senón a forma da busca. Imprime a curva enteira, xirada para que a perda vaia de esquerda a dereita:
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.7928Iso é un val, visto de lado. Ten un único fondo, as paredes soben suavemente a ambos lados e —esta é a parte que a escaleira do Capítulo 1 non podía ofrecer— en cada punto hai unha dirección de «baixada» ben definida. Lembra esa forma. O Capítulo 3 trata por completo de baixar por ela sen visitar os seiscentos un puntos, e do que cambia cando un val ten máis dun fondo.
Entón por que cadrático?
Ligazón á sección: Entón por que cadrático?Temos un val porque elevamos ao cadrado. O erro absoluto teríalle dado unha aresta no fondo; o peor erro teríalle dado tramos planos nos que mover a recta non cambia absolutamente nada. Elevar ao cadrado é innegablemente conveniente, e a conveniencia é máis ou menos a razón que dan a maioría dos cursos, vestida de catro xeitos: fai que os erros sexan positivos (tamén o fai o valor absoluto); castiga máis os erros grandes (por que debería?); é diferenciable (tamén o é a cuarta potencia); é o que usa todo o mundo (é certo, e iso non é un argumento).
Esta é a posición honesta. O erro cadrático seleccionou a recta B e o erro absoluto seleccionou a recta A. Unha delas é correcta para esta fábrica e a outra é incorrecta, e nada do dito ata agora pode dicirche cal. Para escoller a regra necesitas saber algo sobre como as lecturas chegaron a diferir da recta, e iso é unha pregunta sobre o mundo, non sobre as matemáticas. Respondela require unha pequena peza de maquinaria.
A verosimilitude dunha recta
Ligazón á sección: A verosimilitude dunha rectaEsta é a afirmación que converte «que recta é mellor» nunha pregunta con resposta.
Supón que a anchura dunha peza é a recta máis un erro aleatorio, e supón que ese erro se extrae dunha gaussiana —a curva de campá— con media cero e desviación típica :
A densidade da gaussiana é
Agora fai algo que o perceptrón non podía facer. Para unha pendente candidata dada , cada lectura ten un residual, e a fórmula de arriba transforma ese residual nun número: que plausible é un erro exactamente dese tamaño, se esta pendente é a verdade? Unha lectura sobre a recta recibe un número grande; unha lectura a medio milímetro, un pequeno.
As lecturas son independentes —o calibre non lembra a última peza—, así que a regra do produto di que a plausibilidade do caderno enteiro é o produto das densidades individuais. Ese produto é a verosimilitude de .1 Repara na dirección, porque é a dirección da que trata a regra de Bayes: os datos son fixos e coñecidos, e o que varía é o parámetro. Isto non é «a probabilidade da pendente». É a probabilidade que o modelo asigna aos datos que realmente obtiveches, lida como función da pendente.
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.190312Unha pendente de 0,293 fai este caderno corenta e seis mil veces máis plausible ca 0,25, e cento vinte e sete millóns de veces máis plausible ca 0,35. A máxima verosimilitude é o principio de escoller o parámetro que fai que o que realmente observaches sexa o menos sorprendente posible. Non é un teorema senón unha proposta sobre o que debería significar «mellor»: unha proposta con contido, porque obrígate a declarar a túa suposición sobre o ruído antes de que se che permita puntuar nada.
O produto rompe
Ligazón á sección: O produto rompeExecuta as mesmas tres liñas de código nun mes de quendas no canto dunha, e o método cae.
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+308Dúas mil multiplicacións e a resposta é inf. Cambia unha constante —un calibre menos fino, de modo que as densidades saian menores ca 1 no canto de maiores— e o mesmo código devolve 0.0. As dúas respostas son incorrectas, en direccións opostas; ningunha lanza unha excepción que poidas capturar, e a segunda nin sequera imprime unha advertencia.
Non hai nada incorrecto nas matemáticas. A verosimilitude nesas configuracións é un número finito perfectamente ben definido: o seu logaritmo natural é 1400,91, así que o número en si é arredor de . O problema é que o teu ordenador non ten ese número, e paga a pena entender exactamente que números si ten, porque esta non será a última vez que decida o resultado.
De onde vén o cadrado
Ligazón á sección: De onde vén o cadradoA solución para o produto que estoupa é a habitual: tomar logaritmos. O logaritmo converte produtos en sumas, é estritamente crecente así que non pode mover a localización do máximo, e unha suma de dous mil números moderados é algo que float64 manexa sen protestar. Por convención tomamos a log-verosimilitude negativa, para que mellor signifique máis pequeno. Agora substitúe a densidade gaussiana e mira que acontece.
-
Comeza polo produto. A verosimilitude é , con a densidade gaussiana de arriba.
-
Toma menos o logaritmo. O produto convértese nunha suma, e a exponencial da densidade cancélase directamente co logaritmo:
- Tira todo o que non conteña . O primeiro termo é unha constante. O diante da suma é unha constante positiva, e escalar unha función por unha constante positiva non pode mover onde está o seu mínimo. O que queda é
que é a suma dos residuais cadráticos: a cousa coa que comezamos o capítulo porque era o primeiro que se lle ocorre a calquera.
Ese é o resultado para o que existe o capítulo, e merece enunciarse sen matices: o erro cadrático non é unha convención. É a log-verosimilitude negativa dunha gaussiana, coas constantes eliminadas. Minimizar o erro cadrático é exactamente o mesmo acto ca afirmar que os teus erros son gaussianos e preguntar que parámetro fai que os teus datos sexan menos sorprendentes. Estabas a facer esa afirmación todo o tempo; simplemente non cho dicían.
A equivalencia pódese comprobar, así que compróbaa: percorre as mesmas seiscentas unha pendentes coa log-verosimilitude negativa completa, constantes incluídas, e co erro cadrático 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: TrueNúmeros distintos no eixe vertical, e un deles é negativo, cousa que unha suma de cadrados nunca é: unha log-verosimilitude negativa pode baixar de cero, porque unha densidade pode superar 1. O mesmo fondo do mesmo val, ata o último punto da grella.
Mostrar a derivación completa
Que descartes son seguros, exactamente? A mesma manobra aparece en cada capítulo que deriva unha perda, e non sempre é inocente.
Eliminar unha constante aditiva é seguro sempre que non dependa do parámetro que estás a optimizar, e eliminar unha constante multiplicativa positiva é seguro porque para calquera . As dúas cousas fallan no momento en que tamén se está axustando: entón non é unha constante en absoluto, é o termo que impide que o modelo afirme e plausibilidade infinita. Iso é exactamente a seguinte sección.
Volven fallar dun xeito distinto no Capítulo 3: unha constante multiplicativa non move o mínimo, pero si escala o gradiente, e o gradiente multiplícase pola taxa de aprendizaxe. Dividir por para obter o erro cadrático medio no canto da suma é invisible para a resposta e moi visible para a execución do adestramento: coa suma, duplicar o tamaño do teu lote duplica cada paso que das.
Sigma tampouco é gratis
Ligazón á sección: Sigma tampouco é gratisFixamos en 0,12 por decreto, e ninguén na planta coñece a dispersión do erro do seu calibre. Trátaa como unha segunda incógnita e deixa que a máxima verosimilitude a decida tamén. Aquí volve o termo constante que acabamos de descartar, porque é o único que se interpón entre o modelo e unha afirmación de precisión 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.1006As dúas coinciden ata catro decimais, e non por accidente: derivar esa expresión e igualala a cero dá exactamente. Así que o erro cadrático medio non é simplemente semellante a unha varianza. Baixo este modelo é a estimación de máxima verosimilitude da varianza do ruído: o número que estiveches minimizando todo o tempo era unha estimación de canto ruído ten o teu sensor.
Unha engurra, barata de enunciar e cara de redescubrir máis tarde: esa estimación está sesgada á baixa, porque os residuais medíronse contra un axuste que foi escollido precisamente para facelos pequenos. Simúlao: douscentos mil cadernos de vinte lecturas cada un, extraídas dunha distribución cuxa varianza verdadeira é exactamente 1, cun único parámetro do axuste estimado a partir das propias lecturas. Dividir a suma de cadrados por dá unha media de 0,9501; dividila por dá 1,0001; e é 0,95 cravado. Cada parámetro que axustas custa un grao de liberdade, e esta é a instancia visible máis pequena dun problema moito maior: un modelo sempre parece mellor nos datos aos que foi axustado. O Capítulo 4 convérteo na disciplina de reservar datos, e o Capítulo 6 dálle nome ao efecto.
Unha perda é unha afirmación sobre o ruído
Ligazón á sección: Unha perda é unha afirmación sobre o ruídoSe o erro cadrático afirma que o ruído é gaussiano, a seguinte pregunta é que pasa cando a afirmación é falsa. Non lixeiramente falsa: falsa como o son as medicións reais.
No chan da fábrica, a maioría das lecturas do calibre son boas ata unha décima de milímetro, e unha ou dúas veces por quenda unha labra de limalla métese baixo a mordaza e a lectura desvíase varios milímetros. Erros así son de cola pesada: pequenos a maior parte do tempo, ocasionalmente enormes, e enormes moito máis a miúdo do que permite unha curva de campá. A distribución de Cauchy é o modelo limpo estándar dese comportamento, e a súa densidade é tan simple como a da gaussiana:
A diferenza está na cola: a gaussiana cae como , brutalmente rápido, e a de Cauchy como , case nada. A consecuencia é máis doada de ver ca de dicir:
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.10A varianza mostral da gaussiana estabilízase en 0,0144, que é , e queda aí. A da Cauchy sobe, e segue subindo mentres sigas a tomar mostras, porque non hai nada ao que converxer: a distribución de Cauchy non ten varianza, nin tampouco media. Ao erro cadrático, cuxo traballo enteiro é minimizar unha media de cadrados, estáselle pedindo unha cantidade que non existe.
Así que aquí tes unha quenda na que o calibre foi enganado. As mesmas vinte horas, a mesma coitela, a mesma deriva de 0,30 milímetros por hora; só que o ruído agora é Cauchy. Axústaa dúas veces: unha minimizando residuais cadráticos, outra minimizando a log-verosimilitude negativa do ruído que realmente xerou os datos. O truco de centrar non axuda aquí —só fixa o intercepto para o erro cadrático—, así que ambos axustes fanse por forza bruta sobre unha grella de interceptos e pendentes, xa que seguimos sen ter xeito de atopar o fondo dun val agás visitándoo.
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")As dúas liñas destacadas son toda a diferenza entre os axustes. Toma o logaritmo da densidade de Cauchy, descarta as constantes exactamente como antes, e é o que sobrevive. A mesma receita, unha afirmación distinta sobre o ruído.
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 evaluatedOs mínimos cadrados informan dunha deriva de 0,108 milímetros por hora, arredor dun terzo da taxa real, e conclúen que a coitela é boa ata a hora 19,6. A resposta verdadeira é a hora 11,7. Actuando sobre ese axuste, a planta mantén a prensa funcionando oito horas extra facendo pezas fóra de tolerancia, baixo a autoridade da función de perda máis estándar do campo. O axuste de Cauchy, usando as mesmas vinte lecturas, a mesma grella e unha diferenza dunha soa liña no código, cae na hora 11,8.
Dúas obxeccións merecen resposta, porque ambas son o primeiro que di unha boa enxeñeira.
O outlier é obvio: simplemente elimínao. Podes facelo, e axuda, pero non abonda. Eliminar a única peor lectura move a pendente de mínimos cadrados de 0,108 a 0,239, o que aínda pon o cambio de coitela na hora 13,1, hora e media tarde; eliminar a peor, volver axustar e eliminar a que sexa peor agora lévate a 0,286 —e repara en que isto xa é un procedemento, non unha observación: elimina no seu lugar os dous maiores residuais do axuste orixinal e acabas en 0,223. Pero agora fixeches xuízos que non podes escribir nin defender, e automatizar a regra non a rescata: eliminar-o-maior-residual-e-logo-reaxustar, executado sobre mil quendas simuladas, ten un erro mediano de pendente de 0,0177 fronte ao 0,0100 do axuste por verosimilitude, e desvíase máis de 0,05 no 14,7% das quendas fronte ao 1,3%. A eliminación é un parche sobre unha suposición incorrecta. A verosimilitude non precisa parche, porque nunca supuxo que o outlier fose imposible.
Escolliches un conxunto de datos con sorte. Esa obxección é exactamente correcta, por iso o último experimento simula mil quendas independentes e volve axustar das dúas maneiras en cada unha.
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, non media, pola mesma razón ca todo nesta sección: os erros de mínimos cadrados están impulsados por unha Cauchy, así que a súa media non é algo estable que informar. Os mínimos cadrados equivócanse gravemente en dúas quendas de cada cinco; o axuste por verosimilitude equivócase gravemente nunha de cada setenta e sete, e o seu peor fallo en mil quendas é menos dunha quinta parte do peor dos mínimos cadrados.
Nada disto fai malo o erro cadrático. Faino específico, e a aritmética di exactamente por que. Toma un residual de 0,1 mm e un de 7 mm. Elevado ao cadrado, a mala lectura contribúe 4.900 veces máis ao total ca a boa, así que a recta é arrastrada enteira cara a ela; baixo a log-verosimilitude de Cauchy, os mesmos dous residuais contribúen 0,527 e 8,133, unha razón de 15,4. A mala lectura segue contando, simplemente non lle deixas decidir. Este é o comezo da estatística robusta, onde a perda de Huber de 1964 divide a diferenza comportándose de maneira cuadrática para residuais pequenos e lineal para grandes,7 e onde Tukey xa amosara que pouca contaminación fai falta para que a varianza mostral sexa unha ferramenta peor ca a desviación absoluta media.8
Unha nota histórica, demasiado boa para deixala fóra. Os mínimos cadrados publicounos primeiro Legendre en 1805, como un dispositivo alxébrico conveniente sen máis xustificación ca que funcionaba.9 Catro anos despois Gauss fixo o argumento ao revés: deu por feito que a media aritmética é a forma correcta de combinar medicións repetidas, preguntou que distribución de erro fai que a media sexa o valor máis probable, e mostrou que esencialmente só unha o fai: a que agora leva o seu nome.10 A derivación deste capítulo é a súa, ten máis de dous séculos, e segue sendo a parte que a maioría dos cursos deixan fóra.
O que agora podes dicir, e o que aínda non podes facer
Ligazón á sección: O que agora podes dicir, e o que aínda non podes facerGañado. Unha función de perda é unha regra de puntuación, e a clasificación que produce é unha propiedade da regra, non das candidatas. Cada perda deste curso é a log-verosimilitude negativa dalgunha suposición sobre o ruído, coas constantes tiradas fóra: a gaussiana dá erro cadrático aquí, Bernoulli dá entropía cruzada no Capítulo 4, e unha distribución categórica sobre un vocabulario dá a perda de next-token no Capítulo 8. A receita nunca cambia: declara o ruído, escribe a verosimilitude, toma menos o logaritmo. E cando a suposición é incorrecta o modelo non é simplemente impreciso: é incorrecto nunha dirección que podes predicir.
Aínda falta. Atopamos o fondo do val visitando cada punto nel. Iso funcionou para un parámetro e seiscentas candidatas, e sobreviviu a dous parámetros con 401.301 candidatas nun quinto de segundo. Tres parámetros coa mesma resolución son 201.051.801 candidatas e xa non caben nun único array; unha rede pequena no Capítulo 5 ten miles de parámetros, e os modelos aos que o Capítulo 10 pon prezo teñen miles de millóns. A forza bruta aquí non é lenta: é aritmeticamente imposible, e nada neste capítulo suxire unha alternativa.
Mira outra vez o val, porén. De pé en cunha perda de 0,0822, a dirección da «baixada» non é ningún misterio: podes vela na páxina, a curva baixa cara á dereita. Se puideses preguntarlle á función de perda cara a onde se inclina no punto no que estás, sen avaliala en ningún outro sitio, poderías dar un paso nesa dirección, volver preguntar e repetir ata que o chan fose plano.
Esa pregunta ten nome. A pendente dunha función nun punto é a súa derivada, e para unha función de moitos parámetros a colección de pendentes en todas as direccións á vez é o gradiente. O Capítulo 1 non podía usar un, porque o erro do perceptrón era unha escaleira sen pendente pola que preguntar. Este capítulo construíu algo mellor: unha perda suave en todas partes e que veu dunha suposición declarada, non dunha preferencia.
Así que a pregunta para o Capítulo 3 xa non é se existe unha pendente. É como calculala, por que moverse contra ela vai costa abaixo no canto de costa arriba —un signo que case todos os cursos che piden aceptar por fe— e que distancia avanzar antes de volver preguntar, que resulta ser o único número que decide se unha execución de adestramento converxe, oscila arredor da resposta para sempre ou foxe ata o infinito.
Fontes e método
Ligazón á sección: Fontes e métodoTamén paga a pena ler xunto con este capítulo: Prince, Understanding Deep Learning §5.1–5.2 e Apéndice C, que constrúe cada perda do libro a partir da máxima verosimilitude na orde usada aquí; Goodfellow, Bengio e Courville, Deep Learning §3.1–3.11 e §5.5, cuxa sección de máxima verosimilitude tamén deriva a diverxencia KL que necesita o Capítulo 4; Murphy, Probabilistic Machine Learning: An Introduction capítulo 2 e §4.2, sobre o que a máxima verosimilitude garante e non garante; Deisenroth, Faisal e Ong, Mathematics for Machine Learning §6.1–6.4 para a regra da suma, a regra do produto e a regra de Bayes feitas con rigor; a breve nota da CMU de Tom Mitchell Estimating Probabilities: MLE and MAP (2016); e §22.7 de Dive into Deep Learning, que chega ao mesmo resultado en código executable.
Referencias
Ligazón á sección: Referencias-
Fisher, R. A. On the mathematical foundations of theoretical statistics. Philosophical Transactions of the Royal Society A 222, pp. 309–368 (1922). Onde a verosimilitude se presenta como método xeral, xunto con «parámetro», «estatístico», suficiencia e eficiencia. O propio nome, e a separación respecto da probabilidade, é dun ano antes: 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. Define binary32 e binary16, e as regras de redondeo que fan que o experimento de suma saia como sae. ↩
-
Kalamkar, D. et al. A Study of BFLOAT16 for Deep Learning Training. arXiv:1905.12322 (2019). Os parámetros do formato, e o caso a favor de trocar bits de mantisa por bits de expoñente. ↩
-
Micikevicius, P. et al. Mixed Precision Training. ICLR 2018, arXiv:1710.03740. O escalado da perda, e as magnitudes de gradiente medidas que o fan necesario en float16. ↩
-
Goldberg, D. What Every Computer Scientist Should Know About Floating-Point Arithmetic. ACM Computing Surveys 23(1), pp. 5–48 (1991). Segue sendo a mellor explicación única de por que as dúas ordes de suma discrepan. ↩
-
Kahan, W. Pracniques: further remarks on reducing truncation errors. Communications of the ACM 8(1), p. 40 (1965). Suma compensada en media páxina. ↩
-
Huber, P. J. Robust estimation of a location parameter. The Annals of Mathematical Statistics 35(1), pp. 73–101 (1964). A perda que é cuadrática preto de cero e lineal nas colas, derivada no canto de remendada. ↩
-
Tukey, J. W. A survey of sampling from contaminated distributions, en 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éndice Sur la méthode des moindres quarrés. A primeira publicación dos mínimos cadrados, como dispositivo computacional. ↩
-
Gauss, C. F. Theoria Motus Corporum Coelestium (Hamburg, 1809), Libro II, §§175–179. O argumento desde a media aritmética ata a lei normal do erro, e de aí aos mínimos cadrados. ↩