Codepython
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
# ---------------------------
# Generate synthetic data
# ---------------------------
np.random.seed(42)
n = 10
x = np.linspace(0, 100, n)
noise = np.random.normal(0, 500, n) * 150
y = x + x**2 + x**3 + noise
df = pd.DataFrame({"x": x, "y": y})
X = df[["x"]]
y = df["y"]
# ---------------------------
# Train-test split
# ---------------------------
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42
)
# ---------------------------
# Models
# ---------------------------
models = {
# -------------------------
# Model 1: Simple Linear Regression
# -------------------------
# This model assumes a straight-line relationship:
# y = β0 + β1*x
# No polynomial features are added.
"Linear": Pipeline([
("linear", LinearRegression()) # Fit a straight line to the data
]),
# -------------------------
# Model 2: Polynomial Regression (degree = 3)
# -------------------------
# PolynomialFeatures transforms x into:
# [1, x, x^2, x^3]
# Then LinearRegression fits:
# y = β0 + β1*x + β2*x^2 + β3*x^3
"Poly3": Pipeline([
("poly", PolynomialFeatures(degree=3)), # Create polynomial features up to x^3
("linear", LinearRegression()) # Fit linear regression on expanded features
]),
# -------------------------
# Model 3: Polynomial Regression (degree = 6)
# -------------------------
# PolynomialFeatures transforms x into:
# [1, x, x^2, x^3, x^4, x^5, x^6]
# Higher degree allows more flexibility but increases risk of overfitting.
"Poly6": Pipeline([
("poly", PolynomialFeatures(degree=6)), # Create polynomial features up to x^6
("linear", LinearRegression()) # Fit regression on these features
])
}
results = {}
# ---------------------------
# Train models and compute scores
# ---------------------------
for name, model in models.items():
model.fit(X_train, y_train)
y_pred_train = model.predict(X_train)
y_pred_test = model.predict(X_test)
train_r2 = r2_score(y_train, y_pred_train)
test_r2 = r2_score(y_test, y_pred_test)
results[name] = (train_r2, test_r2)
# ---------------------------
# Print comparison
# ---------------------------
print("Model Performance")
print("------------------")
for model, scores in results.items():
print(f"{model} | Train R2: {scores[0]:.2f} | Test R2: {scores[1]:.2f}")
Output
Model Performance
------------------
Linear | Train R2: 0.83 | Test R2: 0.77
Poly3 | Train R2: 0.99 | Test R2: 0.92
Poly6 | Train R2: 1.00 | Test R2: 0.20