Ad Campaign Effectiveness Prediction using Stepwise Regression in ML

We offer you a brighter future with FREE online courses - Start Now!!

Even though marketing teams invest significant money in online and offline ad campaigns, identifying the factors that most effectively drive conversions remains challenging. In this project, we’ll predict campaign effectiveness (e.g., cost per acquisition or conversion rate) based on budget allocation, channel mix (social, search, display), targeting characteristics (age group, region), and creative attributes (ad length, format).

However, by applying stepwise regression, we’ll find the most impactful predictors and build an interpretable linear model that balances simplicity with predictive power—enabling marketers to optimise spend and maximise return.

Libraries Required

import pandas as pd               # Data manipulation  
import numpy as np                # Numerical operations  
import statsmodels.api as sm      # Statistical modeling  
from sklearn.model_selection import train_test_split   # Data splitting  
from sklearn.metrics import r2_score, mean_squared_error  # Evaluation  
import matplotlib.pyplot as plt   # Visualization  

Dataset

Advertising Campaign Dataset

Step-by-Step Code Implementation

Data Loading & Initial Inspection

We load a comprehensive ad campaign dataset—featuring budget, channel, region, creative format, impressions, clicks, and cost per conversion—and inspect its schema and statistics.

# Block 1: Load dataset
# Advertising Campaign Dataset – Kaggle :contentReference[oaicite:0]{index=0}
url = "https://www.kaggle.com/datasets/ziya07/advertising-campaign-dataset/download"
df = pd.read_csv(url)

# Inspect structure and summary
print(df.head())
print(df.info())
print(df.describe())

Data Preprocessing

Categorical fields (Channel, Region, Creative_Format) are one‑hot encoded; any incomplete records are dropped. We designate Cost_Per_Conversion as the response (y) and the remaining columns as predictors (X), then perform an 80/20 train‑test split.

# Block 2: Encode categorical variables and clean
# Assume columns: Channel (Search, Social, Display), Region, Creative_Format
df_enc = pd.get_dummies(df, 
                        columns=["Channel", "Region", "Creative_Format"], 
                        drop_first=True)

# Drop rows with missing values
df_enc = df_enc.dropna()

# Define predictors and target
X = df_enc.drop("Cost_Per_Conversion", axis=1)
y = df_enc["Cost_Per_Conversion"]

# Split into train/test (80/20)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

Stepwise Regression Function

The stepwise_selection function iteratively performs forward inclusion (adding the excluded predictor with the lowest p‑value below 0.01) and backward elimination (removing the included predictor with the highest p‑value above 0.05) until convergence—yielding a concise set of significant features.

# Block 3: Forward–backward stepwise selection
def stepwise_selection(X, y, 
                       initial_list=[], 
                       threshold_in=0.01, 
                       threshold_out=0.05, 
                       verbose=True):
    included = list(initial_list)
    while True:
        changed = False

        # Forward step: consider adding each excluded variable
        excluded = list(set(X.columns) - set(included))
        new_pvals = pd.Series(index=excluded, dtype=float)
        for col in excluded:
            model = sm.OLS(y, sm.add_constant(X[included + [col]])).fit()
            new_pvals[col] = model.pvalues[col]
        best_pval = new_pvals.min()
        if best_pval < threshold_in:
            best_var = new_pvals.idxmin()
            included.append(best_var)
            changed = True
            if verbose:
                print(f"Add  {best_var:30} p-value {best_pval:.6f}")

        # Backward step: consider removing each included variable
        model = sm.OLS(y, sm.add_constant(X[included])).fit()
        pvals = model.pvalues.iloc[1:]  # exclude intercept
        worst_pval = pvals.max()
        if worst_pval > threshold_out:
            worst_var = pvals.idxmax()
            included.remove(worst_var)
            changed = True
            if verbose:
                print(f"Drop {worst_var:30} p-value {worst_pval:.6f}")

        if not changed:
            break

    return included

Model Building & Evaluation

  • Model Fitting: Using the selected predictors, we fit an Ordinary Least Squares regression via statsmodels. The .summary() output shows coefficient estimates, standard errors, p‑values, R², and diagnostic statistics, facilitating interpretation of each factor’s impact on cost efficiency.
  • Evaluation: We generate predictions on the held‑out test set and compute R² (variance explained) and RMSE (root‑mean‑square error) to quantify model generalisation.
# Block 4: Feature selection
selected_features = stepwise_selection(X_train, y_train)

# Fit final OLS model
X_train_sel = sm.add_constant(X_train[selected_features])
model = sm.OLS(y_train, X_train_sel).fit()
print(model.summary())

# Predict on test set
X_test_sel = sm.add_constant(X_test[selected_features])
y_pred = model.predict(X_test_sel)

# Compute metrics
print("Test R²:", r2_score(y_test, y_pred))
print("Test RMSE:", np.sqrt(mean_squared_error(y_test, y_pred)))

Residual Diagnostics

Plotting residuals versus predicted cost checks for non‑random patterns or heteroscedasticity, validating key OLS assumptions.

# Block 5: Residual plot
residuals = y_test - y_pred
plt.scatter(y_pred, residuals)
plt.axhline(0, linestyle="--")
plt.xlabel("Predicted Cost per Conversion")
plt.ylabel("Residuals")
plt.title("Residuals vs. Predicted Cost")
plt.show()

Summary

By applying stepwise regression to ad campaign data, we distil the most influential drivers of cost per conversion—such as budget allocation across channels, targeting regions, and creative formats—while pruning less informative variables.

The resulting linear model achieves a strong balance between interpretability and predictive accuracy (high R², low RMSE), empowering marketers to allocate spend effectively and maximise ROI through a data‑driven strategy.

Your 15 seconds will encourage us to work even harder
Please share your happy experience on Google | Facebook

ProjectGurukul Team

The ProjectGurukul Team delivers project-based tutorials on programming, machine learning, and web development. We simplify learning by providing hands-on projects to help you master real-world skills. We also provide free major and minor projects for enginering students.

Leave a Reply

Your email address will not be published. Required fields are marked *