Belajar ML Engineer - Versioning (Code, Data, Model)
Episode 8 of 28

Belajar ML Engineer - Versioning (Code, Data, Model)

Menjadikan proyek ML benar-benar reproducible: git untuk kode, DVC untuk data, dan model registry untuk artifact — lalu menghubungkan ketiganya dalam satu lineage sehingga setiap model bisa ditelusuri ke dataset dan kode yang memproduksinya

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 6 kita melacak eksperimen dan di episode 7 mengevaluasi secara jujur, kini kita menutup lubang yang paling sering mengubah proyek ML menjadi mimpi buruk: reproduksibilitas. Pernahkah kalian mendapat laporan "model produksi error, tapi aku tidak bisa menjelaskan dari mana model itu dibuat"? Itu terjadi karena kode, data, dan model di-versioning secara terpisah — atau tidak di-versioning sama sekali.

Software engineering sudah lama memecahkan ini dengan git untuk kode. Masalah ML lebih sulit karena ada dua hal lain yang ikut berubah: data (yang bisa sebesar ratusan GB, tidak cocok masuk git) dan model (artifact hasil training). Episode ini membangun lineage utuh: menghubungkan kode, data, dan model sehingga setiap artifact bisa ditelusuri balik ke sumbernya.

Kode: Git + Reproducible Environment

Kode dulu selalu masuk git. Untuk ML, ada tambahan penting: environment harus ikut ter-versioning. requirements.txt atau lockfile (uv/pip-tools) harus di-commit agar tiga bulan lagi kalian bisa membuat environment yang sama persis.

text
# requirements.lock (di-commit ke git)
numpy==1.26.4
pandas==2.2.2
scikit-learn==1.5.0
torch==2.4.1

Tanpa pin versi, "works on my machine" menjadi "works on my machine last month" — sumber frustrasi terbesar di tim ML.

Data: DVC (Data Version Control)

Data tidak bisa masuk git (terlalu besar), tapi harus tetap bisa di-versioning. DVC memecahkannya dengan trik elegan: file data besar disimpan di penyimpanan eksternal (S3, GCS, remote server), sedangkan git hanya menyimpan metadata ringan yang menunjuk ke versi data.

Inisialisasi DVC dan track data
dvc init
dvc remote add -d storage s3://my-bucket/ml-data
dvc add data/raw_events.parquet

File data/raw_events.parquet.dvc yang dihasilkan berisi hash file data — masuk git. Saat data berubah, hash berubah, dan riwayat data ikut di git:

Cek versi data
git log --oneline -- data/raw_events.parquet.dvc
dvc checkout   # restore data sesuai versi git aktif

Kekuatan utama DVC: satu git commit = satu state kode + data yang konsisten. Checkout commit lama, jalankan dvc checkout, dan kalian punya data yang persis seperti dulu.

Meminimalisir "Data Tetangga Berubah"

Praktik yang disarankan: data mentah bersifat immutabel (read-only, tak pernah diubah di tempat). Transformasi menghasilkan data turunan ber-version. Ini mencegah masalah klasik: seseorang mengubah kolom di file CSV produksi tanpa ada yang tahu.

Model: Model Registry sebagai Versioning Artifact

Di episode 6 kita sudah mengenalkan model registry. Dari sisi versioning, registry menyimpan versi model + lineage:

Mencatat lineage saat register
import mlflow
 
with mlflow.start_run() as run:
    mlflow.log_param("dataset_version", "v3")        # hash data dari DVC
    mlflow.log_param("git_commit", "abc123f")        # versi kode
    mlflow.log_param("feature_pipeline", "v2")
    mlflow.log_metric("roc_auc", 0.824)
    mlflow.register_model("runs:/<RUN_ID>/model", "churn-predictor")

Dengan ini, setiap model versi v5 di registry bisa menjawab tiga pertanyaan: data apa yang dipakai? kode versi apa? hyperparameter apa?

Lineage: Menghubungkan Semua Bagian

100%

Lineage yang utuh memungkinkan reproduksi penuh: dari model live, kalian menelusuri ke run, ke commit kode, ke versi data, lalu menjalankan ulang training untuk memverifikasi hasil yang sama.

Praktik Reproducibility di Proyek Nyata

Alur kerja yang sudah terbukti di lapangan:

  1. Pin semua dependensi dengan lockfile yang di-commit.
  2. Track data mentah & turunan dengan DVC; data mentah immutabel.
  3. Set seed deterministik di semua komponen yang punya random (random_state, torch.manual_seed).
  4. Catat versi data + kode + environment ke setiap eksperimen (MLflow).
  5. Satu git commit harus mereproduksi satu model — kode, data, env-nya lengkap.

Verifikasi periodik: simpan satu set commit, lalu jalankan ulang pipeline setahun kemudian. Jika hasilnya tidak sama, sistem reproducibility-nya masih bocor.

Reproduksi penuh dari commit
git checkout v1.4.2
dvc checkout
uv sync --locked
python -m src.train

Warning

Randomness adalah musuh reproducibility. GPU (khususnya operasi seperti cuDNN) tidak deterministik secara penuh, dan perbedaan kecil pun bisa memengaruhi hasil. Tujuan praktis bukan determinisme bit-perfect, melainkan stabilitas yang cukup sehingga hasil training tidak berubah dramatis tanpa perubahan yang jelas.

Common Pitfalls

PitfallDampakPencegahan
pip install tanpa pin versiEnvironment tidak reproducibleLockfile + --locked
Data diubah di tempat tanpa versioningHasil training tidak bisa ditelusuriData mentah immutabel + DVC
Model disimpan model_final.pkl begitu sajaTidak tahu dari run manaRegistry dengan lineage
Hash data tidak dicatat di eksperimenModel tidak terhubung ke datalog_param("dataset_version", ...)
Tanpa seedDua run identik hasil bedaSet seed deterministik

Penutup

Pada episode 8 ini, kalian telah membangun sistem reproduksibilitas penuh:

  • Kode & environment di-versioning dengan git + lockfile.
  • Data di-versioning dengan DVC (metadata di git, blob di remote storage); data mentah immutabel.
  • Model di-versioning dengan registry + lineage (commit, dataset hash, hyperparameter).
  • Lineage menghubungkan ketiganya sehingga setiap model bisa direproduksi dari commit.

Di episode 9 selanjutnya kita akan membahas Containerization & Serving — mengemas model ke Docker, memilih framework serving (Triton, Seldon, BentoML), dan menyajikan prediksi lewat REST maupun gRPC dengan latensi dan throughput yang terukur. Sampai jumpa di episode 9!

Belajar ML Engineer - Versioning (Code, Data, Model) | Belajar ML Engineer