Bayangkan koki bintang lima yang punya intuisi bertahun-tahun (= pengetahuan fuzzy dari pakar), tapi juga mau belajar dari ribuan ulasan pelanggan tentang masakan mana yang paling disukai (= training dari data seperti NN). Hasilnya? Masakan yang intuitif, bisa dijelaskan alasannya, tapi juga terus-menerus disempurnakan berdasarkan feedback nyata. Itulah ANFIS!
ANFIS seperti lini produksi pabrik: bahan baku (input) masuk ke 5 stasiun kerja secara berurutan. Setiap stasiun melakukan transformasi tertentu. Output stasiun terakhir adalah produk jadi (nilai kontrol). Yang membuatnya istimewa: dimensi tiap komponen bisa disesuaikan otomatis berdasarkan data — seperti mesin yang bisa mengkalibrasi dirinya sendiri!
Fuzzifikasi
Hitung μ(x) untuk setiap input. Parameter MF {c,σ} dapat di-update (trainable).
Rule Strength
Kalikan μ tiap rule: wᵢ = μ_A(x₁) × μ_B(x₂)
Normalisasi
w̄ᵢ = wᵢ / Σwⱼ (normalized firing strength)
Consequent
w̄ᵢ · fᵢ dimana fᵢ = pᵢx₁ + qᵢx₂ + rᵢ (T-S rule, trainable!)
Output
y = Σ w̄ᵢ·fᵢ (weighted average defuzzifikasi)
Rule 2: IF x₁ is A₂ AND x₂ is B₂ THEN f₂ = p₂x₁ + q₂x₂ + r₂
w₁ = μ_A₁(x₁) · μ_B₁(x₂)
w₂ = μ_A₂(x₁) · μ_B₂(x₂)
ŷ = (w₁·f₁ + w₂·f₂) / (w₁ + w₂)
Parameter yang di-train:
Premise params: {c₁,σ₁,c₂,σ₂} di membership functions
Consequent params: {p₁,q₁,r₁,p₂,q₂,r₂} di rule consequents
Tim A ahli matematika (Least Squares) dan Tim B ahli heuristic (Backprop). Dalam ANFIS, mereka bekerja bergantian: Tim A (forward pass — Least Squares) mengoptimasi parameter consequent (p,q,r) secara analitis — cepat dan tepat. Tim B (backward pass — Backprop) mengoptimasi parameter premise (c,σ di MF) secara gradien. Kombinasi ini konvergen jauh lebih cepat dari backprop murni!
Premise params tetap → hitung w̄ᵢ
Minimasi: ||Φ·p − y||² secara analitis
p* = (ΦᵀΦ)⁻¹Φᵀy (solusi least squares)
Backward pass (Backpropagation):
Consequent params tetap → update premise params
c ← c − α · ∂E/∂c
σ ← σ − α · ∂E/∂σ
| Aspek | Backprop Murni (NN) | Hybrid Learning (ANFIS) |
|---|---|---|
| Kecepatan konvergensi | Lambat — semua parameter pakai gradient | Lebih cepat — consequent diselesaikan analitis |
| Akurasi akhir | Bergantung learning rate | Umumnya lebih akurat untuk data kecil |
| Interpretabilitas | Black box | Fuzzy rules tetap bisa dibaca |
| Jumlah data yang dibutuhkan | Banyak (ribuan) | Lebih sedikit karena inisialisasi dari prior knowledge |
| Metode | Belajar dari data? | Interpretable? | Model fisika? | Jaminan stabilitas? |
|---|---|---|---|---|
| PID Statis | ❌ | ✅ | ❌ (hanya error) | ✅ (jika dirancang baik) |
| MRAC (S4) | ✅ (online) | ⚠️ (parameter θ) | ✅ (reference model) | ✅ (Lyapunov) |
| Gain Scheduling (S6) | ❌ (offline design) | ✅ | ✅ (linearisasi) | ✅ (per zona) |
| Fuzzy (S9) | ❌ (rules manual) | ✅✅ | ❌ | ⚠️ (tidak formal) |
| Neural Net (S10) | ✅✅ | ❌ | ❌ | ❌ |
| ANFIS (S11) | ✅ | ✅ | ❌ | ⚠️ |
🔑 Posisi ANFIS di Dunia Industri
- ANFIS paling cocok ketika ada prior knowledge fuzzy dari operator, tapi parameter-parameternya perlu dioptimasi lebih lanjut
- Banyak digunakan di: pengolahan sinyal biomedis, peramalan beban listrik, kontrol robot, identifikasi fault sensor
- Di Indonesia: beberapa PLTGU menggunakan ANFIS untuk prediksi efisiensi dan deteksi anomali
Reaktor kimia memiliki dinamika sangat nonlinier: reaksi eksotermis bisa menyebabkan temperature runaway (suhu naik tak terkendali). Operator berpengalaman punya intuisi fuzzy: "JIKA suhu NAIK CEPAT DAN konsentrasi reaktan TINGGI MAKA kurangi laju alir SEGERA". ANFIS mengambil intuisi ini sebagai titik awal, lalu mengoptimasi parameter berdasarkan data historis reaktor.
| Input ANFIS | Variabel | Himpunan Fuzzy |
|---|---|---|
| Error suhu | e_T = T_set − T_actual (°C) | NB, NS, ZE, PS, PB |
| Laju perubahan suhu | ΔT/Δt (°C/menit) | Turun Cepat, Turun, Stabil, Naik, Naik Cepat |
| Output ANFIS | Laju alir pendingin (L/menit) | T-S linear consequent (dioptimasi) |
import numpy as np import matplotlib.pyplot as plt # ========================================== # ANFIS SEDERHANA: 2 INPUT, 2 RULES, T-S OUTPUT # Masalah: identifikasi fungsi nonlinier # Target: y = sin(x1)*cos(x2) + 0.2*x1*x2 # ========================================== np.random.seed(2024) # === GENERATE TRAINING DATA === N_train = 300 x1_tr = np.random.uniform(-3, 3, N_train) x2_tr = np.random.uniform(-3, 3, N_train) y_tr = np.sin(x1_tr)*np.cos(x2_tr) + 0.2*x1_tr*x2_tr + 0.05*np.random.randn(N_train) N_test = 100 x1_te = np.random.uniform(-3, 3, N_test) x2_te = np.random.uniform(-3, 3, N_test) y_te = np.sin(x1_te)*np.cos(x2_te) + 0.2*x1_te*x2_te # === GAUSSIAN MEMBERSHIP FUNCTION === def gaussian_mf(x, c, sigma): return np.exp(-0.5 * ((x - c) / (sigma + 1e-8))**2) # === ANFIS PARAMETER (2 rules, 2 inputs) === # Premise params (MF centers dan widths) — untuk x1 dan x2 c1 = np.array([-1.5, 1.5]) # centers rule 1,2 untuk x1 s1 = np.array([1.2, 1.2]) # sigmas untuk x1 c2 = np.array([-1.5, 1.5]) # centers untuk x2 s2 = np.array([1.2, 1.2]) # sigmas untuk x2 # Consequent params: f_i = p_i*x1 + q_i*x2 + r_i P = np.zeros((2, 3)) # 2 rules × 3 params (p, q, r) def anfis_forward(x1, x2, c1, s1, c2, s2, P): # Layer 1: Fuzzification mu1 = gaussian_mf(x1, c1[0], s1[0]) * gaussian_mf(x2, c2[0], s2[0]) mu2 = gaussian_mf(x1, c1[1], s1[1]) * gaussian_mf(x2, c2[1], s2[1]) # Layer 3: Normalization w_sum = mu1 + mu2 + 1e-10 w1_n, w2_n = mu1/w_sum, mu2/w_sum # Layer 4: Consequent (T-S linear) f1 = P[0,0]*x1 + P[0,1]*x2 + P[0,2] f2 = P[1,0]*x1 + P[1,1]*x2 + P[1,2] # Layer 5: Output y_hat = w1_n*f1 + w2_n*f2 return y_hat, w1_n, w2_n def update_consequents_lse(x1, x2, y, c1, s1, c2, s2): """Least Squares untuk update consequent params""" _, w1_n, w2_n = anfis_forward(x1, x2, c1, s1, c2, s2, np.zeros((2,3))) Phi = np.column_stack([w1_n*x1, w1_n*x2, w1_n, w2_n*x1, w2_n*x2, w2_n]) p_flat, _, _, _ = np.linalg.lstsq(Phi, y, rcond=None) return p_flat.reshape(2, 3) # === HYBRID TRAINING === lr_premise = 0.04 epochs = 120 train_losses, test_losses = [], [] for ep in range(epochs): # --- FORWARD: Update consequents via LSE --- P = update_consequents_lse(x1_tr, x2_tr, y_tr, c1, s1, c2, s2) y_hat_tr, _, _ = anfis_forward(x1_tr, x2_tr, c1, s1, c2, s2, P) train_losses.append(np.mean((y_hat_tr - y_tr)**2)) y_hat_te, _, _ = anfis_forward(x1_te, x2_te, c1, s1, c2, s2, P) test_losses.append(np.mean((y_hat_te - y_te)**2)) # --- BACKWARD: Update premise params via gradient --- eps = 1e-4 for ri in range(2): for param_name, param_arr, idx in [('c1',c1,ri),('s1',s1,ri),('c2',c2,ri),('s2',s2,ri)]: orig = param_arr[idx] param_arr[idx] = orig + eps yp, _, _ = anfis_forward(x1_tr, x2_tr, c1, s1, c2, s2, P) L_p = np.mean((yp - y_tr)**2) param_arr[idx] = orig - eps yp, _, _ = anfis_forward(x1_tr, x2_tr, c1, s1, c2, s2, P) L_m = np.mean((yp - y_tr)**2) grad = (L_p - L_m) / (2*eps) param_arr[idx] = orig - lr_premise * grad # Batas sigma agar tidak negatif if param_name in ('s1', 's2'): param_arr[idx] = np.clip(param_arr[idx], 0.1, 4.0) if ep % 20 == 0: print(f"Ep {ep:3d}: Train MSE={train_losses[-1]:.5f}, Test MSE={test_losses[-1]:.5f}") # === PLOT === fig, axes = plt.subplots(1, 3, figsize=(14, 5)) axes[0].semilogy(train_losses, 'orange', lw=2, label='Training MSE') axes[0].semilogy(test_losses, 'lime', lw=2, ls='--', label='Test MSE') axes[0].set_xlabel('Epoch'); axes[0].set_ylabel('MSE (log)') axes[0].set_title('ANFIS Hybrid Learning Curve') axes[0].legend(); axes[0].grid(alpha=0.3) y_pred_final, _, _ = anfis_forward(x1_te, x2_te, c1, s1, c2, s2, P) axes[1].scatter(y_te, y_pred_final, s=12, alpha=0.6, color='orange') lims = [min(y_te.min(), y_pred_final.min()), max(y_te.max(), y_pred_final.max())] axes[1].plot(lims, lims, 'lime', lw=2, label='y = ŷ (ideal)') axes[1].set_xlabel('y Aktual'); axes[1].set_ylabel('y Prediksi ANFIS') axes[1].set_title('Test: Aktual vs Prediksi ANFIS') axes[1].legend(); axes[1].grid(alpha=0.3) x_vis = np.linspace(-3, 3, 100) axes[2].plot(x_vis, gaussian_mf(x_vis, c1[0], s1[0]), 'cyan', lw=2, label=f'MF₁: c={c1[0]:.2f}, σ={s1[0]:.2f}') axes[2].plot(x_vis, gaussian_mf(x_vis, c1[1], s1[1]), 'orange', lw=2, label=f'MF₂: c={c1[1]:.2f}, σ={s1[1]:.2f}') axes[2].set_xlabel('x₁'); axes[2].set_ylabel('Derajat Keanggotaan') axes[2].set_title('MF yang Dioptimasi ANFIS (setelah training)') axes[2].legend(); axes[2].grid(alpha=0.3) axes[2].set_ylim(0, 1.1) plt.tight_layout(); plt.show() rmse = np.sqrt(np.mean((y_pred_final - y_te)**2)) print(f"\n📊 ANFIS Test RMSE: {rmse:.4f}") print(f"Parameter Consequent Rule 1: p={P[0,0]:.3f}, q={P[0,1]:.3f}, r={P[0,2]:.3f}") print(f"Parameter Consequent Rule 2: p={P[1,0]:.3f}, q={P[1,1]:.3f}, r={P[1,2]:.3f}") print(f"MF x1 Rule 1: center={c1[0]:.3f}, sigma={s1[0]:.3f}") print(f"MF x1 Rule 2: center={c1[1]:.3f}, sigma={s1[1]:.3f}")
📊 Yang Perlu Diperhatikan dari Hasil ANFIS
- Plot 1 (Loss curve): Hybrid learning konvergen dengan cepat karena LSE analitis untuk consequent
- Plot 2 (Scatter aktual vs prediksi): Titik-titik mendekati garis y=ŷ → ANFIS berhasil mempelajari fungsi nonlinier
- Plot 3 (MF setelah training): Centers dan sigma bergeser dari nilai awal! Ini yang membuat ANFIS unggul dari fuzzy biasa — MF dioptimasi otomatis dari data
- Kita masih bisa membaca aturan: "Rule 1 aktif di daerah x₁≈{c1[0]}, Rule 2 aktif di x₁≈{c1[1]}"
🧠 Kuis Pemahaman Sesi 11
1. ANFIS disebut "hybrid" karena menggabungkan dua pendekatan. Apa yang diambil dari masing-masing?
2. Dalam Hybrid Learning ANFIS, Least Squares digunakan untuk mengoptimasi parameter apa?
3. Mengapa ANFIS lebih cocok dari Neural Network murni ketika ada prior knowledge (pengetahuan pakar) tentang sistem?