كورس ML · الدرس 2
Zero Grad · كورس Machine Learning — الدرس التاني

Linear Regression

إزاي الموديل يتعلم سعر العربية من الداتا؟
هنمشي ورا السبورة خطوة خطوة، بنفس مثال المحاضرة: Car Pricing.
كل جزء ليه نسختين: نسخة منظمة تذاكر منها، والسبورة الأصلية زي ما اتكتبت.

كلام المحاضر من السبورة جرّب بنفسك (تفاعلي) إضافة من برا المحاضرة

1الفكرة: معادلة خط

من الرياضة احنا عارفين معادلة الخط: \(y = c + m\,x\)
الـ c هو الـ constant، والـ m هو الـ slope.
في الـ Machine Learning بنكتب نفس المعادلة بأسامي تانية:

\[ y = w_0 + w_1\,x \]
\(y\) — Dependent Variableاللي عايزين نتوقعه (السعر)
Given
\(x\) — Independent Variableالـ feature (الـ power)
Given
\(w_0\) — Bias / Interceptنقطة تقاطع الخط مع محور y
Unknown
\(w_1\) — Weight / Coefficientالميل: \(w_1 = \frac{y_2-y_1}{x_2-x_1}\)
Unknown

الـ x والـ y موجودين معانا في الداتا (جدول فيه m record).
المجهول الوحيد هو الـ weights.
يعني الموديل كله عبارة عن دالة في الداتا:

W = f(X, y)الـ weights بنطلّعها من الداتا

وكلمة Simple معناها إن عندنا feature واحدة بس.
وكل ما الـ correlation بين x و y يبقى أعلى، الخط يمثّل الداتا أحسن.
والتعلّم هنا معناه حاجة واحدة:

Learning ⇒ Find Best Weights
سبورة المحاضر: Supervised ML — Linear Regression
السبورة الأصلية — اضغط على الصورة للتكبير

2Vectorized Form والـ Normal Equation

عندنا m records.
عشان نكتب المعادلة بشكل matrix، بنضيف عمود \(x_0 = 1\) لكل الـ records.
وبكده الـ bias بيدخل في الضرب زي أي weight:

\[ \underset{(m,1)}{y} = w_0\,\underset{(m,1)}{x_0} + w_1\,\underset{(m,1)}{x_1} \]

ولو جمعنا الـ weights في vector واحد \(\mathbf{w} = [w_0,\ w_1]\)،
والـ features في matrix واحدة \(X = [x_0,\ x_1]\):

y = XwVectorized — نفس المعادلة، بس مكتوبة مرة واحدة لكل الـ records

① Ordinary Least Squares (OLS)
بتدينا الـ weights مباشرة، بمعادلة اسمها Normal Equation:

\[ \mathbf{w} = (X^\top X)^{-1} X^\top \mathbf{y} \]

ده Closed Solution.
حسبة واحدة ونطلع بالـ weights، من غير iterations ولا learning rate.

وفي مثال Car Pricing: \(\text{price} = w_0 + w_1 \cdot \text{power}\)
الـ price والـ power معروفين ✓
يبقى \(W = f(\text{power},\ \text{price})\).

➕ إضافة: منين جت الـ Normal Equation؟

عايزين أقل error، يعني نقلل \(J(\mathbf w) = \lVert \mathbf y - X\mathbf w \rVert^2\).
ناخد الـ gradient ونساويه بصفر:

\[ \nabla_{\mathbf w} J = -2X^\top(\mathbf y - X\mathbf w) = 0 \;\Rightarrow\; X^\top X\,\mathbf w = X^\top \mathbf y \;\Rightarrow\; \mathbf w = (X^\top X)^{-1}X^\top \mathbf y \]

الحل ده محتاج إن \(X^\top X\) تكون invertible.
لو فيه features متكررة أو مرتبطة ببعض جامد (multicollinearity)، الحسبة بتبوظ.
وعشان كده LinearRegression في sklearn بتحلها بالـ SVD (pseudo-inverse)، مش بالـ inverse المباشر.

