We work with vectors:
The operations used in code can be written in summation notation as follows:
- Dot product of (X) with itself:
- Dot product of (X) and (Y):
- Mean of (X) (often written as $(\bar{x})$):
- Mean of (Y) (often written as $(\bar{y})$):
- Sum of (X):
The denominator used in slope and intercept formulas:
- Slope (a) (step-by-step):
- Intercept (b) (step-by-step):
Note: This is algebraically equivalent to the simpler form
$(b = \bar{y} - a \bar{x}$ ).
-
Predicted values
$(\hat{y}_i)$ for each observation:
For multiple predictors (p), we organize the data into:
-
Design matrix
$(X) (size (n \times (p+1))$ with intercept):
-
Response vector
$(Y) (size (n \times 1)$ ):
-
Coefficient vector
$(w) (size ((p+1) \times 1)$ ):
- Predicted values:
The coefficients are obtained by solving the normal equations:
Python code:
w = np.linalg.solve(X.T @ X, X.T @ Y)
Yhat = X @ wAlternatively:
w = np.linalg.solve(np.dot(X.T, X), np.dot(X.T, Y))
Yhat = np.dot(X, w)The
- Residuals:
- Total deviation from the mean:
- R-squared:
- Python implementation:
d1 = Y - Yhat
d2 = Y - Y.mean()
r2 = 1 - d1.dot(d1) / d2.dot(d2)
print(f"R-squared: {r2}")
Python code:
```python
d1 = Y - Yhat
d2 = Y - Y.mean()
r2 = 1 - d1.dot(d1) / d2.dot(d2)
print(f"R-squared: {r2}")