MACHINE LEARNING

Tuning the Knobs of Machine Learning: Hyperparameters in ML

June 29, 2026 · 28 min read

The Problem

Imagine setting up a new JioFiber Wi-Fi router in your living room, only to find that the signal drops the moment you walk into your bedroom. To fix this, you cannot change how internet signals work; instead, you must manually log into the router settings, choose between the 2.4GHz or 5GHz band, and adjust the antenna angles until the signal reaches every corner.

These manual settings you tweak before the internet actually starts running are exactly what hyperparameters in ml are.


What is hyperparameters in ml? (And Why Should You Care?)

The Biryani Analogy

Think of a machine learning model as an apprentice chef learning to make the perfect Hyderabadi Biryani.

These high-level decisions are hyperparameters. The apprentice chef cannot “learn” these during cooking; they must be set by the Master Chef beforehand.

In Plain English

In Machine Learning, hyperparameters are the external configuration settings that you (the programmer) must set before training the model. Unlike regular parameters (like weights), the model cannot learn or adjust hyperparameters on its own during training.

Why do we need them? (Where simpler models fail)

If we don’t use hyperparameters, a machine learning model is like an autopilot car with no speed limits or steering sensitivity controls.

Without these controls, the model will either:

Hyperparameters act as the steering wheel and brakes, guiding the model so it learns efficiently without memorizing.


Where is hyperparameters in ml Used in Real Life?

Example 1: IPL Auction Strategy (Sports)

Example 2: PhonePe UPI Fraud Detection (Fintech)

Example 3: Flipkart Recommendation Engine (E-commerce)


The Math Behind hyperparameters in ml (Don’t Panic!)

To see how a hyperparameter works mathematically, let us look at how a model updates its internal settings using Gradient Descent (the math behind how models learn).

Here is the golden equation:

W_new = W_old – α × (∂L / ∂W)

Let us break down this equation, symbol by symbol, and see how it matches our Python code:

What does “Minimizing the Cost Function” mean?

In human terms, minimizing the cost function means reducing our mistakes to zero. We want to adjust our weights (W) so that our Disappointment Meter (L) hits the lowest possible point on the graph.

The Power of the Hyperparameter (α)

Look closely at the equation again:

W_new = W_old – α × Mistake

The hyperparameter α controls how much we listen to our mistakes:

By tuning the hyperparameter α to a sweet spot (like 0.01), we ensure the model learns quickly, safely, and accurately!


GIF 1: Why Simple Models Fail ?

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# Set random seed for reproducibility of our Mumbai housing data
np.random.seed(42)

# 1. Generate Synthetic Mumbai House Price Data
# X: Size of flat in 100s of square feet (e.g., 3 means 300 sq ft, 15 means 1500 sq ft)
# Y: Price of flat in Lakhs (e.g., 50 Lakhs, 120 Lakhs)
# We scale X to keep gradient descent stable and prevent numerical overflow
X = np.linspace(-1.5, 1.5, 30)
# True relationship: Price = 2.5 * Size + 1.0 + random noise
Y = 2.5 * X + 1.0 + np.random.normal(0, 0.4, 30)

# 2. Initialize Model Parameters (Weights and Biases)
# Both models start with the exact same bad guess (slope = -3.0, intercept = -3.0)
w_high = -3.0
b_high = -3.0

w_good = -3.0
b_good = -3.0

# 3. Define Hyperparameters (Learning Rates)
lr_high = 0.95 # WRONG: Too high! Will cause wild oscillations
lr_good = 0.1 # CORRECT: Sweet spot! Will converge smoothly

# Lists to store history for the live loss subplots
epochs_history = []
loss_high_history = []
loss_good_history = []

# 4. Set up the Matplotlib Figure and Subplots (2×2 Grid)
fig, axs = plt.subplots(2, 2, figsize=(14, 10))

# Define a function to update the plots frame-by-frame
def update(frame):
global w_high, b_high, w_good, b_good