سبورة المحاضر: Vectorized و OLS
السبورة الأصلية — اضغط على الصورة للتكبير

3Find Best Weights: الـ Cost Function

يعني إيه "أحسن" weights؟
يعني Best fit line: الخط اللي بيدينا Min Error بين الـ Actual \((y)\) والـ Prediction \((\hat y)\).
عشان كده بنعرّف Cost Function:

\[ J = \lVert \mathbf y - \hat{\mathbf y} \rVert^2 \qquad\qquad J(\mathbf w) = \frac{1}{2m}\sum_{i=1}^{m}\left(y^{(i)} - \mathbf w^\top x^{(i)}\right)^2 \]

الـ Cost function دي اسمها Mean Squared Error.
والـ \(\frac12\) اللي قدامها مش بتغيّر مكان الـ min، هي بس بتسهّل التفاضل.
هدفنا نلاقي الـ weights اللي تخلّي \(J\) أقل حاجة (Min J).
وفيه طريقين:

Normal Equation

Closed Solution

نحل \(\dfrac{\partial J}{\partial \mathbf w} = 0\) مرة واحدة.
ونطلع بالحل: \(\mathbf w = (X^\top X)^{-1}X^\top \mathbf y\)

Gradient Descent

Iterative Solution

نبدأ من weights عشوائية.
وننزل على منحنى \(J\) خطوة خطوة، لحد ما نوصل للـ Min Error.

سبورة المحاضر: Find Best Weights
السبورة الأصلية — اضغط على الصورة للتكبير

4Gradient Descent خطوة بخطوة

عندنا weights اتنين، يبقى الـ cost دالة في الاتنين:

\[ J(w_0, w_1) = \frac{1}{2m}\sum_{i=1}^{m}\left(y^{(i)} - w_0 - w_1 x^{(i)}\right)^2 \]

وعايزين: find w₀, w₁ → Min J(w)
الخطوات:

  1. Random initialization: نبدأ بـ weights قديمة \((w_0, w_1)\) أي قيم.
  2. Calculate gradients: نحسب \(\dfrac{\partial J}{\partial w_0}\) و \(\dfrac{\partial J}{\partial w_1}\).
    يعني الـ slope عند النقطة اللي احنا فيها.
  3. Update weights: \( w_0^{new} = w_0^{old} - \eta\,\dfrac{\partial J}{\partial w_0} \)، \( w_1^{new} = w_1^{old} - \eta\,\dfrac{\partial J}{\partial w_1} \)
    والـ \(\eta\) هو الـ learning rate.
    ونفضل نكرر (iterate) خطوة 2 و 3.

ليه السالب؟
لو الـ slope موجب، يبقى احنا على يمين الـ min، فبنقلل الـ w.
ولو سالب، يبقى احنا على شماله، فبنزوّدها.
وعند الـ min الـ slope بيبقى صفر \(\left(\frac{\partial J}{\partial w}=0\right)\)، والـ weights بتبطّل تتحرك.

والخبر الحلو: الـ \(J\) في الـ Linear Regression شكلها طبق (Convex).
يعني فيها one global min بس، ومفيش local min ممكن نقع فيه.

➕ إضافة: الـ gradients بالتفصيل

لما نفاضل \(J\)، الـ 2 اللي نازلة من التربيع بتلغي الـ \(\frac12\).
ونطلع بـ:

\[ \frac{\partial J}{\partial w_0} = -\frac{1}{m}\sum_{i=1}^{m}\left(y^{(i)} - \hat y^{(i)}\right) \qquad \frac{\partial J}{\partial w_1} = -\frac{1}{m}\sum_{i=1}^{m}\left(y^{(i)} - \hat y^{(i)}\right)x^{(i)} \]

دي بالظبط الحسبة اللي شغالة في الأداة اللي تحت.

