Dari Mana Loss Function Berasal: Likelihood, Bukan Konvensi
Tiga garis pada 20 pengukuran yang sama, tiga aturan skor, tiga pemenang. Squared error adalah pilihan tentang noise.
Di halaman ini
Mata pisau yang memotong komponen itu aus. Selama shift sepuluh jam, ketajamannya cukup berkurang sehingga komponen yang keluar dari ban berjalan menjadi sepersekian milimeter lebih lebar daripada saat mulai, dan begitu melewati 23,5 milimeter, inspeksi menolaknya. Tidak ada seorang pun di pabrik yang tahu kapan itu terjadi. Yang mereka punya adalah jangka sorong, buku catatan, dan dua puluh pembacaan dari Selasa lalu: jumlah jam sejak mata pisau diganti, dan lebar komponen yang diukur pada saat itu.
Seseorang menggambar garis melalui titik-titiknya. Orang lain menggambar garis yang sedikit berbeda. Orang ketiga menggambar garis ketiga. Ketiganya terlihat masuk akal di kertas, dan ketiganya berbeda pendapat tentang kapan mata pisau harus diganti hingga beberapa jam — di pabrik ini, selisih antara minggu yang tenang dan satu batch yang harus dibuang.
Garis mana yang lebih baik?
Seperti dinyatakan, pertanyaan itu tidak punya jawaban. Bukan jawaban yang sulit — benar-benar tidak ada jawaban. “Lebih baik” bukan sifat sebuah garis seperti kemiringannya; itu adalah sifat sebuah garis bersama aturan untuk memberi skor pada garis, dan sampai seseorang menuliskan aturannya, tidak ada yang bisa dihitung. Bab ini menganggap kalimat itu serius, dan berakhir dengan penemuan bahwa aturan paling umum dalam machine learning bukanlah konvensi, melainkan konsekuensi dari klaim tentang dunia — klaim yang bisa kamu uji, dan yang kadang salah.
Satu pengakuan sebelum baris kode pertama. Dua puluh pembacaan ini bukan dari pabrik sungguhan: saya membuatnya dari garis yang saya pilih, , ditambah noise acak dengan sebaran sekitar sepersepuluh milimeter. Itu penting, karena semua yang di bawah ini membahas apakah sebuah metode memulihkan kebenaran, dan satu-satunya cara memeriksanya adalah mengetahui kebenaran lebih dulu. Jadi: 0,30 milimeter per jam adalah jawaban di bagian belakang buku. Kamu tidak boleh memakainya, hanya boleh memeriksanya.
Three rules, three winners
Tautan ke bagian: Three rules, three winnersBerikut pembacaannya dan tiga garisnya, diberi skor dengan tiga cara: squared error, yang semua orang langsung ambil; absolute error, yang mungkin dipilih seorang statistikawan; dan worst error, yang akan dipilih teknisi mesin, karena inspektur tidak peduli dengan rata-ratamu — ia menolak satu komponen yang keluar dari toleransi.
NumPy masuk di sini, satu bab setelah perceptron Python murni, karena satu alasan: pada akhir bab ini kita mengevaluasi empat ratus ribu garis kandidat terhadap masing-masing dua puluh pembacaan, dan loop Python adalah alat yang keliru untuk itu. Ini juga notasi yang dipakai setiap sumber yang dikutip di bawah.
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}") Besaran pada baris yang disorot adalah residual: apa yang dikatakan garis dikurangi apa yang dikatakan jangka sorong, satu angka per pembacaan. Setiap aturan skor dalam bab ini, dan setiap loss function dalam dua puluh delapan bab setelahnya, adalah suatu cara untuk memampatkan daftar residual menjadi satu angka. Bedanya hanya pada cara memampatkannya.
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.320Baca kolomnya, bukan barisnya. Squared error memilih B, absolute error memilih A, worst error memilih C: tiga aturan, tiga pemenang, pada dua puluh titik yang sama.
Saya memilih tiga garis ini agar mereka tidak sepakat, dan saya harus mengatakannya dengan jelas. Poinnya adalah betapa mudahnya itu — beberapa menit mencari di antara intercept dan slope yang tampak masuk akal menghasilkan ratusan tripel seperti ini. Peringkat adalah sifat aturan yang kamu pilih, bukan fakta tentang garis-garisnya, jadi aturan itu bukan detail implementasi: aturan itu adalah definisi masalahnya. Maka muncullah pertanyaan yang menjadi alasan bab ini ada: atas dasar apa kamu memilihnya?
One parameter, and a valley
Tautan ke bagian: One parameter, and a valleyPertama hal yang lebih kecil, karena garisnya bukan tiga, melainkan tak terhingga banyaknya. Ambil squared error dulu, karena itulah yang diambil semua orang, dan perkecil masalahnya menjadi satu angka menggunakan trik yang menyelamatkan perceptron dari sebelas ribu epoch di Bab 1: kurangi rata-rata dari kedua kolom. Setelah awan titik dipusatkan pada origin, garis terbaik di bawah squared error melewati origin persis — jadi intercept sudah ditetapkan dan hanya slope yang tersisa untuk dipilih.
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.010115Enam ratus satu slope kandidat, satu pemenang: 0,293 milimeter per jam melawan kebenaran 0,300. Dua puluh pembacaan ber-noise dan sebuah for-loop berhasil mendekati dalam seperseratus milimeter per jam — dua koma sepertiga persen.
Bagian menariknya bukan pemenangnya, melainkan bentuk pencariannya. Cetak seluruh kurva, diputar sehingga loss berjalan dari kiri ke kanan:
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.7928Itu adalah lembah, dilihat dari samping. Ia punya satu dasar, dindingnya naik mulus di kedua sisi, dan — inilah bagian yang tidak bisa ditawarkan tangga Bab 1 — di setiap titik tunggal di atasnya ada arah “menurun” yang terdefinisi jelas. Ingat bentuk itu. Bab 3 sepenuhnya tentang berjalan menurun tanpa mengunjungi keenam ratus satu titik, dan tentang apa yang berubah ketika sebuah lembah punya lebih dari satu dasar.
So why squared?
Tautan ke bagian: So why squared?Kita punya lembah karena kita menguadratkan. Absolute error akan memberinya tekukan di dasar; worst error akan memberinya bentangan datar di mana menggeser garis tidak mengubah apa pun. Menguadratkan jelas nyaman — dan kenyamanan kira-kira menjadi alasan yang diberikan kebanyakan kursus, dihias dalam empat bentuk: ia membuat error positif (absolute value juga begitu); ia menghukum error besar lebih berat (mengapa harus begitu?); ia differentiable (pangkat empat juga); ia dipakai semua orang (memang, dan itu bukan argumen).
Inilah posisi yang jujur. Squared error memilih garis B dan absolute error memilih garis A. Salah satunya benar untuk pabrik ini dan yang lain salah, dan belum ada apa pun sejauh ini yang bisa memberi tahu kamu yang mana. Untuk memilih aturan, kamu perlu mengetahui sesuatu tentang bagaimana pembacaan bisa berbeda dari garis, dan itu adalah pertanyaan tentang dunia, bukan tentang matematika. Menjawabnya membutuhkan satu perangkat kecil.
The likelihood of a line
Tautan ke bagian: The likelihood of a lineInilah klaim yang mengubah “garis mana yang lebih baik” menjadi pertanyaan dengan jawaban.
Anggap lebar sebuah komponen adalah garis ditambah error acak, dan anggap error itu diambil dari Gaussian — kurva lonceng — dengan mean nol dan standard deviation :
Density Gaussian adalah
Sekarang lakukan sesuatu yang tidak bisa dilakukan perceptron. Untuk slope kandidat tertentu , setiap pembacaan memiliki residual, dan rumus di atas mengubah residual itu menjadi angka: seberapa masuk akal error sebesar itu persisnya, jika slope ini adalah kebenaran? Pembacaan yang berada di garis mendapat angka besar, pembacaan yang meleset setengah milimeter mendapat angka kecil.
Pembacaannya independen — jangka sorong tidak mengingat komponen terakhir — jadi product rule mengatakan bahwa plausibilitas seluruh buku catatan adalah hasil kali density individual. Hasil kali itu adalah likelihood dari .1 Perhatikan arahnya, karena arah inilah yang dibahas Bayes’ rule: datanya tetap dan diketahui, dan parameternyalah yang berubah. Ini bukan “probabilitas slope”. Ini adalah probabilitas yang diberikan model pada data yang benar-benar kamu dapatkan, dibaca sebagai fungsi dari slope.
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.190312Slope 0,293 membuat buku catatan ini empat puluh enam ribu kali lebih masuk akal daripada 0,25, dan seratus dua puluh tujuh juta kali lebih masuk akal daripada 0,35. Maximum likelihood adalah prinsip bahwa kamu memilih parameter yang membuat apa yang benar-benar kamu amati menjadi sesedikit mungkin mengejutkan. Itu bukan teorema, melainkan usulan tentang apa arti “terbaik” semestinya — usulan yang punya isi, karena ia memaksamu menyatakan asumsi tentang noise sebelum kamu boleh memberi skor apa pun.
The product breaks
Tautan ke bagian: The product breaksJalankan tiga baris kode yang sama pada satu bulan shift, bukan satu shift, dan metodenya tumbang.
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+308Dua ribu perkalian dan jawabannya adalah inf. Ubah satu konstanta — jangka sorong yang lebih ceroboh, sehingga density keluar lebih kecil dari 1 alih-alih lebih besar — dan kode yang sama mengembalikan 0.0. Keduanya salah, dalam arah berlawanan, tidak ada exception yang bisa kamu tangkap, dan yang kedua bahkan tidak mencetak peringatan.
Tidak ada yang salah dengan matematikanya. Likelihood pada pengaturan itu adalah angka hingga yang terdefinisi sempurna: logaritma naturalnya 1400,91, jadi angkanya sendiri sekitar . Masalahnya komputer kamu tidak memiliki angka itu, dan memahami persis angka mana yang ia miliki layak dilakukan, karena ini bukan terakhir kalinya ia akan menentukan hasil.
Where the square comes from
Tautan ke bagian: Where the square comes fromPerbaikan untuk hasil kali yang meledak adalah yang biasa: ambil logaritma. Logaritma mengubah hasil kali menjadi jumlah, ia strictly increasing sehingga tidak bisa menggeser lokasi maksimum, dan jumlah dua ribu angka sedang adalah sesuatu yang ditangani float64 tanpa keluhan. Secara konvensi kita mengambil negative log-likelihood, sehingga lebih baik berarti lebih kecil. Sekarang substitusikan density Gaussian dan lihat apa yang terjadi.
-
Mulai dari hasil kali. Likelihood adalah , dengan density Gaussian di atas.
-
Ambil minus log. Hasil kali menjadi jumlah, dan eksponensial dalam density langsung saling meniadakan dengan logaritma:
- Buang semua yang tidak mengandung . Term pertama adalah konstanta. di depan jumlah adalah konstanta positif, dan menskalakan fungsi dengan konstanta positif tidak bisa menggeser lokasi minimumnya. Yang tersisa adalah
yaitu jumlah residual kuadrat — hal yang kita pakai untuk memulai bab ini karena itulah hal pertama yang terpikir oleh siapa pun.
Itulah hasil yang menjadi alasan bab ini ada, dan ia layak dinyatakan tanpa pagar: squared error bukan konvensi. Ia adalah negative log-likelihood dari Gaussian, setelah konstanta dibuang. Meminimalkan squared error adalah tindakan yang persis sama dengan menegaskan bahwa error kamu Gaussian dan bertanya parameter mana yang membuat datamu paling tidak mengejutkan. Kamu sudah membuat penegasan itu sejak awal; hanya saja tidak ada yang memberitahumu.
Ekuivalensinya bisa diperiksa, jadi periksalah: pindai enam ratus satu slope yang sama dengan negative log-likelihood lengkap, konstanta dan semuanya, dan dengan squared error biasa.
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: TrueAngka berbeda pada sumbu vertikal, dan salah satunya negatif, sesuatu yang tidak pernah terjadi pada jumlah kuadrat: negative log-likelihood bisa turun di bawah nol, karena density bisa melebihi 1. Dasar yang sama dari lembah yang sama, hingga titik grid terakhir.
Tampilkan derivasi lengkap
Pembuangan mana yang aman, tepatnya? Manuver yang sama muncul di setiap bab yang menurunkan loss, dan tidak selalu tidak berbahaya.
Membuang konstanta aditif aman kapan pun ia tidak bergantung pada parameter yang kamu optimalkan, dan membuang konstanta multiplikatif positif aman karena untuk apa pun. Keduanya gagal begitu juga sedang di-fit: saat itu sama sekali bukan konstanta, melainkan term yang mencegah model mengklaim dan plausibilitas tak hingga. Itulah tepatnya bagian berikutnya.
Keduanya gagal dengan cara berbeda lagi di Bab 3: konstanta multiplikatif tidak menggeser minimum, tetapi ia menskalakan gradient, dan gradient dikalikan dengan learning rate. Membagi dengan untuk mendapatkan mean squared error alih-alih sum tidak terlihat pada jawabannya dan sangat terlihat pada training run — dengan sum, menggandakan ukuran batch menggandakan setiap langkah yang kamu ambil.
Sigma is not free either
Tautan ke bagian: Sigma is not free eitherKita menetapkan pada 0,12 secara sewenang-wenang, dan tidak ada seorang pun di pabrik yang tahu sebaran error jangka sorong mereka. Perlakukan ia sebagai unknown kedua dan biarkan maximum likelihood menentukannya juga. Di sini term konstanta yang baru saja kita buang kembali, karena hanya term itu yang berdiri di antara model dan klaim presisi sempurna.
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.1006Keduanya sepakat hingga empat desimal, dan bukan kebetulan: menurunkan ekspresi itu dan menyetelnya ke nol memberi persis. Jadi mean squared error bukan sekadar mirip variance. Di bawah model ini, ia adalah estimasi maximum-likelihood dari variance noise — angka yang selama ini kamu minimalkan adalah estimasi seberapa berisik sensormu.
Satu kerutan, murah untuk dinyatakan dan mahal untuk ditemukan kembali nanti: estimasi itu bias ke bawah, karena residual diukur terhadap fit yang dirinya sendiri dipilih untuk membuat residual kecil. Simulasikan — dua ratus ribu buku catatan, masing-masing dua puluh pembacaan, diambil dari distribution yang true variance-nya tepat 1, dengan satu parameter fit diestimasi dari pembacaan itu sendiri. Membagi jumlah kuadrat dengan memberi rata-rata 0,9501; membagi dengan memberi 1,0001; dan adalah 0,95 tepat. Setiap parameter yang kamu fit menghabiskan satu degree of freedom, dan ini adalah contoh terkecil yang terlihat dari masalah yang jauh lebih besar: model selalu tampak lebih baik pada data yang dipakai untuk fit. Bab 4 mengubahnya menjadi disiplin menahan sebagian data, dan Bab 6 memberi nama pada efeknya.
A loss is a claim about the noise
Tautan ke bagian: A loss is a claim about the noiseJika squared error menegaskan bahwa noise adalah Gaussian, pertanyaan berikutnya adalah apa yang terjadi ketika penegasan itu salah. Bukan sedikit salah — salah seperti pengukuran nyata itu salah.
Di lantai produksi, sebagian besar pembacaan jangka sorong akurat hingga sepersepuluh milimeter, dan sekali atau dua kali per shift serpihan geram masuk ke bawah rahang sehingga pembacaannya meleset beberapa milimeter. Error seperti itu heavy-tailed: kecil hampir sepanjang waktu, sesekali sangat besar, dan sangat besar jauh lebih sering daripada yang diizinkan kurva lonceng. Distribution Cauchy adalah model bersih standar untuk perilaku itu, dan density-nya sesederhana Gaussian:
Bedanya ada di tail: Gaussian turun seperti , sangat cepat, dan Cauchy seperti , hampir tidak turun sama sekali. Konsekuensinya lebih mudah dilihat daripada dikatakan:
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.10Sample variance Gaussian menetap pada 0,0144, yaitu , dan tetap di sana. Cauchy naik, dan terus naik selama kamu mengambil sampel, karena tidak ada apa pun yang menjadi tujuan convergence: distribution Cauchy tidak punya variance, dan tidak punya mean juga. Squared error, yang seluruh urusannya adalah meminimalkan rata-rata kuadrat, sedang diminta mencari besaran yang tidak ada.
Jadi inilah satu shift ketika jangka sorong tertipu. Dua puluh jam yang sama, mata pisau yang sama, drift 0,30 milimeter per jam yang sama — hanya noise-nya sekarang Cauchy. Fit dua kali: sekali dengan meminimalkan residual kuadrat, sekali dengan meminimalkan negative log-likelihood dari noise yang benar-benar menghasilkan data. Trik centring tidak membantu di sini — ia hanya mengunci intercept untuk squared error — jadi kedua fit dilakukan dengan brute force di atas grid intercept dan slope, karena kita masih tidak punya cara untuk menemukan dasar lembah kecuali dengan mengunjunginya.
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")Dua baris yang disorot adalah seluruh perbedaan antara fit. Ambil log dari density Cauchy, buang konstanta persis seperti sebelumnya, dan adalah yang tersisa. Resep yang sama, klaim berbeda tentang noise.
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 evaluatedLeast squares melaporkan drift 0,108 milimeter per jam, kira-kira sepertiga dari laju sebenarnya, dan menyimpulkan bahwa mata pisau masih baik sampai jam 19,6. Jawaban sebenarnya adalah jam 11,7. Jika bertindak berdasarkan fit itu, pabrik menjalankan press delapan jam ekstra membuat komponen yang keluar dari toleransi, atas otoritas loss function paling standar di bidang ini. Fit Cauchy, memakai dua puluh pembacaan yang sama, grid yang sama, dan perbedaan satu baris kode, mendarat pada jam 11,8.
Dua keberatan layak dijawab, karena keduanya adalah hal pertama yang dikatakan engineer yang baik.
Outlier-nya jelas — hapus saja. Kamu bisa, dan itu membantu, dan itu belum cukup. Menghapus satu pembacaan terburuk menggeser slope least-squares dari 0,108 ke 0,239, yang masih menempatkan penggantian mata pisau pada jam 13,1, terlambat satu setengah jam; menghapus yang terburuk, melakukan refit, lalu menghapus apa pun yang terburuk sekarang membawamu ke 0,286 — dan perhatikan bahwa ini sudah merupakan prosedur, bukan observasi: hapus dua residual terbesar dari fit awal sebagai gantinya dan kamu mendarat pada 0,223. Namun kini kamu telah membuat judgement call yang tidak bisa kamu tulis atau pertahankan, dan mengotomatiskan aturan itu tidak menyelamatkannya: drop-the-largest-residual-then-refit, dijalankan pada seribu shift simulasi, memiliki median error slope 0,0177 melawan 0,0100 dari likelihood fit, dan meleset lebih dari 0,05 pada 14,7% shift melawan 1,3%. Penghapusan adalah tambalan di atas asumsi yang salah. Likelihood tidak membutuhkan tambalan, karena ia tidak pernah mengasumsikan outlier itu mustahil.
Kamu memilih dataset yang beruntung. Keberatan itu tepat sekali, karena itulah eksperimen terakhir mensimulasikan seribu shift independen dan melakukan refit dua cara pada masing-masing.
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 shiftsMedian, bukan mean, karena alasan yang sama seperti semua hal lain di bagian ini: error least-squares didorong oleh Cauchy, jadi rata-ratanya bukan sesuatu yang stabil untuk dilaporkan. Least squares sangat salah dua shift dari lima; likelihood fit sangat salah satu shift dari tujuh puluh tujuh, dan kegagalan terburuknya di seribu shift kurang dari seperlima kegagalan terburuk least squares.
Semua ini tidak membuat squared error buruk. Ini membuatnya spesifik, dan aritmetika menjelaskan persis alasannya. Ambil residual 0,1 mm dan residual 7 mm. Setelah dikuadratkan, pembacaan buruk berkontribusi 4.900 kali lebih besar ke total daripada pembacaan baik, sehingga garis diseret utuh ke arahnya; di bawah Cauchy log-likelihood, dua residual yang sama berkontribusi 0,527 dan 8,133, rasio 15,4. Pembacaan buruk tetap dihitung, ia hanya tidak berhak memutuskan. Ini awal dari robust statistics, tempat Huber’s 1964 loss membagi selisih dengan berperilaku kuadratik untuk residual kecil dan linear untuk residual besar,7 dan tempat Tukey sudah menunjukkan betapa sedikit kontaminasi yang dibutuhkan untuk membuat sample variance menjadi alat yang lebih buruk daripada mean absolute deviation.8
Satu catatan historis, terlalu bagus untuk ditinggalkan. Least squares pertama kali diterbitkan oleh Legendre pada 1805, sebagai perangkat aljabar yang nyaman tanpa pembenaran selain bahwa ia bekerja.9 Empat tahun kemudian Gauss menjalankan argumen itu mundur: ia menganggap sudah benar bahwa arithmetic mean adalah cara tepat untuk menggabungkan pengukuran berulang, bertanya error distribution mana yang membuat mean menjadi nilai paling mungkin, dan menunjukkan bahwa pada dasarnya hanya satu yang bisa — yang kini dinamai menurut dirinya.10 Turunan dalam bab ini adalah miliknya, berusia lebih dari dua abad, dan masih menjadi bagian yang ditinggalkan kebanyakan kursus.
What you can now say, and what you still cannot do
Tautan ke bagian: What you can now say, and what you still cannot doEarned. Loss function adalah aturan skor, dan peringkat yang dihasilkannya adalah sifat aturan itu, bukan sifat kandidat. Setiap loss dalam kursus ini adalah negative log-likelihood dari suatu asumsi tentang noise, setelah konstanta dibuang — Gaussian memberi squared error di sini, Bernoulli memberi cross-entropy di Bab 4, dan categorical distribution atas vocabulary memberi next-token loss di Bab 8. Resepnya tidak pernah berubah: nyatakan noise, tulis likelihood, ambil minus log. Dan ketika asumsinya salah, model bukan sekadar tidak presisi, ia salah dalam arah yang bisa kamu prediksi.
Still missing. Kita menemukan dasar lembah dengan mengunjungi setiap titik di dalamnya. Itu berhasil untuk satu parameter dan enam ratus kandidat, dan bertahan untuk dua parameter pada 401.301 kandidat dalam seperlima detik. Tiga parameter pada resolusi yang sama adalah 201.051.801 kandidat dan tidak lagi muat dalam satu array; network kecil di Bab 5 punya ribuan parameter, dan model yang diberi harga oleh Bab 10 punya miliaran. Brute force di sini bukan lambat, melainkan mustahil secara aritmetika, dan tidak ada apa pun dalam bab ini yang menyarankan alternatif.
Namun lihat kembali lembahnya. Berdiri di dengan loss 0,0822, arah “menurun” bukan misteri — kamu bisa melihatnya di halaman, kurvanya menurun ke kanan. Jika kamu bisa bertanya kepada loss function ke arah mana ia miring di titik tempat kamu berdiri, tanpa mengevaluasinya di tempat lain, kamu bisa melangkah ke arah itu, bertanya lagi, dan mengulanginya sampai tanahnya datar.
Pertanyaan itu punya nama. Kemiringan fungsi pada sebuah titik adalah derivative-nya, dan untuk fungsi dengan banyak parameter, kumpulan kemiringan di semua arah sekaligus adalah gradient. Bab 1 tidak bisa memakai gradient, karena error perceptron berupa tangga tanpa kemiringan untuk ditanyakan. Bab ini telah membangun sesuatu yang lebih baik: loss yang mulus di mana-mana dan berasal dari asumsi yang dinyatakan, bukan dari preferensi.
Jadi pertanyaan untuk Bab 3 bukan lagi apakah slope ada. Pertanyaannya adalah bagaimana menghitungnya, mengapa bergerak melawannya turun bukannya naik — tanda yang hampir setiap kursus memintamu terima begitu saja — dan seberapa jauh melangkah sebelum bertanya lagi, yang ternyata menjadi satu angka yang menentukan apakah training run converges, berosilasi di sekitar jawaban selamanya, atau lari menuju infinity.
Sources and method
Tautan ke bagian: Sources and methodJuga layak dibaca bersama bab ini: Prince, Understanding Deep Learning §5.1–5.2 dan Appendix C, yang membangun setiap loss dalam buku dari maximum likelihood dengan urutan yang dipakai di sini; Goodfellow, Bengio, dan Courville, Deep Learning §3.1–3.11 dan §5.5, yang bagian maximum-likelihood-nya juga menurunkan KL divergence yang dibutuhkan Bab 4; Murphy, Probabilistic Machine Learning: An Introduction bab 2 dan §4.2, tentang apa yang dijamin dan tidak dijamin maximum likelihood; Deisenroth, Faisal, dan Ong, Mathematics for Machine Learning §6.1–6.4 untuk sum rule, product rule, dan Bayes’ rule yang dilakukan dengan benar; catatan singkat CMU dari Tom Mitchell Estimating Probabilities: MLE and MAP (2016); serta §22.7 dari Dive into Deep Learning, yang mencapai hasil yang sama dalam kode yang bisa dijalankan.
Referensi
Tautan ke bagian: Referensi-
Fisher, R. A. On the mathematical foundations of theoretical statistics. Philosophical Transactions of the Royal Society A 222, hlm. 309–368 (1922). Tempat likelihood dijabarkan sebagai metode umum, bersama “parameter”, “statistic”, sufficiency, dan efficiency. Penamaannya sendiri, dan pemisahannya dari probability, muncul setahun lebih awal: Fisher, R. A., On the “probable error” of a coefficient of correlation deduced from a small sample, Metron 1, hlm. 3–32 (1921), hlm. 24–25. ↩
-
IEEE Standard for Floating-Point Arithmetic, IEEE 754-2019. Mendefinisikan binary32 dan binary16, serta aturan pembulatan yang membuat eksperimen penjumlahan keluar seperti itu. ↩
-
Kalamkar, D. et al. A Study of BFLOAT16 for Deep Learning Training. arXiv:1905.12322 (2019). Parameter formatnya, dan alasan menukar bit mantissa dengan bit exponent. ↩
-
Micikevicius, P. et al. Mixed Precision Training. ICLR 2018, arXiv:1710.03740. Loss scaling, dan besaran gradient terukur yang membuatnya perlu di float16. ↩
-
Goldberg, D. What Every Computer Scientist Should Know About Floating-Point Arithmetic. ACM Computing Surveys 23(1), hlm. 5–48 (1991). Masih menjadi penjelasan tunggal terbaik tentang mengapa dua urutan penjumlahan tidak sepakat. ↩
-
Kahan, W. Pracniques: further remarks on reducing truncation errors. Communications of the ACM 8(1), hlm. 40 (1965). Compensated summation dalam setengah halaman. ↩
-
Huber, P. J. Robust estimation of a location parameter. The Annals of Mathematical Statistics 35(1), hlm. 73–101 (1964). Loss yang kuadratik dekat nol dan linear di tail, diturunkan alih-alih ditambal. ↩
-
Tukey, J. W. A survey of sampling from contaminated distributions, dalam Contributions to Probability and Statistics (Stanford University Press, 1960), hlm. 448–485. ↩
-
Legendre, A. M. Nouvelles méthodes pour la détermination des orbites des comètes (Paris, 1805), lampiran Sur la méthode des moindres quarrés. Publikasi pertama least squares, sebagai perangkat komputasi. ↩
-
Gauss, C. F. Theoria Motus Corporum Coelestium (Hamburg, 1809), Buku II, §§175–179. Argumen dari arithmetic mean ke normal error law, dan dari sana ke least squares. ↩