DataLens

Ide tentang model dan loss function

Pahami model sebagai fungsi dengan parameter, ukur seberapa salahnya dengan loss function, dan temukan parameter terbaik dengan mencari loss terendah.

Level: Dasar · 8 menit baca

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.

Idenya

Dua kata memikul sebagian besar machine learning:

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?

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

Latihan modul ini

Soal-soal untuk pelajaran ini berjalan di browser-mu dan langsung mengecek jawabanmu.

Berikutnya: Overfitting, underfitting, dan generalisasi →