سبورة المحاضر: Gradient Descent
السبورة 3 (الجزء اليمين: Gradient Descent)
سبورة المحاضر: Gradient Descent visualization
السبورة 4 — اضغط على الصورة للتكبير

5Simple vs Multiple Linear Regression

Simple Linear Regression

one feature → line
\[ y = w_0 + w_1 x \]

الـ \(X\) شكلها \((m, 2)\): عمود \(x_0\) كله 1، وعمود \(x_1\).

Multiple Linear Regression

multiple features → hyperplane
\[ y = w_0 + w_1x_1 + w_2x_2 + \dots + w_nx_n \]

الـ \(X\) شكلها \((m, n+1)\): عمود \(x_0\)، و n features.

Same ideas: لسه بنفترض علاقة Linear.
والـ Normal Equation شغالة ✓، والـ Gradient Descent شغال ✓.
الفرق الوحيد إن الـ \(\mathbf w\) بقى فيها weights أكتر.

سبورة المحاضر: Simple vs Multiple
السبورة الأصلية — اضغط على الصورة للتكبير

6OLS ولا Gradient Descent؟

OLS (Normal Equation)Gradient Descent
نوع الحلClosed SolutionIterative Solution
IterationsNo iterationsNeed iterations
Learning rateNo learning rateNeed learning rate
Complexityأعلى ↑ (بتكبر بسرعة مع عدد الـ features)أقل ↓ (أسرع مع الداتا الكبيرة)
Feature scalingمش محتاجمحتاج
في sklearnLinearRegression() (بتستخدم SVD)SGDRegressor (loss = squared error)
Recommendationلحد حوالي \(10^5\) records، والـ features مش كتيرداتا ضخمة جدًا (أكتر من \(10^5\) records)، أو features كتير جدًا

الـ \(10^5\) رقم تقريبي، مش قاعدة ثابتة.
تكلفة الـ OLS بتكبر بسرعة مع عدد الـ features، أكتر من عدد الـ records.
فلو الداتا ضخمة جدًا، أو الـ features كتير جدًا، روح للـ Gradient Descent.

from sklearn.linear_model import LinearRegression, SGDRegressor
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler

# Closed solution (OLS)
ols = LinearRegression()
ols.fit(X_train, y_train)

# Iterative solution: محتاج scaling قبله
sgd = make_pipeline(StandardScaler(),
                    SGDRegressor(loss="squared_error", eta0=0.01, max_iter=1000))
sgd.fit(X_train, y_train)
➕ إضافة
SGDRegressor بيضيف regularization صغير by default (penalty="l2", alpha=0.0001).
عشان كده الـ weights بتاعته ممكن تطلع مختلفة شوية عن LinearRegression.
هنتكلم عن الـ regularization (Ridge / Lasso) بعدين.
سبورة المحاضر: OLS vs Gradient Descent
السبورة 6
سبورة المحاضر: LinearRegression و SGDRegressor
السبورة 7

7Regression Evaluation

Error

No limit: كل ما يقل كل ما أحسن

Mean Squared Error \[ \text{MSE} = \frac1m\sum_{i=1}^{m}\left(y^{(i)}-\hat y^{(i)}\right)^2 \]

Mean Absolute Error \[ \text{MAE} = \frac1m\sum_{i=1}^{m}\left|y^{(i)}-\hat y^{(i)}\right| \]

Root Mean Squared Error \[ \text{RMSE} = \sqrt{\text{MSE}} \]

R² Score

Coefficient of Determination
\[ R^2 = 1 - \frac{\sum_{i}\left(y^{(i)}-\hat y^{(i)}\right)^2}{\sum_{i}\left(y^{(i)}-\bar y\right)^2} \]

بنقراها زي الـ Accuracy: الطبيعي إنها بين 0 و 1.
وكل ما تقرب من 1 كل ما الموديل أحسن، والـ 1 معناها 100%.
بس ممكن تطلع سالبة، لو الموديل أسوأ من الـ Dummy Regressor.