# — MODEL A: WRONG HYPERPARAMETER (HIGH LEARNING RATE) —
# Compute predictions
y_pred_high = w_high * X + b_high
# Compute Mean Squared Error (Loss)
loss_high = np.mean((y_pred_high – Y) ** 2)
# Compute Gradients (Derivatives of Loss with respect to w and b)
dw_high = (2 / len(X)) * np.sum((y_pred_high – Y) * X)
db_high = (2 / len(X)) * np.sum(y_pred_high – Y)
# Update weights using Gradient Descent
w_high = w_high – lr_high * dw_high
b_high = b_high – lr_high * db_high

# — MODEL B: CORRECT HYPERPARAMETER (GOOD LEARNING RATE) —
# Compute predictions
y_pred_good = w_good * X + b_good
# Compute Mean Squared Error (Loss)
loss_good = np.mean((y_pred_good – Y) ** 2)
# Compute Gradients
dw_good = (2 / len(X)) * np.sum((y_pred_good – Y) * X)
db_good = (2 / len(X)) * np.sum(y_pred_good – Y)
# Update weights using Gradient Descent
w_good = w_good – lr_good * dw_good
b_good = b_good – lr_good * db_good

# Store history for live loss plotting
epochs_history.append(frame)
loss_high_history.append(loss_high)
loss_good_history.append(loss_good)

# — PLOTTING AND RENDERING —
# Clear all subplots to draw the new frame
for ax in axs.flat:
ax.clear()

# Generate a smooth line for plotting the regression fits
line_x = np.linspace(-2.0, 2.0, 100)

# TOP-LEFT: High LR Model Fit
axs[0, 0].scatter(X, Y, color=’orange’, edgecolor=’k’, alpha=0.7, label=’Mumbai Flats’)
line_y_high = w_high * line_x + b_high
axs[0, 0].plot(line_x, line_y_high, color=’red’, linewidth=2.5, label=f’Fit (w={w_high:.2f}, b={b_high:.2f})’)
axs[0, 0].set_xlim(-2.0, 2.0)
axs[0, 0].set_ylim(-8, 8)
axs[0, 0].set_title(f”High LR (α = {lr_high}) | Loss: {loss_high:.2f}”, color=’red’, fontsize=11, fontweight=’bold’)
axs[0, 0].set_xlabel(“Flat Size (Scaled)”)
axs[0, 0].set_ylabel(“Price in Lakhs (Scaled)”)
axs[0, 0].legend(loc=’upper left’)
axs[0, 0].grid(True, linestyle=’–‘, alpha=0.5)

# BOTTOM-LEFT: High LR Loss Curve
axs[1, 0].plot(epochs_history, loss_high_history, color=’red’, linewidth=2)
axs[1, 0].set_title(“High LR Loss History”, color=’red’, fontsize=10, fontweight=’bold’)
axs[1, 0].set_xlabel(“Epoch”)
axs[1, 0].set_ylabel(“Loss (MSE)”)
axs[1, 0].grid(True, linestyle=’–‘, alpha=0.5)

# TOP-RIGHT: Good LR Model Fit
axs[0, 1].scatter(X, Y, color=’orange’, edgecolor=’k’, alpha=0.7, label=’Mumbai Flats’)
line_y_good = w_good * line_x + b_good
axs[0, 1].plot(line_x, line_y_good, color=’green’, linewidth=2.5, label=f’Fit (w={w_good:.2f}, b={b_good:.2f})’)
axs[0, 1].set_xlim(-2.0, 2.0)
axs[0, 1].set_ylim(-8, 8)
axs[0, 1].set_title(f”Good LR (α = {lr_good}) | Loss: {loss_good:.2f}”, color=’green’, fontsize=11, fontweight=’bold’)
axs[0, 1].set_xlabel(“Flat Size (Scaled)”)
axs[0, 1].set_ylabel(“Price in Lakhs (Scaled)”)
axs[0, 1].legend(loc=’upper left’)
axs[0, 1].grid(True, linestyle=’–‘, alpha=0.5)

# BOTTOM-RIGHT: Good LR Loss Curve
axs[1, 1].plot(epochs_history, loss_good_history, color=’green’, linewidth=2)
axs[1, 1].set_title(“Good LR Loss History”, color=’green’, fontsize=10, fontweight=’bold’)
axs[1, 1].set_xlabel(“Epoch”)
axs[1, 1].set_ylabel(“Loss (MSE)”)
axs[1, 1].grid(True, linestyle=’–‘, alpha=0.5)

