Concepts 🚀 Project 🧮 Labs
🚀 Learn with Project / Stage 2 — 3 plots that tell you if ML is even possible
🚀 Stage 2 of 13
← Previous — Stage 1
Meet the dataset — 4 questions you always ask
←

3 plots that tell you if ML is even possible

Scatter plot of each feature vs the target. If there's no visible relationship, ML can't magically find one.

🧠 The intuition Before training, plot each feature against the target. You're looking for ANY visible trend — a cloud is fine, but a flat horizontal line means that feature is useless. Why this matters: ML can only learn what's in the data. If study_hours vs final_score is a flat cloud, no model in the world can use study_hours to predict final_score. You'd be wasting your time adding it as a feature. 3 plots, 3 questions: 1. study_hours vs final_score -> do studiers score higher? 2. attendance vs final_score -> do attendees score higher? 3. previous_score vs final_score -> is past performance predictive?
✏️ Tiny task — write this yourself Make ONE scatter plot of study_hours vs final_score. Just one. Don't try to make it pretty. import matplotlib.pyplot as plt df.plot.scatter(x='study_hours', y='final_score') plt.show()
✅ Check — what you should see You should see a cloud that trends UP-AND-TO-THE-RIGHT. If you see a flat horizontal line, ML on this feature is hopeless. If you see a clean diagonal, ML will be easy.

🧮 Code files for this stage

📄 explore_plots.py python
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('data/students.csv')

fig, axes = plt.subplots(1, 3, figsize=(15, 4))

# Plot 1: study_hours vs final_score
df.plot.scatter(x='study_hours', y='final_score', ax=axes[0], alpha=0.5)
axes[0].set_title('Study hours vs Final score')

# Plot 2: attendance vs final_score
df.plot.scatter(x='attendance', y='final_score', ax=axes[1], alpha=0.5, color='green')
axes[1].set_title('Attendance vs Final score')

# Plot 3: previous_score vs final_score
df.plot.scatter(x='previous_score', y='final_score', ax=axes[2], alpha=0.5, color='orange')
axes[2].set_title('Previous score vs Final score')

plt.tight_layout()
plt.savefig('data/explore.png', dpi=100)
plt.show()

How it works

Each subplot answers one question. If plot 1 trends up, study time matters. If plot 3 is a tight diagonal, previous_score is the strongest predictor (it usually is — past performance is the best predictor of future performance). If a plot is a flat cloud, drop that feature. The point isn't to make pretty charts — it's to decide which features deserve to be in your model.

🚧 Routes — what's wired up at this stage Still no routes. Visualization runs offline, in a notebook or script. The web app will surface these plots later (Stage 11) — but for now we're just exploring the data.
🧮 Is a response model necessary here? NO — use response_class=HTMLResponse

Matplotlib returns a Figure object, not JSON. No response model needed.

⚠️ Common mistakes to avoid
  • Plotting all 8 features at once in a correlation matrix and being overwhelmed. Plot 3, look, decide, move on.
  • Skipping this step entirely and going straight to model.fit() — you'll have no idea why the model is bad.
  • Making plots pretty (titles, colors, legends) before checking if they show a trend. Pretty but useless is still useless.
👀 What's next Next: Stage 3 cleans the data — handles nulls, encodes categoricals, and splits into X (features) and y (target).
Next — Stage 3
Clean the data + split into X and y
→