والـ Dummy Regressor هو اللي في المقام: موديل بسيط بيتوقع المتوسط \(\bar y\) لكل الـ X.
فالـ R² بتقارن الموديل بتاعنا بيه:

\(R^2 = 0\)E(model) = E(ȳ): مش أحسن من المتوسط
\(R^2\) +ve ↑E(model) ≪ E(ȳ): الموديل أحسن بكتير
\(R^2\) −veE(model) > E(ȳ): الموديل أسوأ من المتوسط
➕ إضافة: MAE ولا RMSE؟
الاتنين بنفس وحدة الـ y (يعني بالألف في مثالنا)، فسهل نفهمهم.
الـ RMSE بيعاقب الأخطاء الكبيرة أكتر، بسبب التربيع.
فلو غلطة كبيرة في سعر عربية واحدة تفرق معاك، بص على الـ RMSE.
سبورة المحاضر: Regression Evaluation
السبورة الأصلية — اضغط على الصورة للتكبير

8Polynomial Regression

Simple\(\text{price} = w_0 + w_1 \times \text{power}\)
Multiple\(\text{price} = w_0 + w_1 \times \text{power} + w_2 \times \text{mileage} + w_3 \times \text{km} + \dots + w_nx_n\)
Polynomial\(\text{price} = w_0 + w_1 \times \text{power}^2 + w_2 \times \text{mileage}^3 + w_3 \times \text{power}\times\text{mileage} + \dots\)

لو العلاقة بين الـ power والسعر مش خط مستقيم (Non linear)، بنعمل Polynomial Features.
كل feature بنرفعها لأس \(d = 2, 3, \dots\)، يعني \(x_i \rightarrow x_i^{\,d}\).
وكمان بنضرب الـ features في بعض.

Polynomial Regression = Polynomial Features + Linear Regressionالموديل لسه Linear في الـ weights، الـ non-linearity كلها في الـ features
➕ إضافة: Overfitting وليه بنقسم الداتا train / test
كل ما الـ degree يعلى، الـ train error بيقل دايمًا.
لأن المنحنى بقى عنده حرية أكتر يعدّي على كل النقط.
بس عند حد معين بيبدأ يحفظ الداتا بدل ما يفهمها، والـ test error يرجع يعلى.
ده اسمه Overfitting.
وعكسه لما الموديل أبسط من الداتا (زي خط مستقيم على داتا شكلها S)، واسمه Underfitting.
فاحنا بنختار الـ degree على أساس الـ test (أو الـ validation)، مش الـ train.
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.pipeline import make_pipeline
from sklearn.linear_model import LinearRegression

model = make_pipeline(PolynomialFeatures(degree=3), StandardScaler(), LinearRegression())
model.fit(X_train, y_train)
print(model.score(X_test, y_test))   # R² على الـ test
سبورة المحاضر: Polynomial Regression
السبورة الأصلية — اضغط على الصورة للتكبير

9اختبر نفسك

8 أسئلة سريعة.
اختار إجابة، وهتلاقي الشرح ظهر تحتها.

0 / 8

10الخلاصة في كارت واحد

الموديل

\(\hat{\mathbf y} = X\mathbf w\)
Learning ⇒ Find Best Weights

Cost Function (MSE)

\(J(\mathbf w)=\frac{1}{2m}\sum (y^{(i)}-\hat y^{(i)})^2\)

OLS / Normal Equation

\(\mathbf w=(X^\top X)^{-1}X^\top\mathbf y\)
Closed · No scaling · LinearRegression

Gradient Descent

\(w^{new}=w^{old}-\eta\,\frac{\partial J}{\partial w}\)
Iterative · Needs scaling · SGDRegressor

Evaluation

MSE · MAE · RMSE
\(R^2 = 1-\frac{SSE}{SST}\)، مقارنة بالـ Dummy \(\bar y\)

Polynomial

Polynomial Features + Linear Regression
اختار الـ degree على الـ test