# Dynamic Storytelling Titles
if frame == 0:
fig.suptitle(“Epoch 0 — Both starting blind”, fontsize=14, fontweight=’bold’)
elif frame < 25:
fig.suptitle(f”Epoch {frame} — High LR bouncing wildly, Good LR learning fast”, fontsize=14, fontweight=’bold’)
else:
fig.suptitle(f”Epoch {frame} — High LR exploded/stuck! Good LR nailed it.”, fontsize=14, fontweight=’bold’)

plt.tight_layout()

# 5. Run the Animation
# We run for 60 frames (epochs) to show the full convergence and oscillation cycle
ani = FuncAnimation(fig, update, frames=60, interval=150, repeat=False)

# Save the animation as a GIF
ani.save(‘comparison_hyperparameters_in_ml.gif’, writer=’pillow’, fps=10)
plt.close()

 

View post on imgur.com

Comparison Animation

What You Will See in This GIF:


GIF 2: How hyperparameters in ml Actually Learns ?

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# Set random seed for reproducibility of our Mumbai housing data
np.random.seed(42)

# 1. Generate Synthetic Mumbai House Price Data
# X: Size of flat in 100s of square feet (e.g., 3 means 300 sq ft, 15 means 1500 sq ft)
# Y: Price of flat in Lakhs (e.g., 50 Lakhs, 120 Lakhs)
X = np.linspace(3, 15, 40)
# True relationship: Price = 8.0 * Size + 20.0 + random noise
Y = 8.0 * X + 20.0 + np.random.normal(0, 12, 40)

# Scale features to keep gradient descent stable and prevent numerical overflow
X_mean = np.mean(X)
X_std = np.std(X)
X_scaled = (X – X_mean) / X_std

# 2. Initialize Model Parameters (Weights and Biases)
# We start with a very bad guess (slope = -20.0, intercept = 10.0)
w = -20.0
b = 10.0

# 3. Define Hyperparameters
# Learning rate (alpha) controls the step size of our updates
learning_rate = 0.05

# Lists to store history for the live loss subplot
epochs_history = []
loss_history = []

# 4. Set up the Matplotlib Figure and Subplots (1×2 Grid)
fig, (ax_fit, ax_loss) = plt.subplots(1, 2, figsize=(14, 6))

# Define the update function to train the model frame-by-frame
def update(frame):
global w, b

# — MANUAL GRADIENT DESCENT STEP —
# Compute predictions using current weight and bias
Y_pred = w * X_scaled + b

# Compute Mean Squared Error (Loss)
loss = np.mean((Y_pred – Y) ** 2)

# Compute Gradients (Derivatives of Loss with respect to w and b)
dw = (2 / len(X_scaled)) * np.sum((Y_pred – Y) * X_scaled)
db = (2 / len(X_scaled)) * np.sum(Y_pred – Y)

# Update weights manually using our learning rate hyperparameter
w = w – learning_rate * dw
b = b – learning_rate * db

# Store history for live loss plotting
epochs_history.append(frame)
loss_history.append(loss)

# — PLOTTING AND RENDERING —
# Clear both subplots to draw the new frame
ax_fit.clear()
ax_loss.clear()

# LEFT SUBPLOT: Live Model Fit
ax_fit.scatter(X, Y, color=’orange’, edgecolor=’k’, s=50, label=’Mumbai Flats’)
# Generate a smooth line for plotting the regression fit
X_line_scaled = np.linspace(min(X_scaled), max(X_scaled), 100)
Y_line_pred = w * X_line_scaled + b
X_line_unscaled = X_line_scaled * X_std + X_mean
ax_fit.plot(X_line_unscaled, Y_line_pred, color=’red’, linewidth=3, label=f’Fit: y = {w:.2f}*x_scaled + {b:.2f}’)
ax_fit.set_xlim(2, 16)
ax_fit.set_ylim(0, 180)
ax_fit.set_title(“Model Fitting Live on Mumbai Housing Data”, fontsize=12, fontweight=’bold’)
ax_fit.set_xlabel(“Flat Size (100s of sq ft)”)
ax_fit.set_ylabel(“Price (Lakhs)”)
ax_fit.legend(loc=’upper left’)
ax_fit.grid(True, linestyle=’–‘, alpha=0.5)

