الدرس 8 من 9

Feature Engineering و Pipelines

الفرق بين موديل عادي وموديل ممتاز غالباً بيبقى هنا.

النصوص لأرقام: One-Hot Encoding

الموديل مبيفهمش «Cairo». ممكن تقول Cairo=1 و Giza=2 و Alexandria=3؟ لأ، كده الموديل هيفهم إن إسكندرية «أكبر» من القاهرة، وده مالوش معنى. الحل: عمود لكل مدينة فيه ١ أو ٠.

onehot.py
import pandas as pd

df = pd.DataFrame({"city": ["Cairo", "Giza", "Alexandria", "Cairo"]})
print(pd.get_dummies(df, columns=["city"], dtype=int))

اعمل features جديدة من خبرتك

انت فاهم المجال أكتر من الموديل. عمود زي «المساحة لكل أوضة» أو «قريب من المترو؟» ممكن يساعد الموديل أكتر من الأعمدة الخام. وفي التواريخ: اليوم في الأسبوع، والشهر، وهل هو إجازة، كلها features مفيدة جداً.

⚠ الـ Data Leakageأخطر غلطة: feature فيها معلومة من المستقبل أو من الإجابة نفسها. مثلاً في موديل التسعير تضيف «السعر لكل متر»، اللي محسوب من السعر أصلاً! الموديل هيبان عبقري في الـ test، ويفشل تماماً في الحقيقة لأن العمود ده مش هيبقى موجود. اسأل نفسك دايماً: هل المعلومة دي هتبقى معايا وقت التوقع؟

الـ Pipeline: كل الخطوات في حتة واحدة

الـ Pipeline بيربط التجهيز والموديل في object واحد. ليه ده مهم؟ لأن الـ scaling مثلاً لازم يتعلم المتوسط من الـ train بس، مش من الداتا كلها، وإلا يبقى leakage. الـ Pipeline بيعمل ده صح لوحده، وكمان بتحفظه وتستخدمه في الإنتاج كحتة واحدة.

pipeline.py
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error

df = pd.read_csv("apartments.csv")
numeric = ["area", "rooms", "floor", "age", "metro_km"]
categorical = ["city"]

X_train, X_test, y_train, y_test = train_test_split(
    df[numeric + categorical], df["price_k"], test_size=0.2, random_state=42)

prep = ColumnTransformer([
    ("num", StandardScaler(), numeric),                          # scale numbers
    ("cat", OneHotEncoder(handle_unknown="ignore"), categorical), # encode text
])
pipe = Pipeline([("prep", prep), ("model", LinearRegression())])

pipe.fit(X_train, y_train)
mae = mean_absolute_error(y_test, pipe.predict(X_test))
print(f"MAE with city: {mae:.0f}K EGP")

الغلط نزل من حوالي ٢٨٥ ألف لـ ١٨٤ ألف، يعني أقل بأكتر من الربع، وده من مجرد إننا ضفنا المدينة بطريقة صح. ده معنى إن Feature Engineering غالباً بيفرق أكتر من تغيير الموديل.

احفظ الموديل واستخدمه بعدين

save_model.py
import joblib
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LinearRegression

df = pd.read_csv("apartments.csv")
cols = ["area", "rooms", "floor", "age", "metro_km", "city"]
pipe = Pipeline([
    ("prep", ColumnTransformer([("cat", OneHotEncoder(), ["city"])],
                               remainder="passthrough")),
    ("model", LinearRegression()),
]).fit(df[cols], df["price_k"])

joblib.dump(pipe, "price_model.joblib")        # save to disk

loaded = joblib.load("price_model.joblib")     # later, in another program
flat = pd.DataFrame([{"area": 130, "rooms": 3, "floor": 4, "age": 5,
                      "metro_km": 1.2, "city": "Cairo"}])
print(f"Cairo flat: {loaded.predict(flat)[0]:,.0f}K EGP")
🚀 الخطوة الجاية للملف دهالملف price_model.joblib ده في المرحلة ٨ هنحطه ورا API بـ FastAPI، فأي تطبيق أو موقع يبعتله بيانات شقة ويرجعله السعر. كده الموديل يطلع من الـ notebook للعالم.
الدرس اللي فات