Chapter sebelumnya menutup dengan satu janji: alasan di balik pilihan ReLU dan sigmoid akan dibahas tuntas. Fungsi aktivasi memang terlihat seperti detail kecil — satu baris np.maximum(0.0, z) — tetapi keputusan ini menentukan dua hal besar sekaligus: bentuk fungsi yang bisa diwakili jaringan, dan kelancaran gradien saat pelatihan. Chapter ini membedah empat fungsi inti (sigmoid, tanh, ReLU, Leaky ReLU) plus softmax untuk keluaran banyak kelas, menghitung nilai dan turunannya secara numerik, lalu mendemonstrasikan masalah yang mengubah sejarah arsitektur jaringan: vanishing gradient. Di akhir chapter, angka-angka akan menjelaskan sendiri mengapa ReLU menjadi pilihan bawaan hampir semua jaringan modern.
Kenapa Nonlinieritas Tidak Bisa Dinegosiasikan #
Sebelum membahas pilihan fungsinya, mari kita pahami dulu mengapa fungsi aktivasi wajib nonlinier. Misalkan kita membuang g dan menumpuk dua lapisan linear murni: Z2 = (X @ W1 + b1) @ W2 + b2. Aljabar sederhana menunjukkan hasilnya:
(X @ W1 + b1) @ W2 + b2 = X @ (W1 @ W2) + (b1 @ W2 + b2) = X @ W' + b'Dua lapisan linear identik dengan satu lapisan linear — menumpuknya sepuluh kali pun tidak menambah kekayaan fungsi sedikit pun. Justru fungsi aktivasi nonlinier di antara lapisan-lapisan itulah yang membuat komposisi bertingkat menjadi ekspresif, seperti yang dibuktikan teorema universal approximation pada chapter sebelumnya. Sekarang kita bandingkan kandidat nonlinieritas utama.
Empat Fungsi Aktivasi Inti #
Berikut rumus nilai dan turunan keempat fungsi yang akan kita hitung:
sigmoid(z) = 1 / (1 + e^-z) turunan: s * (1 - s)
tanh(z) = (e^z - e^-z)/(e^z+e^-z) turunan: 1 - tanh(z)^2
relu(z) = max(0, z) turunan: 1 jika z > 0, selain itu 0
leaky_relu(z) = z jika z > 0, a*z turunan: 1 jika z > 0, selain itu aRentang dan perilaku gradiennya sangat berbeda. Sigmoid memetakan keluaran ke (0, 1) — pas untuk peluang biner — tetapi turunannya mencapai puncak hanya 0,25 di z = 0 dan segera mengecil menuju nol di kedua ujung (wilayah jenuh). Tanh berpusat di nol dengan rentang (-1, 1) dan turunan puncak 1,0 — lebih sehat daripada sigmoid untuk lapisan tersembunyi, tetapi tetap jenuh di ujung. ReLU tidak jenuh di wilayah positif: turunannya konstan 1 untuk semua z > 0. Leaky ReLU menambani kelemahan satu-satunya ReLU — turunan nol untuk z < 0 — dengan kemiringan kecil a (misalnya 0,1) agar neuron negatif tetap menerima gradien.
# Nilai dan turunan empat fungsi aktivasi pada rentang masukan tetap,
# ditutup contoh softmax untuk masalah banyak kelas. Turunan ditampilkan
# karena menentukan aliran gradien saat pelatihan.
import numpy as np
def sigmoid(z):
return 1.0 / (1.0 + np.exp(-z))
def dsigmoid(z):
s = sigmoid(z)
return s * (1.0 - s)
def dtanh(z):
return 1.0 - np.tanh(z) ** 2
def relu(z):
return np.maximum(0.0, z)
def drelu(z):
return (z > 0).astype(float)
def leaky_relu(z, alpha=0.1):
return np.where(z > 0, z, alpha * z)
def dleaky_relu(z, alpha=0.1):
return np.where(z > 0, 1.0, alpha)
nilai_x = np.array([-6.0, -3.0, -1.0, 0.0, 1.0, 3.0, 6.0])
print(" x sigmoid d/dx tanh d/dx relu d/dx lrelu d/dx")
for x in nilai_x:
print(f"{x:6.1f} {sigmoid(x):8.4f} {dsigmoid(x):7.4f} "
f"{np.tanh(x):7.4f} {dtanh(x):7.4f} {relu(x):6.1f} {drelu(x):6.1f} "
f"{leaky_relu(x):7.3f} {dleaky_relu(x):6.2f}")
# Softmax mengubah vektor logit menjadi distribusi peluang berjumlah 1.
logit = np.array([2.0, 1.0, 0.1])
peluang = np.exp(logit) / np.exp(logit).sum()
print("\nSoftmax untuk logit", logit.tolist())
print("peluang kelas =", np.round(peluang, 4).tolist())
print(f"jumlah peluang = {peluang.sum():.4f}")Output yang Dihasilkan:
x sigmoid d/dx tanh d/dx relu d/dx lrelu d/dx
-6.0 0.0025 0.0025 -1.0000 0.0000 0.0 0.0 -0.600 0.10
-3.0 0.0474 0.0452 -0.9951 0.0099 0.0 0.0 -0.300 0.10
-1.0 0.2689 0.1966 -0.7616 0.4200 0.0 0.0 -0.100 0.10
0.0 0.5000 0.2500 0.0000 1.0000 0.0 0.0 0.000 0.10
1.0 0.7311 0.1966 0.7616 0.4200 1.0 1.0 1.000 1.00
3.0 0.9526 0.0452 0.9951 0.0099 3.0 1.0 3.000 1.00
6.0 0.9975 0.0025 1.0000 0.0000 6.0 1.0 6.000 1.00
Softmax untuk logit [2.0, 1.0, 0.1]
peluang kelas = [0.659, 0.2424, 0.0986]
jumlah peluang = 1.0000Tabel output layak dibaca kolom per kolom:
- Kolom
sigmoiddand/dx: diz = ±6, nilai sigmoid sudah menempel di 0,0025 dan 0,9975 sementara turunannya tinggal 0,0025 — kurang dari 1% dari puncak 0,2500 diz = 0. Neuron sigmoid yang sangat yakin (nilai ekstrem) hampir tidak mengirim gradien. - Kolom
tanhdand/dx: pola yang sama dengan pusat yang lebih baik; turunan 1,0 di titik nol, tetapi 0,0000 kembali muncul diz = ±6. - Kolom
reludand/dx: turunan 1,0 untuk semuazpositif — dari 1,0 sampai 6,0 tidak ada penurunan sama sekali. Untukz <= 0turunannya 0. - Kolom
lreludand/dx: di wilayah negatif turunannya 0,10 — kecil, tetapi tidak nol; inilah seluruh tujuan Leaky ReLU.
Bagian softmax di akhir output menunjukkan logit [2.0, 1.0, 0.1] berubah menjadi peluang [0.659, 0.2424, 0.0986] yang berjumlah tepat 1,0000. Softmax bukan aktivasi per-neuron seperti keempat fungsi lainnya; softmax beroperasi pada seluruh vektor logit sekaligus dan dipakai di lapisan keluaran masalah banyak kelas — keluarganya akan bertemu lagi pada categorical cross-entropy di chapter berikutnya.
| Fungsi | Rentang Keluaran | Turunan di Ekstrem | Catatan Praktis |
|---|---|---|---|
| Sigmoid | (0, 1) | mendekati 0 | peluang biner di lapisan keluaran |
| Tanh | (-1, 1) | mendekati 0 | terpusat nol, lebih baik dari sigmoid |
| ReLU | [0, tak hingga) | 1 (positif), 0 (negatif) | bawaan jaringan modern |
| Leaky ReLU | tak terbatas | 1 (positif), a (negatif) | penambal neuron ReLU mati |
| Softmax | (0, 1), jumlah 1 | tergantung vektor | keluaran klasifikasi banyak kelas |
Vanishing Gradient: Ketika Rantai Perkalian Menyusut #
Backpropagation (chapter berikutnya) mengalirkan gradien dari lapisan keluaran menuju lapisan awal, dan di setiap lapisan gradien dikalikan turunan aktivasi lokal. Untuk jaringan sedalam L lapisan, gradien yang sampai ke lapisan pertama adalah hasil kali L turunan. Di sinilah sigmoid dan tanh kalah: turunan maksimum sigmoid hanya 0,25, sehingga lima lapisan saja sudah memangkas gradien paling banter menjadi 0,25^5 = 0,00098 — dan itu skenario terbaiknya. Mari kita hitung secara numerik:
# Vanishing gradient: gradien yang merambat mundur dikalikan turunan
# aktivasi di setiap lapisan. Lima lapisan berarti lima perkalian berturut,
# dan hasil kalinya menentukan apakah bobot lapisan awal masih bisa belajar.
import numpy as np
def sigmoid(z):
return 1.0 / (1.0 + np.exp(-z))
def dsigmoid(z):
s = sigmoid(z)
return s * (1.0 - s)
print("Skenario A: kelima lapisan sigmoid menerima z yang sama")
print("z turunan lokal hasil kali 5 lapisan")
for z in (0.0, 1.0, 2.0, 4.0):
lokal = dsigmoid(z)
hasil = lokal ** 5
print(f"{z:4.1f} {lokal:.4f} {hasil:.10f}")
print("\nSkenario B: kelima lapisan ReLU menerima z yang sama")
print("z turunan lokal hasil kali 5 lapisan")
for z in (1.0, -1.0):
lokal = 1.0 if z > 0 else 0.0
hasil = lokal ** 5
print(f"{z:4.1f} {lokal:.4f} {hasil:.4f}")
# Skenario C: z berbeda tiap lapisan -- neuron sigmoid sangat aktif
# (z besar positif) justru punya turunan kecil karena jenuh.
z_lapisan = np.array([3.2, 4.1, 2.8, 5.0, 3.7])
hasil_sigmoid = float(np.prod(dsigmoid(z_lapisan)))
hasil_relu = float(np.prod(np.where(z_lapisan > 0, 1.0, 0.0)))
print(f"\nSkenario C: lima lapisan dengan z = {z_lapisan.tolist()}")
print(f"hasil kali turunan sigmoid = {hasil_sigmoid:.10f}")
print(f"hasil kali turunan ReLU = {hasil_relu:.4f}")Output yang Dihasilkan:
Skenario A: kelima lapisan sigmoid menerima z yang sama
z turunan lokal hasil kali 5 lapisan
0.0 0.2500 0.0009765625
1.0 0.1966 0.0002937984
2.0 0.1050 0.0000127589
4.0 0.0177 0.0000000017
Skenario B: kelima lapisan ReLU menerima z yang sama
z turunan lokal hasil kali 5 lapisan
1.0 1.0000 1.0000
-1.0 0.0000 0.0000
Skenario C: lima lapisan dengan z = [3.2, 4.1, 2.8, 5.0, 3.7]
hasil kali turunan sigmoid = 0.0000000051
hasil kali turunan ReLU = 1.0000Angka-angka tersebut menceritakan kisah yang sangat jelas:
- Skenario A (baris 17–22): bahkan pada titik paling bersahabat
z = 0, lima lapisan sigmoid memangkas gradien menjadi 0,0009765625 — tinggal seperseperseribu. Padaz = 4, hasil kalinya 0,0000000017: praktis nol. - Skenario B (baris 24–29): ReLU menjaga hasil kali 1,0000 selama semua
zpositif. Bobot lapisan awal menerima gradien utuh — inilah alasan utama ReLU mendominasi sejak 2011. - Skenario C (baris 31–38): skenario realistis dengan
zberbeda per lapisan. Kelima nilaizyang besar positif (neuron sangat aktif) justru bencana bagi sigmoid: hasil kali 0,0000000051. ReLU tetap 1,0000.
Dengan aktivasi yang sehat, jaringan siap dilatih — tetapi “dilatih” membutuhkan dua komponen yang belum kita punya: ukuran galat (loss function) dan cara menghitung ke arah mana setiap bobot harus digeser (backpropagation). Keduanya adalah materi Chapter Loss Function dan Backpropagation, tempat turunan-turunan pada chapter ini akhirnya dipakai di tempatnya.
Referensi Resmi #
- numpy.exp — NumPy — fungsi eksponensial yang menjadi bahan dasar sigmoid, tanh, dan softmax.
- numpy.maximum — NumPy — operasi inti ReLU.
- Neural network supervised — scikit-learn User Guide
— daftar aktivasi yang didukung
MLPClassifier(relu,tanh,logistic) beserta catatannya.