# RIGHT SUBPLOT: Live Loss Curve
ax_loss.plot(epochs_history, loss_history, color=’blue’, linewidth=2, label=’MSE Loss’)
ax_loss.set_xlim(-5, 205)
ax_loss.set_ylim(-500, 12000)
ax_loss.set_title(“Loss Curve Dropping in Real Time”, fontsize=12, fontweight=’bold’)
ax_loss.set_xlabel(“Epoch”)
ax_loss.set_ylabel(“Loss (Mean Squared Error)”)
ax_loss.legend(loc=’upper right’)
ax_loss.grid(True, linestyle=’–‘, alpha=0.5)

# Annotate key moments (e.g., when loss drops fast at the beginning)
if frame >= 15:
ax_loss.annotate(‘Rapid Drop!’, xy=(15, loss_history[15]), xytext=(60, 8000),
arrowprops=dict(facecolor=’black’, shrink=0.05, width=1.5, headwidth=8))

# Dynamic Storytelling Titles
if frame == 0:
fig.suptitle(f”Epoch 0 — Random guess. Loss = {loss:.2f}”, fontsize=14, fontweight=’bold’, color=’red’)
elif frame == 50:
fig.suptitle(f”Epoch 50 — Learning… Loss = {loss:.2f}”, fontsize=14, fontweight=’bold’, color=’orange’)
elif frame == 150:
fig.suptitle(f”Epoch 150 — Getting there! Loss = {loss:.2f}”, fontsize=14, fontweight=’bold’, color=’blue’)
elif frame == 200:
fig.suptitle(f”Epoch 200 — Converged! Loss = {loss:.2f}”, fontsize=14, fontweight=’bold’, color=’green’)
else:
fig.suptitle(f”Epoch {frame} — Loss = {loss:.2f}”, fontsize=14, fontweight=’bold’)

plt.tight_layout()

# 5. Run the Animation
# We run for 201 frames (epochs 0 to 200) to show the full convergence cycle
ani = FuncAnimation(fig, update, frames=201, interval=50, repeat=False)

# Save the animation as a GIF
ani.save(‘training_hyperparameters_in_ml.gif’, writer=’pillow’, fps=10)
plt.close()

 

View post on imgur.com

Training Animation

What You Will See in This GIF:

This GIF shows the heart of hyperparameters in ml.


Let’s Build It: Real Python Project —

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import mean_squared_error, r2_score

# Set random seed for reproducibility of our Mumbai ride data
np.random.seed(42)

# 1. Generate Synthetic Ola Mumbai Ride Dataset
# We simulate 500 ride requests across Mumbai
total_rides = 500

# Distance of rides in kilometers (e.g., from Colaba to Bandra)
ride_distance_km = np.random.uniform(2.0, 40.0, total_rides)

# Demand-to-Supply Ratio (0.5 means plenty of cabs, 4.0 means extreme shortage during monsoon)
demand_supply_ratio = np.random.uniform(0.5, 4.0, total_rides)

# True Surge Multiplier formula with non-linear relationships and random noise
# Surge increases exponentially when demand exceeds supply
true_surge = 1.0 + 0.15 * (demand_supply_ratio ** 2) + 0.01 * ride_distance_km
noise = np.random.normal(0, 0.15, total_rides)
surge_multiplier = np.clip(true_surge + noise, 1.0, 3.5) # Surge is capped between 1.0x and 3.5x

# Combine into a clean Pandas DataFrame
ola_dataset = pd.DataFrame({
‘Distance_KM’: ride_distance_km,
‘Demand_Supply_Ratio’: demand_supply_ratio,
‘Surge_Multiplier’: surge_multiplier
})

# 2. Separate Features (X) and Target Variable (Y)
features = ola_dataset[[‘Distance_KM’, ‘Demand_Supply_Ratio’]]
target = ola_dataset[‘Surge_Multiplier’]

# 3. Train-Test Split (80% Training, 20% Testing)
X_train, X_test, y_train, y_test = train_test_split(
features, target, test_size=0.20, random_state=42
)

