أساسيات MLOps
لما يبقى عندك ٥٠ تجربة و ١٠ نسخ من الموديل، محتاج نظام.
يعني إيه MLOps؟
زي ما الـ DevOps بيخلي نشر البرامج منظم وأوتوماتيك، الـ MLOps بيعمل نفس الحكاية للموديلات. بس الموديلات أصعب: عندك كود وداتا وموديل، والتلاتة بيتغيروا، وأي واحد فيهم ممكن يبوظ النتيجة.
تتبع التجارب بـ MLflow
جربت ١٠ إعدادات مختلفة الأسبوع اللي فات، أنهي واحدة كانت أحسن؟ وكانت بأنهي داتا؟ لو معتمد على ذاكرتك أو على ورقة، هتتوه. MLflow بيسجل كل تجربة: الإعدادات والنتايج والموديل نفسه.
import mlflow import pandas as pd from sklearn.compose import ColumnTransformer from sklearn.linear_model import Ridge from sklearn.metrics import mean_absolute_error from sklearn.model_selection import train_test_split from sklearn.pipeline import Pipeline from sklearn.preprocessing import OneHotEncoder, StandardScaler mlflow.set_tracking_uri("sqlite:///mlflow.db") # local tracking database mlflow.set_experiment("apartment-prices") df = pd.read_csv("apartments.csv") num, cat = ["area", "rooms", "floor", "age", "metro_km"], ["city"] X_tr, X_te, y_tr, y_te = train_test_split(df[num + cat], df["price_k"], test_size=0.2, random_state=42) for alpha in [0.1, 10, 100, 1000]: # try 4 settings with mlflow.start_run(run_name=f"ridge-{alpha}"): pipe = Pipeline([ ("prep", ColumnTransformer([("num", StandardScaler(), num), ("cat", OneHotEncoder(), cat)])), ("model", Ridge(alpha=alpha)), ]).fit(X_tr, y_tr) mae = mean_absolute_error(y_te, pipe.predict(X_te)) mlflow.log_param("alpha", alpha) # what you tried mlflow.log_metric("mae_k", mae) # how it did runs = mlflow.search_runs(order_by=["metrics.mae_k ASC"]) print(runs[["params.alpha", "metrics.mae_k"]].round(1).to_string(index=False))
كل التجارب اتسجلت ومترتبة من الأحسن للأسوأ. ولو شغلت mlflow ui --backend-store-uri sqlite:///mlflow.db هتفتحلك صفحة تقارن فيها التجارب بالرسوم. وRidge هنا هو Linear Regression ومعاه regularization: كل ما الـ alpha تكبر، بيعاقب الأوزان الكبيرة أكتر. وواضح إن الـ alpha الكبيرة زيادة بوظت الموديل.
الأتمتة: CI بـ GitHub Actions
CI (Continuous Integration) يعني مع كل push على GitHub، الـ tests بتتشغل أوتوماتيك. لو حد بوّظ حاجة، هتعرف في دقيقة، قبل ما توصل للإنتاج:
name: tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -r requirements.txt pytest
- run: python train.py # train a fresh model
- run: pytest -q # then run all the testsنسخ الموديل
- كل موديل ليه رقم نسخة، ومعاه النتايج بتاعته والداتا اللي اتدرب عليها.
- النسخة الجديدة متتنشرش غير لو غلبت القديمة على نفس الـ test set.
- خلي النسخة القديمة جاهزة عشان ترجعلها في دقيقة لو الجديدة عملت مشكلة (rollback).