Model yang berakhir di notebook belum menyelesaikan masalah apa pun. Nilai machine learning baru terwujud ketika prediksi bisa diakses pengguna atau sistem lain, entah lewat API yang menerima request satu per satu atau lewat proses batch yang tiap malam memproses jutaan baris. Pada chapter penutup section ini kita membungkus model ke endpoint HTTP dengan FastAPI, memahami perbedaan batch dan real-time, serta merapikan fondasi produksi: reproducibility, registry, dan monitoring.

Dari Function ke HTTP Endpoint #

Prediksi pada dasarnya adalah function: input fitur, output hasil. Deployment real-time berarti membuka function tersebut lewat HTTP agar klien mana pun bisa memanggilnya. FastAPI membuat pekerjaan ini ringkas; kita pakai pipeline scaler plus k-NN dari chapter sebelumnya, dengan dua fitur kelopak sebagai input:

python
from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

app = FastAPI()

iris = load_iris()
X = iris.data[:, 2:]  # hanya fitur kelopak: panjang dan lebar
y = iris.target

pipeline = Pipeline([
    ("scaler", StandardScaler()),
    ("model", KNeighborsClassifier(n_neighbors=5)),
])
pipeline.fit(X, y)


class PermintaanPrediksi(BaseModel):
    panjang_kelopak: float
    lebar_kelopak: float


@app.post("/prediksi")
def prediksi(permintaan: PermintaanPrediksi):
    fitur = [[permintaan.panjang_kelopak, permintaan.lebar_kelopak]]
    indeks = pipeline.predict(fitur)[0]
    return {"spesies": iris.target_names[indeks]}


client = TestClient(app)
respons = client.post("/prediksi", json={"panjang_kelopak": 5.1, "lebar_kelopak": 1.8})
print(respons.status_code)
print(respons.json())

Output yang Dihasilkan:

text
200
{'spesies': 'virginica'}

Mari kita bedah bagian-bagian penting kode di atas:

  1. Baris 15-19 (class PermintaanPrediksi(BaseModel)): Pydantic memvalidasi request body. Request tanpa panjang_kelopak, atau dengan tipe string, otomatis ditolak dengan status 422 sebelum menyentuh model.
  2. Baris 22 (@app.post("/prediksi")): decorator FastAPI mendaftarkan function prediksi() sebagai handler HTTP method POST di path /prediksi.
  3. Baris 23-27 (def prediksi(...)): handler menerima objek tervalidasi, membentuk input dua dimensi (pipeline mengharapkan bentuk (n_sampel, n_fitur)), lalu mengembalikan dictionary yang FastAPI serialisasi menjadi JSON.
  4. Baris 30-33 (TestClient(app)): class TestClient memanggil endpoint tanpa menjalankan server sungguhan, cara yang benar untuk menguji aplikasi FastAPI seperti dibahas pada chapter Menulis Test dengan pytest.

Di produksi, aplikasi ini dijalankan dengan server ASGI: uvicorn app:app --reload memulai server development, dan hasil {'spesies': 'virginica'} tadi persis yang akan diterima klien yang mengirim request serupa.

Batch vs Real-Time #

Tidak semua prediksi harus live. Pilihan mode deployment bergantung pada seberapa segar hasil dibutuhkan:

AspekBatchReal-time API
Waktu hasilTerjadwal (tiap malam, tiap jam)Milidetik setelah request
Contoh kasusSkor risiko kredit bulanan, rekomendasi mingguanDeteksi fraud saat transaksi, autocomplete
Beban puncakRata, bisa dijadwalkanMengikuti trafik pengguna, perlu autoscaling
Biaya operasionalRendah, satu cron jobLebih tinggi, server harus selalu hidup
KompleksitasSkrip plus penjadwalValidasi input, logging, monitoring

Skema hibrida juga umum: skor berat dihitung batch tiap malam, lalu API hanya membaca hasilnya, sehingga request real-time tetap cepat tanpa memanggil model.

Latency, Throughput, dan Batching #

Dua angka menggambarkan performa layanan prediksi. Latency adalah waktu satu request dari masuk hingga jawaban keluar, biasanya dalam milidetik. Throughput adalah jumlah request per detik yang mampu dilayani. Keduanya saling tarik-menarik dengan satu senjata sederhana: batching. Memproses 1 request memakan hampir selama memproses 32 request sekaligus untuk model seperti k-NN, sehingga menumpuk request kecil menjadi batch besar menaikkan throughput total dengan mengorbankan latency individu:

StrategiLatency per requestThroughputCocok untuk
Satu-satuTerendahRendahKebutuhan interaktif
Batching kecil (mis. 8-32)Sedikit naikNaik signifikanTrafik tinggi
Batching besar (ratusan)TinggiTertinggiPekerjaan latar belakang

Menentukan titik impasnya adalah pekerjaan pengukuran, bukan tebakan: ukur latency dan throughput pada trafik serupa produksi, lalu putuskan.

Reproducibility Sebelum Deploy #

Model yang dimuat di server harus identik dengan model yang tervalidasi. Dua kebiasaan menjaminnya:

  • Virtual environment per proyek, dibahas pada chapter Membuat Virtual Environment, mengisolasi versi Python dan library server dari mesin pelatih.
  • Pin semua dependensi, dibahas pada chapter Dependency Pinning: requirements.txt dengan versi persis (scikit-learn==1.5.2) menjamin kombinasi Python dan scikit-learn yang sama dengan saat model dibuat, prasyarat file pickle dimuat tanpa kejutan sesuai chapter Model Serialization.

Tanpa keduanya, deployment baru bisa saja membawa versi library berbeda, dan prediksi produksi diam-diam bergeser dari hasil evaluasi tanpa satu pun error yang tercetak.

Setelah Deploy: Registry dan Monitoring #

Pekerjaan tidak selesai saat model online. Praktik industri menambahkan dua lapisan:

  • Model registry: satu tempat terpusat (misalnya MLflow Model Registry atau layanan sejenis) yang mencatat setiap versi model, metadata, status (staging, produksi, diarsipkan), dan siapa yang melatihnya. Registry menjawab pertanyaan “model versi berapa yang sedang melayani trafik sekarang” dalam hitungan detik.
  • Monitoring drift: performa dan sebaran input diawasi terus-menerus. Data drift terjadi ketika pola input berubah (pendapatan rata-rata pelanggan naik setahun kemudian); concept drift ketika hubungan input-output bergeser (selera berubah, penipuan menemukan celah baru). Deteksi drift umumnya membandingkan distribusi fitur dan tingkat error terhadap baseline saat model dirilis, dan drift yang terdeteksi adalah sinyal untuk melatih ulang model dengan data terbaru.

Dengan ini rangkaian section Machine Learning tertutup: dari memahami pola belajar dari data, menyiapkan dataset, merancang fitur, melatih model supervised dan unsupervised, mengevaluasi dengan jujur, merangkai pipeline, menyimpan model, hingga menyajikannya sebagai layanan. Langkah berikutnya di luar section ini adalah memperdalam satu domain nyata dan mengulang siklusnya pada data milik kita sendiri.