Idenya
Dua kata memikul sebagian besar machine learning:
- Model adalah fungsi yang mengubah fitur menjadi prediksi, dengan beberapa angka yang bisa disesuaikan di dalamnya, yaitu parameter-nya.
- Loss function adalah satu angka yang menyatakan seberapa salah prediksi model pada data training. Semakin rendah semakin baik.
Training = menemukan parameter dengan loss terendah. Semua hal lainnya (regresi linear, jaringan saraf) adalah variasi dari kalimat itu.
Model untuk permintaan kopi
daily_demand.csv berisi penjualan kopi harian selama setahun beserta belanja iklan hari itu (dalam juta Rupiah):
import numpy as np
import pandas as pd
demand = pd.read_csv("daily_demand.csv")
ad = demand["ad_spend"].to_numpy()
units = demand["units"].to_numpy()
print(demand.head(3))
print(len(demand))
date temperature weekend promo ad_spend units
0 2024-01-01 26.4 0 0 2.45 57
1 2024-01-02 27.4 0 0 2.62 63
2 2024-01-03 27.2 0 0 2.05 51
366
Model sederhana: unit terjual = w × belanja iklan + b. Dua parameter: w (unit tambahan per juta Rupiah iklan) dan b (unit terjual tanpa iklan).
def predict(ad, w, b):
return w * ad + b
print(predict(np.array([0.0, 1.0, 2.0]), w=8, b=45))
[45. 53. 61.]
w dan b yang berbeda menghasilkan model yang berbeda. Pasangan mana yang terbaik?
Mengukur kesalahan: loss
Untuk setiap hari, error (residual) adalah prediksi dikurangi nilai sebenarnya. Untuk merangkum banyak error dalam satu angka, pilihan yang paling umum untuk regresi adalah mean squared error (MSE): kuadratkan setiap error, lalu rata-ratakan.
def mse(predicted, actual):
return np.mean((predicted - actual) ** 2)
for w, b in [(0, 56), (8, 45), (15, 30)]:
print(w, b, round(mse(predict(ad, w, b), units), 1))
0 56 131.3
8 45 90.0
15 30 140.6
Model tengah punya loss terendah dari ketiganya, jadi paling cocok. Kenapa error-nya dikuadratkan?
- Error +5 dan −5 tidak boleh saling meniadakan; mengkuadratkan membuat keduanya positif.
- Error besar dihitung jauh lebih berat daripada error kecil (error 10 bernilai 100; dua error 5 bernilai 50 bersama-sama). Itu biasanya yang kamu inginkan: model yang sesekali sangat salah lebih buruk daripada model yang selalu sedikit meleset.
- Kuadrat itu mulus, yang membuat matematika untuk menemukan nilai minimumnya mudah (gradient descent, nanti di track ini).
Alternatifnya, mean absolute error (MAE), np.mean(np.abs(errors)), memperlakukan semua error secara proporsional dan lebih mudah dijelaskan ("rata-rata meleset 4 unit"). Modul metrik regresi membandingkan keduanya.
Training = mencari loss terendah
Dengan hanya dua parameter, kita bisa mencoba grid nilai dan menyimpan yang terbaik, persis seperti pencarian batas di modul pertama:
best = None
for w in np.arange(0, 15.5, 0.5):
for b in np.arange(30, 61, 1.0):
loss = mse(predict(ad, w, b), units)
if best is None or loss < best[0]:
best = (loss, w, b)
print(f"loss {best[0]:.1f} at w={best[1]}, b={best[2]}")
loss 88.6 at w=7.5, b=45.0
Datanya berkata: sekitar 7,5 unit tambahan per juta Rupiah iklan, dan sekitar 45 unit tanpa iklan sama sekali. Itulah wawasan bisnis yang dipelajari.
Grid search seperti ini meledak saat parameternya bertambah (10 parameter × masing-masing 30 nilai = 30¹⁰ kombinasi). Training sungguhan memakai metode yang lebih cerdas: rumus eksak untuk regresi linear (dua modul dari sekarang), dan gradient descent untuk hampir semua hal lainnya, termasuk jaringan saraf.
Lanskap loss
Bayangkan loss sebagai sebuah lanskap: setiap titik di tanah adalah pilihan (w, b), dan ketinggiannya adalah loss. Training berarti menemukan lembah terendah. Untuk regresi linear dengan MSE, lanskapnya berupa mangkuk mulus dengan tepat satu dasar, itulah sebabnya ia mudah dilatih. Jaringan saraf punya lanskap bergelombang dengan banyak lembah, itulah sebabnya melatihnya adalah sebuah seni.
for w in [4, 6, 7.5, 9, 11]:
print(w, round(mse(predict(ad, w, 45), units), 1))
4 122.0
6 93.6
7.5 88.6
9 97.5
11 131.3
Menggeser w menjauh dari nilai terbaik ke arah mana pun menaikkan loss: dinding-dinding mangkuknya.
Loss untuk klasifikasi
Untuk prediksi ya/tidak, model biasanya mengeluarkan probabilitas (0,8 = "80% kemungkinan churn"), dan loss standarnya adalah log loss (cross-entropy): jawaban salah yang penuh keyakinan dihukum berat.
def log_loss(p, y):
p = np.clip(p, 1e-12, 1 - 1e-12)
return -np.mean(y * np.log(p) + (1 - y) * np.log(1 - p))
actual = np.array([1, 0, 1])
print(round(log_loss(np.array([0.9, 0.1, 0.8]), actual), 3)) # yakin dan benar
print(round(log_loss(np.array([0.6, 0.4, 0.5]), actual), 3)) # ragu-ragu
print(round(log_loss(np.array([0.1, 0.9, 0.2]), actual), 3)) # yakin dan salah
0.145
0.572
2.072
Kamu akan bertemu lagi dengannya di regresi logistik dan di PyTorch, di mana ia disebut BCELoss / CrossEntropyLoss.
Mengapa ini penting untuk kode yang bersih
"Model + loss + pencarian" adalah dekomposisi bersih yang bisa kamu terapkan ke masalah ML apa pun: tulis model sebagai fungsi, loss sebagai fungsi, dan training sebagai loop atau pemanggilan library yang menghubungkan keduanya. Saat hasilnya terlihat salah, kamu bisa memeriksa setiap bagian secara terpisah: apakah prediksinya masuk akal? Apakah loss-nya dihitung dengan benar? Apakah pencariannya konvergen?
Rangkuman
- Model adalah fungsi dengan parameter; training menemukan parameter dengan loss terendah.
- Loss regresi: MSE (rata-rata error kuadrat) menghukum error besar; MAE (mean absolute error) proporsional dan mudah dijelaskan.
- Grid search berfungsi untuk beberapa parameter; training sungguhan memakai rumus atau gradient descent.
- Lanskap loss: untuk regresi linear dengan MSE, satu mangkuk yang mulus.
- Loss klasifikasi: log loss pada probabilitas yang diprediksi; kesalahan yang penuh keyakinan paling mahal.