Week 9: Correlation & Regression Foundations
Quick overview of today’s plan:
Activity
Converse with your neighbor and identify…
In business, we rarely care about a single number in isolation. Leaders ask questions like:
Today’s Goal: Learn to measure and model these relationships quantitatively.
Think about your work experience, internships, or daily life:
Share your examples with your partner!
Then we’ll take a few responses…
Correlation measures how strongly two variables move together in a linear relationship.
Key Insight: Correlation is descriptive—it tells you variables move together, but not why.
Setup & Game Link
Teams: I’m dividing the room into 2-3 teams
Game: We’ll use the interactive game at guessthecorrelation.com
How it works:
Scoring: Keep track of your team’s average accuracy
Prize: Winning team gets extra credit bragging rights! 🎉
Let’s play 5-10 rounds!
Congratulations to our winning team! 🏆
Key Takeaways from the Challenge:
Next: How do we move from measuring relationships to making predictions?
Your turn! Let’s analyze some real grocery chain data.
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Example dataset: advertising spend vs. weekly sales
data = pd.DataFrame({
"ad_spend": [400, 500, 600, 700, 800, 900, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000, 2100, 2200, 2300],
"weekly_sales": [4200, 4400, 4100, 4800, 5600, 5200, 4900, 5500, 5300, 5900, 5700, 6300, 6900, 6200, 5800, 6600, 7100, 6800, 7300, 7800]
})
# Visualize the relationship
plt.figure(figsize=(8, 5))
plt.scatter(data["ad_spend"], data["weekly_sales"], alpha=0.7, s=60)
plt.xlabel("Advertising Spend ($)")
plt.ylabel("Weekly Sales")
plt.title("Ad Spend vs. Weekly Sales")
plt.grid(True, alpha=0.3)
plt.show()Question for you: What do you think the correlation is? Write down your guess!
Let’s see how close your guess was!
Correlation coefficient: 0.941
Full correlation matrix:
| ad_spend | weekly_sales | |
|---|---|---|
| ad_spend | 1.000000 | 0.941372 |
| weekly_sales | 0.941372 | 1.000000 |
Interpretation:
We found a strong correlation (~0.9) between advertising and sales.
But now the business question is: Can we use advertising spend to predict future sales?
Question: If you could draw a line to represent this relationship, what would it look like?
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
# Visualize the relationship
plt.figure(figsize=(8, 5))
plt.scatter(data["ad_spend"], data["weekly_sales"], alpha=0.7, s=60)
plt.xlabel("Advertising Spend ($)")
plt.ylabel("Weekly Sales")
plt.title("Ad Spend vs. Weekly Sales")
plt.grid(True, alpha=0.3)
plt.show()Remember from high school? The equation of a line:
\[ y = mx + b \]
With linear regression, we follow a similar approach but the typical equation you’ll see is:
\[ y = \beta_0 + \beta_1 x \]
Where:
Important
The goal: Find the best values for slope and intercept that minimize prediction errors!
from sklearn.linear_model import LinearRegression
# Prepare the data
X = data[["ad_spend"]] # Feature matrix (note the double brackets)
y = data["weekly_sales"] # Target variable
# Fit the model
model = LinearRegression()
model.fit(X, y)
# Extract the results
intercept = model.intercept_
slope = model.coef_[0]
print(f"Intercept (β₀): ${intercept:.0f}")
print(f"Slope (β₁): ${slope:.2f}")Intercept (β₀): $3552
Slope (β₁): $1.68
Our fitted equation: \[ \text{Weekly Sales} = 3552 + 1.68 \times \text{Ad Spend} \]
Interpretation: For every $1 increase in advertising, we expect weekly sales to increase by $1.68!
# Create the regression line visualization
plt.figure(figsize=(10, 6))
plt.scatter(data["ad_spend"], data["weekly_sales"], alpha=0.7, s=60, label="Actual data")
# Add the fitted regression line
plt.plot(data["ad_spend"], model.predict(X), color="red", linewidth=3, label="Regression line")
# Show specific predictions
pred_x = [1500, 2000]
for x_val in pred_x:
pred_y = model.predict([[x_val]])[0]
plt.scatter(x_val, pred_y, color="orange", s=120, zorder=5)
plt.annotate(f"${x_val} → ${pred_y:.0f}",
xy=(x_val, pred_y), xytext=(5, -15),
textcoords='offset points', fontsize=10)
plt.xlabel("Advertising Spend ($)")
plt.ylabel("Weekly Sales")
plt.title("Linear Regression: Predictions on the Line")
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()Key insight: Every prediction falls exactly on our regression line!
Business value: Now we can forecast sales for any advertising budget!
# Make predictions for different scenarios
scenarios = pd.DataFrame({
'ad_spend': [1500, 2500, 3000]
})
predictions = model.predict(scenarios)
print("Business Predictions:")
for spend, pred in zip(scenarios['ad_spend'], predictions):
print(f"Spend ${spend:,} → Predicted Sales: ${pred:,.0f}")
# Manual calculation to verify
print(f"\nManual check for $1,500:")
manual_pred = 1.68 * 1500 + 3552
print(f"1.68 × 1500 + 3552 = ${manual_pred:.0f}")Business Predictions:
Spend $1,500 → Predicted Sales: $6,072
Spend $2,500 → Predicted Sales: $7,752
Spend $3,000 → Predicted Sales: $8,592
Manual check for $1,500:
1.68 × 1500 + 3552 = $6072
We now have a model that can make predictions…
Question 🤔
How do we know if this is a GOOD model?
How would you assess prediction quality?
Business Reality Check:
Think about it:
flowchart TD
A[Build Model] --> B[Make Predictions]
B --> C[Compare with Actuals]
C --> D[Calculate Metrics]
D --> E{Good Performance?}
E -->|Yes| F[Deploy Model]
E -->|No| G[Improve Model]
G --> A
style A fill:#e1f5fe
style D fill:#fff3e0
style F fill:#c8e6c9
style G fill:#ffcdd2
R² (R-squared): “What percentage of the variation does my model explain?”
RMSE (Root Mean Squared Error): “How far off are my predictions, on average?”
Additional Details in Readings
The readings will go into more details about these metrics and also introduce additional metrics like MAE (Mean Absolute Error) and MAPE (Mean Absolute Percentage Error).
Key takeaway: All these metrics measure how our model’s predicted values differ from the actual values.
Let’s see how to calculate these evaluation metrics using our advertising model:
R² Score: 0.886
RMSE: $347
What do these numbers tell us about our model’s performance?
Wait a minute… 🤔
We just evaluated our model on the same data we used to build it!
This is like:
Generalization Problem
Training data evaluation can be overly optimistic!
We need to test on data the model has never seen before.
The Real Question 🤔
Question: How will our model perform on new, unseen data?
Solution: Train/Test splits simulate real-world deployment!
The golden rule: Never evaluate on the same data you used to train!
flowchart TD
A[Complete Dataset] --> B[Training Set<br/>70-80%]
A --> C[Test Set<br/>20-30%]
B --> D[Train Model]
D --> E[Trained Model]
C --> F[Evaluate Performance]
E --> F
F --> G[Unbiased Performance<br/>Estimate]
style A fill:#f0f8ff
style B fill:#e8f5e8
style C fill:#ffe6e6
style G fill:#fff2cc
Key insight: Test set simulates future, unseen data!
Let’s split our advertising data into training and test sets:
from sklearn.model_selection import train_test_split
# Split data: 70% training, 30% testing
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=30
)
# Check the sizes
print(f"Total data points: {len(X)}")
print(f"Training set: {len(X_train)} points ({len(X_train)/len(X):.1%})")
print(f"Test set: {len(X_test)} points ({len(X_test)/len(X):.1%})")Total data points: 20
Training set: 14 points (70.0%)
Test set: 6 points (30.0%)
Important: random_state=30 ensures reproducible results!
Now let’s train on training data and evaluate on both sets:
# Train on training data only
model_honest = LinearRegression()
model_honest.fit(X_train, y_train)
# Calculate RMSE on both sets
from sklearn.metrics import root_mean_squared_error
train_rmse = root_mean_squared_error(y_train, model_honest.predict(X_train))
test_rmse = root_mean_squared_error(y_test, model_honest.predict(X_test))
print(f"Training RMSE: ${train_rmse:.0f}")
print(f"Testing RMSE: ${test_rmse:.0f}")
print(f"Difference: ${test_rmse - train_rmse:.0f}")Training RMSE: $330
Testing RMSE: $403
Difference: $73
Business Insight: The difference tells us how well our model will generalize to future data!
Notice: Test RMSE ($403) > Training RMSE ($330) - this is normal! Our model performs slightly worse on new data because it was optimized for the training set. However, the larger this difference becomes the more concern we should have on whether we have a good model or not.
Let’s see the complete machine learning workflow using a fresh dataset:
# Step 1: Import a dataset
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, root_mean_squared_error
# Load the classic Advertising dataset
advertising = pd.read_csv("../data/Advertising.csv")
print("Dataset shape:", advertising.shape)
advertising.head()Dataset shape: (200, 4)
| TV | radio | newspaper | sales | |
|---|---|---|---|---|
| 0 | 230.1 | 37.8 | 69.2 | 22.1 |
| 1 | 44.5 | 39.3 | 45.1 | 10.4 |
| 2 | 17.2 | 45.9 | 69.3 | 9.3 |
| 3 | 151.5 | 41.3 | 58.5 | 18.5 |
| 4 | 180.8 | 10.8 | 58.4 | 12.9 |
Step 1 complete: We have our data loaded and ready!
# Step 2: Split data into features (X) and target (y), then train/test
X = advertising[['TV', 'radio', 'newspaper']] # Multiple predictors
y = advertising['sales'] # Target variable
# Split into train/test sets
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"Training set: {len(X_train)} samples")
print(f"Test set: {len(X_test)} samples")Training set: 160 samples
Test set: 40 samples
Step 2 complete: Data is properly split for honest evaluation!
Model coefficients:
TV: 0.045
radio: 0.189
newspaper: 0.003
Intercept: 2.979
Step 3 complete: Model is trained and ready to make predictions!
# Step 4: Evaluate model performance
train_predictions = model.predict(X_train)
test_predictions = model.predict(X_test)
# Calculate metrics
train_r2 = r2_score(y_train, train_predictions)
test_r2 = r2_score(y_test, test_predictions)
train_rmse = root_mean_squared_error(y_train, train_predictions)
test_rmse = root_mean_squared_error(y_test, test_predictions)
print("Performance Summary:")
print(f"Training R²: {train_r2:.3f} | Training RMSE: {train_rmse:.2f}")
print(f"Test R²: {test_r2:.3f} | Test RMSE: {test_rmse:.2f}")Performance Summary:
Training R²: 0.896 | Training RMSE: 1.64
Test R²: 0.899 | Test RMSE: 1.78
Complete workflow achieved! 🎉 We can now trust our model’s performance estimates.
We covered the core concepts, but there’s more to explore in your readings:
Tip
Bottom line: Today gave you the foundation. The readings will deepen your understanding and show you more advanced techniques!
Remember: A model that looks perfect on training data might be useless on new data!
This Week’s Lab Preview
In Thursday’s lab, you’ll get hands-on practice with:
Come prepared to become a regression modeling expert!
Next Tuesday: Advanced machine learning concepts and ensemble methods
Thursday Lab: Hands-on regression modeling and evaluation practice
Homework: This week’s Lab will serve as your homework!
BANA 4080 | Week 9