Polynomial Regression: Predict Ad Revenue
Part 5 of the ML Regression Lab. Capture nonlinear, diminishing-returns trends by adding a squared feature — fit a curve to ad-spend vs. revenue using plain LinearRegression.
@shvinn
Machine Learning Engineer
The whole series so far assumed relationships are straight lines. But ad spend vs.
revenue usually shows diminishing returns — each extra dollar buys a little
less. Part 5, the finale, fits that curve with polynomial regression —
and the surprise is that we still use plain LinearRegression.
Follow along:
05_digital_marketing_ad_revenue_predictionin github.com/shvinn/ai-lab-99.
The key idea
A model is "linear" in its parameters, not its features. If we add a new feature equal to the square of the input, a linear model can fit a curve:
That's just multiple linear regression where one "feature" happens to be . The technique — inventing new columns from existing ones — is feature engineering.
Step 1 — Baseline: a plain line
First fit a straight line so you have something to beat.
import pandas as pd
from sklearn.linear_model import LinearRegression
df = pd.read_csv("digital_marketing_data.csv")
X = df[["ad_spend_usd"]]
y = df["revenue_usd"]
linear = LinearRegression().fit(X, y)If the true relationship curves, a straight line will systematically under- and over-predict in different ranges — visible as structure in the residuals.
Step 2 — Engineer the squared feature
Add a column for alongside the original spend:
X_poly = pd.DataFrame()
X_poly["ad_spend_usd_squared"] = df["ad_spend_usd"] ** 2
X_poly["ad_spend_usd"] = df["ad_spend_usd"]Step 3 — Train the polynomial model
Same estimator, richer features:
poly_model = LinearRegression().fit(X_poly, y)
poly_model.coef_ # → [-4.22e-04, 6.51] (squared term, linear term)
poly_model.intercept_ # → 8123.73The negative coefficient on the squared term is the math expressing diminishing returns — the curve bends downward as spend grows.
Step 4 — Evaluate against the baseline
from sklearn.metrics import mean_squared_error
for name, m, feats in [("linear", linear, X), ("polynomial", poly_model, X_poly)]:
rmse = mean_squared_error(y, m.predict(feats)) ** 0.5
print(f"{name:>10} RMSE: {rmse:.2f}")The polynomial model should have the lower RMSE — proof the curve fits better than the line. (Beware: keep raising the degree and you'll overfit, chasing noise. Degree 2 is enough here.)
Step 5 — Deploy
import streamlit as st
def predict_revenue(ad_spend_usd):
return (-4.21948692e-04 * ad_spend_usd ** 2
+ 6.51043749 * ad_spend_usd + 8123.725871275172)
st.title("📊 Predict Revenue from Ad Spend")
ad_spend = st.number_input("Ad Spend (USD)", min_value=0.0, value=1000.0, step=100.0)
if st.button("Predict"):
st.metric("Estimated Revenue (USD)", f"${predict_revenue(ad_spend):,.2f}")Series wrap-up
You built five deployable models and, with them, the core toolkit of classical regression:
- Simple linear regression — one feature, the full workflow.
- Multiple linear regression — many features.
- Binary encoding — two-value categoricals.
- One-hot encoding — multi-value categoricals.
- Polynomial regression — nonlinear trends via feature engineering.
Same LinearRegression estimator throughout — what changed each time was the
features you fed it. That insight, more than any single model, is what
carries you into the rest of machine learning. The complete code for all five is
in github.com/shvinn/ai-lab-99.
Related reading
One-Hot Encoding: Predict Streaming Revenue
Part 4 of the ML Regression Lab. Handle a multi-category feature the right way — one-hot encode subscription tiers and predict a streaming user's monthly revenue.
Simple Linear Regression: Predict Housing Prices
Part 1 of the ML Regression Lab. Build, evaluate, and deploy a one-feature linear regression model that predicts house prices from area — the full workflow, end to end.