# 4. Preprocessing: Standardize Features
# Scaling features to have a mean of 0 and variance of 1
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 5. Model Training with Tuned Hyperparameter (max_depth=4)
# We set max_depth=4 as our sweet-spot hyperparameter to avoid underfitting (depth=1) and overfitting (depth=15)
tuned_decision_tree = DecisionTreeRegressor(max_depth=4, random_state=42)
tuned_decision_tree.fit(X_train_scaled, y_train)

# 6. Model Predictions
predictions_test = tuned_decision_tree.predict(X_test_scaled)

# 7. Evaluation Metrics
mse_score = mean_squared_error(y_test, predictions_test)
r2_accuracy = r2_score(y_test, predictions_test)

print(“— OLA SURGE MODEL PERFORMANCE —“)
print(f”Mean Squared Error (MSE): {mse_score:.4f}”)
print(f”R-squared (R2) Score: {r2_accuracy:.4f}”)

# 8. Generate Comparison Diagnostic Plots
fig, (ax_pred, ax_resid) = plt.subplots(1, 2, figsize=(14, 6))

# Subplot 1: Actual vs Predicted Surge Multiplier
ax_pred.scatter(y_test, predictions_test, color=’dodgerblue’, edgecolor=’black’, alpha=0.7, s=60, label=’Predicted Rides’)
# Perfect prediction line (y = x)
min_val = min(y_test.min(), predictions_test.min())
max_val = max(y_test.max(), predictions_test.max())
ax_pred.plot([min_val, max_val], [min_val, max_val], color=’crimson’, linestyle=’–‘, linewidth=2.5, label=’Perfect Prediction’)
ax_pred.set_title(“Actual vs. Predicted Ola Surge Multipliers”, fontsize=12, fontweight=’bold’)
ax_pred.set_xlabel(“Actual Surge Multiplier”, fontsize=10)
ax_pred.set_ylabel(“Predicted Surge Multiplier”, fontsize=10)
ax_pred.legend(loc=’upper left’)
ax_pred.grid(True, linestyle=’–‘, alpha=0.5)

# Subplot 2: Residuals Scatter Plot
residuals = y_test – predictions_test
ax_resid.scatter(predictions_test, residuals, color=’mediumseagreen’, edgecolor=’black’, alpha=0.7, s=60, label=’Residuals’)
ax_resid.axhline(y=0, color=’crimson’, linestyle=’–‘, linewidth=2.5)
ax_resid.set_title(“Residual Analysis (Errors vs. Predictions)”, fontsize=12, fontweight=’bold’)
ax_resid.set_xlabel(“Predicted Surge Multiplier”, fontsize=10)
ax_resid.set_ylabel(“Residuals (Actual – Predicted)”, fontsize=10)
ax_resid.legend(loc=’upper right’)
ax_resid.grid(True, linestyle=’–‘, alpha=0.5)

plt.tight_layout()

# Save the comparison plot as a PNG
plt.savefig(‘sklearn_hyperparameters_in_ml.png’, dpi=150, bbox_inches=’tight’)
plt.close()

 

Results

What Does This Output Mean?


GIF 3: What Happens When We Push Too Far?

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

# Set random seed for reproducibility of Maharashtra crop data
np.random.seed(42)

# 1. Generate Synthetic Maharashtra Crop Yield Data
# Rainfall deviation from normal (scaled between -1.0 and 1.0)
rainfall_scaled = np.linspace(-1.0, 1.0, 25)
# True relationship: Yield peaks at moderate rainfall, drops during drought (-1) or flood (+1)
true_yield = 25.0 + 15.0 * rainfall_scaled – 30.0 * (rainfall_scaled ** 2) – 10.0 * (rainfall_scaled ** 3)
noise = np.random.normal(0, 2.5, len(rainfall_scaled))
crop_yield = true_yield + noise

# 2. Pre-compute Polynomial Feature Matrices manually
# Degree 1 Features: [1, x]
X_poly1 = np.vstack([np.ones_like(rainfall_scaled), rainfall_scaled]).T

# Degree 3 Features: [1, x, x^2, x^3]
X_poly3 = np.vstack([np.ones_like(rainfall_scaled), rainfall_scaled, rainfall_scaled**2, rainfall_scaled**3]).T

