Hamilton: Bikin Dataflow dan Pipeline ML yang Rapi dan Gampang Dirawat di Python
Halo temen-temen, ketemu lagi sama aku Ruby. Kali ini aku mau ngajak kalian kenalan sama satu library Python yang menurutku underrated banget tapi manfaatnya gede kalau kalian sering ngurusin data: namanya Hamilton, dibikin sama tim DAGWorks. Kalau kalian pernah punya pipeline data atau feature engineering yang isinya ratusan baris kode berantakan, penuh variabel df1, df2, dffinal, dffinalv2, dan kalian sendiri sampai lupa urutan transformasinya, nah Hamilton ini obatnya.
Ide dasarnya sederhana tapi elegan: setiap fungsi Python adalah satu node di dalam dataflow. Nama fungsi itu jadi nama output-nya, dan parameter fungsi itu jadi dependensinya. Jadi Hamilton bakal baca fungsi-fungsi kalian, nyusun otomatis siapa butuh siapa, terus bikin DAG (Directed Acyclic Graph) yang jelas dan bisa divisualisasikan. Kalian tinggal bilang "aku mau output ini", dan Hamilton yang ngurusin urutan eksekusinya. Keren kan?
Di artikel ini aku bakal bahas dari nol: cara instalasi, konsep dasar nulis transform function, bikin Driver, minta output, ngasih input dan config, visualisasi DAG, sampai gimana cara pakai Hamilton buat feature engineering dan pipeline machine learning beneran. Aku bakal kasih banyak contoh kode yang bisa langsung kalian jalanin. Yuk kita mulai.
Introduction: Kenapa Harus Hamilton?
Sebelum masuk ke kode, aku mau cerita dulu soal masalah yang sering banget kejadian di dunia data. Bayangin kalian lagi ngerjain feature engineering. Awalnya cuma dua tiga transformasi, gampang. Tapi lama-lama tim nambah kolom baru, nambah fitur baru, dan file kalian tumbuh jadi 500 baris kode prosedural. Kode kayak gini punya beberapa penyakit klasik:
- Susah dites. Karena semua nyampur jadi satu skrip panjang, kalian nggak bisa nge-tes satu transformasi doang tanpa jalanin semuanya.
- Susah dibaca. Orang baru yang masuk tim bakal pusing ngikutin alur
dfyang di-overwrite berkali-kali. - Susah dilacak. Kalau ada satu kolom yang nilainya aneh, kalian harus scroll manual buat nyari dari mana asalnya.
- Susah dipakai ulang. Mau pakai satu logika transformasi di project lain? Ya copy-paste, dan mulai bermasalah lagi.
Hamilton nyelesain ini dengan satu paradigma: kalian nulis fungsi murni yang deklaratif. Tiap fungsi cuma tanggung jawab menghasilkan satu hal, dan dia minta inputnya lewat parameter. Contoh gampangnya gini:
import pandas as pd
def spendpersignup(spend: pd.Series, signups: pd.Series) -> pd.Series:
"""Rata-rata biaya marketing per signup."""
return spend / signups
Coba perhatiin. Fungsi ini namanya spendpersignup. Buat Hamilton, itu berarti fungsi ini menghasilkan output bernama spendpersignup. Parameternya spend dan signups, jadi Hamilton ngerti bahwa spendpersignup itu butuh dua node lain yaitu spend dan signups. Kalian nggak perlu nulis kode "panggil ini dulu baru panggil itu". Hamilton yang nyimpulin sendiri dari signature fungsinya.
Karena tiap fungsi itu terisolasi dan punya nama jelas, kalian dapet bonus gratis: kode gampang dites (tinggal panggil fungsinya langsung), gampang dibaca (nama fungsi = nama kolom), gampang dilacak (Hamilton tahu persis lineage tiap output), dan gampang dipakai ulang (import modulnya aja).
Satu hal yang perlu aku garis bawahi: Hamilton itu framework-agnostic soal data. Dia nggak maksa kalian pakai pandas doang. Kalian bisa pakai Series pandas, bisa objek Python biasa, bisa numpy array, bahkan bisa integrasi sama Polars, Dask, Ray, atau Spark. Hamilton fokusnya di orkestrasi dependensi antar fungsi, bukan di mesin komputasinya. Jadi dia ringan banget dan nggak maksa kalian ikut ekosistem tertentu.
Instalasi
Instalasinya gampang banget. Nama package-nya bukan hamilton ya temen-temen, tapi sf-hamilton. Ini penting karena nama hamilton di PyPI itu udah dipakai package lain. Jalanin aja:
pip install sf-hamilton
Kalau kalian mau fitur visualisasi DAG (yang menurutku wajib banget dicoba), install juga extra-nya:
pip install "sf-hamilton[visualization]"
Ini bakal narik graphviz sebagai dependensi Python. Tapi inget, kalian juga butuh binary Graphviz terpasang di sistem. Di Ubuntu/Debian tinggal:
sudo apt-get install graphviz
Kalau di Mac pakai Homebrew:
brew install graphviz
Buat yang mau coba integrasi lain, Hamilton punya banyak extra. Misalnya buat integrasi dengan berbagai backend eksekusi:
pip install "sf-hamilton[ray]" # eksekusi paralel pakai Ray
pip install "sf-hamilton[dask]" # eksekusi terdistribusi pakai Dask
Buat ngecek instalasi berhasil, coba jalanin ini di Python:
import hamilton
print(hamilton.version)
Nah perhatiin lagi, walaupun package-nya sf-hamilton, waktu import kalian tetap pakai import hamilton. Ini sering bikin bingung orang baru, jadi aku tekankan sekali lagi biar kalian nggak salah.
Aku saranin pakai virtual environment ya, biar rapi:
python -m venv venv
source venv/bin/activate # kalau Windows: venv\Scripts\activate
pip install "sf-hamilton[visualization]"
Basic Usage: Node, Modul, dan Driver
Oke, sekarang kita masuk ke inti Hamilton. Ada tiga konsep utama yang harus kalian pahamin: fungsi transform (node), modul, dan Driver.
Nulis Fungsi Transform di Modul
Di Hamilton, kalian nulis fungsi-fungsi transform kalian di sebuah file Python terpisah, yang biasa disebut modul dataflow. Ini penting karena Hamilton bakal nge-scan modul itu buat nyari semua fungsi dan nyusun DAG-nya. Yuk kita bikin file namanya functions.py:
# functions.py
import pandas as pd
def avg3wkspend(spend: pd.Series) -> pd.Series:
"""Rolling average pengeluaran 3 minggu."""
return spend.rolling(3).mean()
def spendpersignup(spend: pd.Series, signups: pd.Series) -> pd.Series:
"""Biaya per signup tiap minggu."""
return spend / signups
def spendmean(spend: pd.Series) -> float:
"""Rata-rata pengeluaran keseluruhan."""
return spend.mean()
def spendzeromean(spend: pd.Series, spendmean: float) -> pd.Series:
"""Pengeluaran yang di-center ke nol (dikurangi mean)."""
return spend - spendmean
def spendstddev(spend: pd.Series) -> float:
"""Standar deviasi pengeluaran."""
return spend.std()
def spendzeromeanunitvariance(
spendzeromean: pd.Series, spendstddev: float
) -> pd.Series:
"""Pengeluaran yang sudah dinormalisasi (standarisasi)."""
return spendzeromean / spendstddev
Coba perhatiin baik-baik alurnya. Fungsi spendzeromean butuh dua input: spend dan spendmean. Nah spendmean itu bukan data mentah, tapi output dari fungsi spendmean yang ada di atasnya. Hamilton otomatis nyambungin ini. Terus spendzeromeanunitvariance butuh spendzeromean (output fungsi lain) dan spendstddev (output fungsi lain juga). Jadi kalian lihat kan, cuma dari nama parameter dan nama fungsi, Hamilton bisa nyusun rantai dependensi yang panjang.
Yang jadi input mentah (yang harus kalian sediakan dari luar) itu adalah spend dan signups, karena nggak ada fungsi yang namanya spend atau signups. Hamilton nyebut input semacam ini sebagai node yang kalian isi lewat data eksternal.
Bikin Driver dan Minta Output
Sekarang kita bikin skrip utama buat ngejalanin dataflow ini. Namanya run.py:
# run.py
import pandas as pd
from hamilton import driver
import functions # modul yang tadi kita bikin
1. Bangun Driver dari modul
dr = (
driver.Builder()
.withmodules(functions)
.build()
)
2. Siapkan data input mentah
initialdata = {
"spend": pd.Series([10, 10, 20, 40, 40, 50]),
"signups": pd.Series([1, 10, 50, 100, 200, 400]),
}
3. Tentukan output apa yang kita mau
outputcolumns = [
"spend",
"signups",
"avg3wkspend",
"spendpersignup",
"spendzeromeanunitvariance",
]
4. Eksekusi
df = dr.execute(outputcolumns, inputs=initialdata)
print(df)
Jalanin python run.py, dan Hamilton bakal:
functions, kumpulin semua fungsi jadi node.outputcolumns).Poin nomor 4 itu penting banget dan sering bikin orang kagum. Kalau kalian cuma minta spendpersignup, Hamilton nggak bakal repot-repot ngitung avg3wkspend atau spendstddev. Dia cuma jalanin yang relevan sama output yang kalian minta. Jadi efisien, nggak buang-buang komputasi.
Aku pakai driver.Builder() di sini, yang merupakan cara modern dan direkomendasikan sekarang. Dulu ada cara lama pakai driver.Driver(config, module) langsung, tapi pola Builder ini jauh lebih fleksibel dan enak dibaca, jadi aku saranin kalian pakai ini aja.
Ngerti Output DataFrame
Waktu kalian panggil dr.execute(outputcolumns, ...) dan output-nya campuran Series pandas, Hamilton secara default bakal nge-join semuanya jadi satu DataFrame berdasarkan index. Kolomnya sesuai nama node yang kalian minta. Jadi hasilnya kira-kira gini:
spend signups avg3wkspend spendpersignup spendzeromeanunitvariance
0 10 1 NaN 10.000000 -1.064581
1 10 10 NaN 1.000000 -1.064581
2 20 50 13.333333 0.400000 -0.483900
...
Kalau output yang kalian minta bukan Series (misalnya scalar float kayak spendmean), kalian bisa atur cara Hamilton nyusun output-nya lewat yang namanya resultbuilder, tapi itu bakal aku bahas di bagian advanced.
Advanced Usage: Config, Visualisasi, dan Result Builder
Setelah paham dasarnya, sekarang kita naik level. Bagian ini bakal ngebahas fitur-fitur yang bikin Hamilton beneran powerful buat production.
Ngasih Config buat Ngatur Struktur DAG
Ada perbedaan penting antara inputs dan config di Hamilton:
- inputs: data yang berubah tiap kali eksekusi (misalnya DataFrame yang beda tiap run).
- config: nilai yang menentukan bentuk DAG itu sendiri, dikasih waktu bangun Driver, bukan waktu eksekusi.
Config berguna banget kalau kalian mau punya cabang logika yang beda-beda. Misalnya, kalian mau logika transformasi berbeda antara data harian dan mingguan. Hamilton punya decorator @config.when buat ini:
# functions.py (lanjutan)
from hamilton.functionmodifiers import config
@config.when(datasource="production")
def rawdataprod(dbconnection: object) -> pd.DataFrame:
"""Ambil data dari database produksi."""
return pd.readsql("SELECT FROM events", dbconnection)
@config.when(datasource="testing")
def rawdatatest() -> pd.DataFrame:
"""Data dummy buat testing."""
return pd.DataFrame({"value": [1, 2, 3]})
Perhatiin ada prod dan _test di belakang nama fungsi. Itu namanya name-mangling. Hamilton bakal ngebuang bagian setelah double-underscore, jadi kedua fungsi itu sama-sama menghasilkan node bernama rawdata. Bedanya, cuma satu yang aktif tergantung config yang kalian kasih:
dr = (
driver.Builder()
.withconfig({"datasource": "testing"})
.withmodules(functions)
.build()
)
Dengan config datasource="testing", cuma fungsi rawdatatest yang masuk ke DAG. Ini pola yang keren banget buat bikin satu codebase yang bisa jalan di environment berbeda tanpa if-else berserakan.
Visualisasi DAG
Nah ini fitur favoritku. Hamilton bisa gambarin DAG kalian jadi diagram visual. Ini luar biasa membantu buat dokumentasi, debugging, dan onboarding orang baru. Syaratnya kalian udah install extra [visualization] dan binary graphviz tadi.
# Visualisasikan seluruh DAG dan simpan ke file
dr.displayallfunctions("mydag.png")
Visualisasikan cuma jalur yang dibutuhkan buat output tertentu
dr.visualizeexecution(
finalvars=["spendzeromeanunitvariance"],
outputfilepath="executionpath.png",
inputs={"spend": pd.Series([1, 2, 3]), "signups": pd.Series([1, 2, 3])},
)
displayallfunctions bakal gambarin semua node dan koneksinya. Sementara visualizeexecution cuma nampilin node yang bakal beneran dieksekusi buat menghasilkan output yang kalian minta. Aku sering pakai yang kedua ini buat mastiin pipeline-ku nggak jalanin komputasi yang nggak perlu. Kalian bisa lihat sendiri secara visual jalur mana yang aktif.
Kalau kalian kerja di Jupyter notebook, output visualisasi ini bahkan langsung ke-render inline. Jadi kalian bisa iterasi cepet sambil lihat bentuk DAG-nya real-time.
Result Builder: Ngatur Bentuk Output
Secara default Hamilton nge-join output jadi DataFrame pandas. Tapi kadang kalian nggak mau itu. Mungkin kalian mau output berupa dictionary, atau numpy array, atau tetap DataFrame tapi dengan aturan tertentu. Di sinilah resultbuilder masuk:
from hamilton import base, driver
Output sebagai dictionary
dr = (
driver.Builder()
.withmodules(functions)
.withadapters(base.DictResult())
.build()
)
result = dr.execute(["spendmean", "spendstddev"], inputs=initialdata)
print(result)
{'spendmean': 28.33, 'spendstddev': 17.51}
base.DictResult() bikin Hamilton ngembaliin dictionary, di mana key-nya nama node dan value-nya hasil komputasi. Ini pas banget kalau output kalian campuran tipe (ada scalar, ada Series, ada objek model). Ada juga base.PandasDataFrameResult() (default) dan base.NumpyMatrixResult() kalau kalian butuh format lain.
Decorator yang Sering Dipakai
Hamilton punya banyak decorator buat bikin kode kalian makin ringkas. Aku bahas beberapa yang paling sering aku pakai.
@tag buat ngasih metadata ke node, berguna buat filtering dan dokumentasi:
from hamilton.functionmodifiers import tag
@tag(owner="data-team", stage="production")
def revenue(price: pd.Series, quantity: pd.Series) -> pd.Series:
return price
quantity
@extractcolumns buat mecah satu DataFrame jadi beberapa node kolom sekaligus. Ini super berguna di awal pipeline:
from hamilton.functionmodifiers import extractcolumns
@extractcolumns("spend", "signups", "region")
def loadrawdata(datapath: str) -> pd.DataFrame:
"""Load data dan langsung pecah kolomnya jadi node terpisah."""
return pd.readcsv(datapath)
Dengan @extractcolumns, setelah loadrawdata jalan, Hamilton otomatis bikin node spend, signups, dan region yang masing-masing bisa jadi dependensi fungsi lain. Jadi kalian nggak perlu nulis fungsi terpisah buat ekstrak tiap kolom.
@parameterize buat bikin banyak node mirip dari satu fungsi template, mengurangi duplikasi:
from hamilton.functionmodifiers import parameterize, source
@parameterize(
spendrolling3=dict(window=source("window3")),
spendrolling7=dict(window=source("window7")),
)
def spendrolling(spend: pd.Series, window: int) -> pd.Series:
return spend.rolling(window).mean()
Ini bakal generate dua node: spendrolling3 dan spendrolling7, dari satu definisi fungsi. Bayangin kalau kalian butuh 10 window berbeda, decorator ini nyelametin kalian dari nulis 10 fungsi yang hampir sama.
Materializer: Baca dan Tulis Data Otomatis
Buat pipeline production, kalian sering butuh baca dari sumber data dan nulis hasil ke suatu tempat. Hamilton punya konsep materializer lewat to dan from yang ngurusin I/O ini secara deklaratif:
from hamilton.io.materialization import to
from hamilton import driver
dr = driver.Builder().withmodules(functions).build()
Eksekusi sekaligus simpan output ke CSV
materializers = [
to.csv(
path="./output/features.csv",
id="featurestocsv",
dependencies=["spendpersignup", "avg3wkspend"],
)
]
dr.materialize(*materializers, inputs=initialdata)
Dengan materializer, logika penyimpanan output kepisah dari logika transformasi. Jadi fungsi transform kalian tetap murni dan gampang dites, sementara urusan "simpan ke mana" diatur di level Driver.
Feature Engineering dan Pipeline ML
Sekarang bagian yang paling seru, yaitu gimana kita pakai Hamilton buat kasus nyata: feature engineering dan machine learning. Ini area di mana Hamilton beneran bersinar.
Feature Engineering yang Terstruktur
Salah satu alasan utama Hamilton dibuat (fun fact: awalnya diciptakan di Stitch Fix buat ngurusin ribuan fitur time-series) adalah feature engineering. Coba kita bikin modul fitur:
# features.py
import pandas as pd
import numpy as np
from hamilton.functionmodifiers import extractcolumns
@extractcolumns("age", "income", "purchases", "dayssincesignup")
def rawcustomers(datapath: str) -> pd.DataFrame:
return pd.readcsv(datapath)
def incomelog(income: pd.Series) -> pd.Series:
"""Log transform buat income yang skewed."""
return np.log1p(income)
def agebucket(age: pd.Series) -> pd.Series:
"""Kelompokkan umur jadi bucket kategori."""
return pd.cut(age, bins=[0, 25, 40, 60, 120],
labels=["muda", "dewasa", "matang", "senior"])
def purchasefrequency(purchases: pd.Series, dayssincesignup: pd.Series) -> pd.Series:
"""Frekuensi pembelian per hari sejak signup."""
return purchases / dayssincesignup.clip(lower=1)
def highvalueflag(income: pd.Series, purchases: pd.Series) -> pd.Series:
"""Flag pelanggan bernilai tinggi."""
return ((income > income.median()) & (purchases > purchases.median())).astype(int)
Lihat betapa bersihnya ini. Tiap fitur adalah satu fungsi mandiri dengan nama yang jelas. Kalau nanti data scientist lain mau nambah fitur baru, dia tinggal nulis fungsi baru tanpa nyentuh yang lama. Dan yang paling penting, tiap fitur bisa dites satuan:
def testpurchasefrequency():
purchases = pd.Series([10, 20])
days = pd.Series([5, 10])
result = purchasefrequency(purchases, days)
assert result.tolist() == [2.0, 2.0]
Nggak perlu setup pipeline gede cuma buat nge-tes satu fitur. Panggil fungsinya langsung, kasih input, cek output. Simpel.
Pipeline ML End-to-End
Sekarang kita bikin pipeline machine learning lengkap dari raw data sampai model terlatih. Hamilton bisa nampung seluruh alur ini dalam satu DAG yang koheren:
# mlpipeline.py
import pandas as pd
from sklearn.modelselection import traintestsplit
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracyscore
from hamilton.functionmodifiers import extractcolumns
@extractcolumns("feature1", "feature2", "feature3", "target")
def dataset(datapath: str) -> pd.DataFrame:
return pd.readcsv(datapath)
def featurematrix(
feature1: pd.Series, feature2: pd.Series, feature3: pd.Series
) -> pd.DataFrame:
"""Gabungkan fitur jadi matriks X."""
return pd.concat([feature1, feature2, feature3], axis=1)
def traintestdata(
featurematrix: pd.DataFrame, target: pd.Series, testsize: float, randomstate: int
) -> dict:
"""Split data jadi train dan test."""
Xtrain, Xtest, ytrain, ytest = traintestsplit(
featurematrix, target, testsize=testsize, randomstate=randomstate
)
return {"Xtrain": Xtrain, "Xtest": Xtest, "ytrain": ytrain, "ytest": ytest}
def fittedmodel(traintestdata: dict, nestimators: int) -> RandomForestClassifier:
"""Latih Random Forest."""
model = RandomForestClassifier(nestimators=nestimators, randomstate=42)
model.fit(traintestdata["Xtrain"], traintestdata["ytrain"])
return model
def predictions(fittedmodel: RandomForestClassifier, traintestdata: dict) -> pd.Series:
"""Prediksi di data test."""
return pd.Series(fittedmodel.predict(traintestdata["Xtest"]))
def modelaccuracy(predictions: pd.Series, traintestdata: dict) -> float:
"""Hitung akurasi model."""
return accuracyscore(traintestdata["ytest"], predictions)
Dan skrip buat ngejalaninnya:
# runml.py
from hamilton import base, driver
import mlpipeline
dr = (
driver.Builder()
.withmodules(mlpipeline)
.withadapters(base.DictResult())
.build()
)
results = dr.execute(
["fittedmodel", "modelaccuracy", "predictions"],
inputs={
"datapath": "customers.csv",
"testsize": 0.2,
"randomstate": 42,
"nestimators": 100,
},
)
print("Akurasi:", results["modelaccuracy"])
model = results["fittedmodel"] # model siap dipakai/disimpan
Coba resapi struktur ini. Seluruh pipeline ML, dari load data, bikin fitur, split, training, sampai evaluasi, semuanya jadi fungsi-fungsi kecil yang saling terhubung lewat DAG. Kalian bisa minta output di titik mana aja. Mau cuma model terlatih tanpa evaluasi? Minta fittedmodel aja. Mau lihat akurasi? Minta modelaccuracy. Hamilton ngitung persis yang dibutuhin.
Perhatiin juga aku pakai nestimators, testsize, randomstate sebagai input. Ini bikin hyperparameter kalian eksplisit dan gampang diubah. Mau eksperimen dengan nestimators=500? Ganti satu angka di input, DAG-nya tetap sama. Ini bikin eksperimen jadi reproducible dan rapi.
Dan tentu aja, kalian bisa visualisasikan seluruh pipeline ML ini:
dr.visualizeexecution(
final
vars=["modelaccuracy"],
output
filepath="mldag.png",
inputs={"datapath": "customers.csv", "testsize": 0.2,
"randomstate": 42, "nestimators": 100},
)
Bayangin kalian nunjukin diagram ini ke stakeholder atau tim baru. Mereka langsung ngerti alur pipeline tanpa harus baca kode satu per satu. Ini nilai jual Hamilton yang gede banget buat kolaborasi tim.
Best Practices
Setelah aku pakai Hamilton di beberapa project, ada beberapa best practice yang mau aku bagi ke kalian biar nggak jatuh ke lubang yang sama.
1. Jaga fungsi tetap murni (pure). Fungsi transform kalian idealnya cuma bergantung ke parameternya dan nggak punya side effect. Jangan baca file atau global variable di dalam fungsi transform kecuali itu emang node input. Fungsi murni bikin DAG-nya predictable dan gampang dites. 2. Kasih type hint yang jelas. Hamilton pakai type hint bukan cuma buat dokumentasi, tapi juga buat validasi. Kalau kalian tulis-> pd.Series, Hamilton bisa cek apakah output-nya beneran Series. Type hint yang benar bikin error ketahuan lebih awal.
3. Nama fungsi = nama fitur yang bermakna. Karena nama fungsi jadi nama node, kasih nama yang deskriptif. spendpersignup jauh lebih jelas daripada sps atau feature12. Ini investasi kecil yang kebayar besar waktu maintenance.
4. Pecah modul berdasarkan domain. Kalau pipeline kalian gede, jangan tumpuk semua fungsi di satu file. Pisah jadi dataloading.py, features.py, model.py. Driver bisa nerima banyak modul sekaligus:
dr = (
driver.Builder()
.withmodules(dataloading, features, model)
.build()
)
Hamilton bakal gabungin semua node dari semua modul jadi satu DAG. Jadi kalian bisa organize kode dengan rapi tanpa kehilangan koneksi antar node.
5. Manfaatin testing satuan. Ini keunggulan terbesar Hamilton. Karena tiap fungsi terisolasi, tulis unit test buat logika-logika penting. Kalian bakal tidur lebih nyenyak tahu tiap transformasi udah tervalidasi. 6. Pakai@config.when buat variasi environment, bukan if-else di dalam fungsi. Kalau kalian butuh logika beda buat dev vs prod, pakai config decorator. Ini bikin tiap versi tetap jadi fungsi terpisah yang bersih dan bisa dites sendiri-sendiri.
7. Validasi output pakai @checkoutput. Hamilton punya decorator buat data validation langsung di node:
from hamilton.functionmodifiers import checkoutput
@check
output(range=(0, 1), datatype=float)
def conversion
rate(signups: pd.Series, visits: pd.Series) -> pd.Series:
return signups / visits
Kalau output keluar dari range yang kalian tentukan, Hamilton bakal kasih warning atau error. Ini jaring pengaman yang bagus buat data quality di production.
8. Visualisasikan sebelum deploy. Sebelum naikin pipeline ke production, gambar dulu DAG-nya. Sering banget aku nemuin dependensi yang nggak sengaja kepasang atau node yatim yang nggak kepakai cuma dari lihat diagramnya. 9. Simpan config eksplisit. Kalau pipeline kalian pakai banyak config dan input, simpan di file YAML atau JSON terpisah, jangan hardcode di skrip. Ini bikin pipeline gampang diatur dan di-version. 10. Mulai kecil, kembangin bertahap. Kalian nggak perlu langsung migrasi seluruh codebase ke Hamilton. Mulai dari satu bagian pipeline yang paling berantakan, rasain manfaatnya, baru perluas. Hamilton itu inkremental, jadi santai aja.Conclusion
Oke temen-temen, kita udah keliling cukup jauh soal Hamilton. Aku recap ya poin-poin pentingnya. Hamilton adalah library Python ringan dari DAGWorks yang bikin dataflow dan pipeline kalian jadi rapi lewat satu ide sederhana: setiap fungsi adalah satu node, nama fungsi adalah output, parameter adalah dependensi. Dari situ Hamilton nyusun DAG otomatis, ngeksekusi cuma yang diperlukan, dan ngasih kalian kode yang gampang dites, dibaca, dilacak, dan dipakai ulang.
Kita udah bahas cara install (pip install sf-hamilton, inget import-nya tetap hamilton), cara nulis fungsi transform di modul, bikin Driver pakai Builder, minta output pakai execute, bedain inputs dan config, visualisasi DAG, sampai pakai decorator kayak @extractcolumns, @parameterize, @config.when, dan @checkoutput. Terus kita praktik langsung bikin feature engineering yang terstruktur dan pipeline ML end-to-end dari raw data sampai model terlatih.
Menurutku, kekuatan terbesar Hamilton itu bukan di fitur canggihnya, tapi di disiplin yang dia paksain. Dia bikin kalian nulis kode data yang terstruktur secara alami, tanpa harus mikirin arsitektur ribet. Kalau tim kalian sering berantem soal pipeline yang susah dirawat, coba deh Hamilton. Aku yakin kalian bakal ngerasain bedanya, terutama waktu ada anggota tim baru yang bisa langsung paham alur data cuma dari lihat DAG-nya.
Segitu dulu dari aku. Coba langsung praktikin ya, karena belajar library kayak gini paling cepet lewat ngoding langsung. Kalau kalian nemu pola menarik atau ada pertanyaan, jangan ragu buat eksplor dokumentasi resmi Hamilton yang menurutku lengkap banget. Semangat terus belajar dan bikin pipeline yang rapi. Sampai ketemu di tutorial berikutnya. Happy coding temen-temen!