# Degree 10 Features: [1, x, x^2, …, x^10]
X_poly10 = np.vstack([rainfall_scaled**i for i in range(11)]).T

# 3. Initialize Weights for Gradient Descent
weights_deg1 = np.zeros(2)
weights_deg3 = np.zeros(4)
weights_deg10 = np.zeros(11)

# 4. Set Learning Rates (Hyperparameters for the optimizer)
lr_deg1 = 0.15
lr_deg3 = 0.15
lr_deg10 = 0.08 # Lower learning rate to keep high-degree polynomial stable

# Lists to store loss histories
epochs = []
loss_history_deg1 = []
loss_history_deg3 = []
loss_history_deg10 = []

# 5. Set up the 2×3 Matplotlib Figure Grid
# Top Row: Model Fits | Bottom Row: Live Loss Curves
fig, axs = plt.subplots(2, 3, figsize=(18, 10))

# Generate smooth X values for plotting continuous curves
smooth_x = np.linspace(-1.1, 1.1, 100)
smooth_X_poly1 = np.vstack([np.ones_like(smooth_x), smooth_x]).T
smooth_X_poly3 = np.vstack([np.ones_like(smooth_x), smooth_x, smooth_x**2, smooth_x**3]).T
smooth_X_poly10 = np.vstack([smooth_x**i for i in range(11)]).T

# Define the animation update loop
def update(frame):
global weights_deg1, weights_deg3, weights_deg10

# — MANUAL GRADIENT DESCENT STEP —
# Degree 1 Predictions & Updates
pred_deg1 = X_poly1 @ weights_deg1
loss_deg1 = np.mean((pred_deg1 – crop_yield) ** 2)
grad_deg1 = (2 / len(rainfall_scaled)) * (X_poly1.T @ (pred_deg1 – crop_yield))
weights_deg1 -= lr_deg1 * grad_deg1

# Degree 3 Predictions & Updates
pred_deg3 = X_poly3 @ weights_deg3
loss_deg3 = np.mean((pred_deg3 – crop_yield) ** 2)
grad_deg3 = (2 / len(rainfall_scaled)) * (X_poly3.T @ (pred_deg3 – crop_yield))
weights_deg3 -= lr_deg3 * grad_deg3

# Degree 10 Predictions & Updates
pred_deg10 = X_poly10 @ weights_deg10
loss_deg10 = np.mean((pred_deg10 – crop_yield) ** 2)
grad_deg10 = (2 / len(rainfall_scaled)) * (X_poly10.T @ (pred_deg10 – crop_yield))
weights_deg10 -= lr_deg10 * grad_deg10

# Store history
epochs.append(frame)
loss_history_deg1.append(loss_deg1)
loss_history_deg3.append(loss_deg3)
loss_history_deg10.append(loss_deg10)

# — RENDERING PLOTS —
for ax in axs.flat:
ax.clear()

# — TOP ROW: MODEL FITS —
# Panel 1: Degree 1 (Underfit)
axs[0, 0].scatter(rainfall_scaled, crop_yield, color=’orange’, edgecolor=’k’, s=40, label=’Maharashtra Farms’)
axs[0, 0].plot(smooth_x, smooth_X_poly1 @ weights_deg1, color=’red’, linewidth=2.5, label=’Degree 1 Fit’)
axs[0, 0].set_ylim(0, 40)
axs[0, 0].set_title(f”Degree 1 (Underfit) | Loss: {loss_deg1:.2f}”, color=’red’, fontsize=11, fontweight=’bold’)
axs[0, 0].set_xlabel(“Rainfall Deviation”)
axs[0, 0].set_ylabel(“Crop Yield (Quintals/Hectare)”)
axs[0, 0].legend(loc=’lower center’)
axs[0, 0].grid(True, linestyle=’–‘, alpha=0.5)

# Panel 2: Degree 3 (Good Fit)
axs[0, 1].scatter(rainfall_scaled, crop_yield, color=’orange’, edgecolor=’k’, s=40, label=’Maharashtra Farms’)
axs[0, 1].plot(smooth_x, smooth_X_poly3 @ weights_deg3, color=’green’, linewidth=2.5, label=’Degree 3 Fit’)
axs[0, 1].set_ylim(0, 40)
axs[0, 1].set_title(f”Degree 3 (Good Fit) | Loss: {loss_deg3:.2f}”, color=’green’, fontsize=11, fontweight=’bold’)
axs[0, 1].set_xlabel(“Rainfall Deviation”)
axs[0, 1].legend(loc=’lower center’)
axs[0, 1].grid(True, linestyle=’–‘, alpha=0.5)

# Panel 3: Degree 10 (Overfit)
axs[0, 2].scatter(rainfall_scaled, crop_yield, color=’orange’, edgecolor=’k’, s=40, label=’Maharashtra Farms’)
axs[0, 2].plot(smooth_x, smooth_X_poly10 @ weights_deg10, color=’purple’, linewidth=2.5, label=’Degree 10 Fit’)
axs[0, 2].set_ylim(0, 40)
axs[0, 2].set_title(f”Degree 10 (Overfit) | Loss: {loss_deg10:.2f}”, color=’purple’, fontsize=11, fontweight=’bold’)
axs[0, 2].set_xlabel(“Rainfall Deviation”)
axs[0, 2].legend(loc=’lower center’)
axs[0, 2].grid(True, linestyle=’–‘, alpha=0.5)

# — BOTTOM ROW: LIVE LOSS CURVES —
# Degree 1 Loss
axs[1, 0].plot(epochs, loss_history_deg1, color=’red’, linewidth=2)
axs[1, 0].set_title(“Degree 1 Loss History”, color=’red’, fontsize=10, fontweight=’bold’)
axs[1, 0].set_xlabel(“Epoch”)
axs[1, 0].set_ylabel(“Mean Squared Error”)
axs[1, 0].grid(True, linestyle=’–‘, alpha=0.5)

# Degree 3 Loss
axs[1, 1].plot(epochs, loss_history_deg3, color=’green’, linewidth=2)
axs[1, 1].set_title(“Degree 3 Loss History”, color=’green’, fontsize=10, fontweight=’bold’)
axs[1, 1].set_xlabel(“Epoch”)
axs[1, 1].grid(True, linestyle=’–‘, alpha=0.5)

# Degree 10 Loss
axs[1, 2].plot(epochs, loss_history_deg10, color=’purple’, linewidth=2)
axs[1, 2].set_title(“Degree 10 Loss History”, color=’purple’, fontsize=10, fontweight=’bold’)
axs[1, 2].set_xlabel(“Epoch”)
axs[1, 2].grid(True, linestyle=’–‘, alpha=0.5)

# Dynamic Frame Titles
if frame == 0:
fig.suptitle(“Epoch 0 — I know nothing”, fontsize=14, fontweight=’bold’)
elif frame == 50:
fig.suptitle(“Epoch 50 — Getting warmer!”, fontsize=14, fontweight=’bold’)
elif frame == 149:
fig.suptitle(“Epoch 150 — Final Fits: Underfit vs. Perfect vs. Overfit!”, fontsize=14, fontweight=’bold’)
else:
fig.suptitle(f”Epoch {frame} — Training Polynomial Models Simultaneously”, fontsize=14, fontweight=’bold’)

plt.tight_layout()

# 6. Run and Save the Animation
ani = FuncAnimation(fig, update, frames=150, interval=100, repeat=False)
ani.save(‘edgecase_hyperparameters_in_ml.gif’, writer=’pillow’, fps=8)
plt.close()

 

hyperparameters

Edge Case Animation

What You Will See in This GIF:


Line-by-Line Code Walkthrough

Here is a breakdown of the most important concepts from our Python codes:


Quick Recap ✅


Test Yourself 🧠

1. What is the main difference between a parameter and a hyperparameter?

Answer: B

2. In the Gradient Descent equation, what happens if the learning rate hyperparameter (α) is set too high?

Answer: C

3. If you are training a Decision Tree and notice it is memorizing the training data perfectly but failing on new test data (Overfitting), which hyperparameter tweak would help?

Answer: B

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
// STILL BROWSING?
Build along, don't just read.
Get labs & articles matched to what you're into — free, takes 30 seconds.
Start building free
0
Would love your thoughts, please comment.x
()
x