Support Ticket Cost Prediction using Bayesian Regression in ML

FREE Online Courses: Elevate Skills, Zero Cost. Enroll Now!

Customer support organisations need to forecast the total resolution cost for an incoming help‑desk ticket before allocating resources. Early‑ticket indicators—priority (low/medium/high), issue category (software/hardware/billing), time to first response, and customer tenure—drive both labour hours and escalation risk. Costs scale nonlinearly (critical tickets often incur senior‑engineer rates; repeated escalations spike total hours), and future costs carry uncertainty from customer-behaviour variability and labour-rate fluctuations. By applying Bayesian Regression, we derive:

1. A point estimate of resolution cost per ticket.

2. A credible interval quantifying our uncertainty—enabling data‑driven staffing, SLA‑pricing, and budget provisioning.

Libraries Required

import pandas as pd                              # data loading & manipulation  
import numpy as np                               # numerical operations  

import matplotlib.pyplot as plt                  # plotting  
import seaborn as sns                            # visualization  

import pymc3 as pm                               # Bayesian modeling  
import arviz as az                               # posterior analysis  

from sklearn.model_selection import train_test_split  
from sklearn.preprocessing import StandardScaler  
from sklearn.metrics import mean_absolute_error  

Dataset

Customer Support Ticket Dataset

Step-by-Step Code Implementation

Data Loading & Preprocessing

  • One‑hot encode priority and category so discrete ticket features drive cost.
  • Z‑score numeric features (time_to_first_response, customer_tenure_days) to aid MCMC convergence and ensure uniformly scaled priors.
import pandas as pd

# Load ticket data
df = pd.read_csv("data/customer_support_tickets.csv")

# Keep relevant fields and drop any missing rows
df = df[['priority','category','time_to_first_response',
         'customer_tenure_days','resolution_cost']].dropna()

# One-hot encode categorical features
df = pd.get_dummies(df, columns=['priority','category'], drop_first=True)

# Split into predictors and target
X = df.drop(columns='resolution_cost').values
y = df['resolution_cost'].values

# Train/test split (80% train / 20% test)
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# Standardize numeric columns for stable MCMC
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler().fit(X_train[:, :2])  # first two cols are numeric
X_train_s = X_train.copy()
X_train_s[:, :2] = scaler.transform(X_train[:, :2])
X_test_s = X_test.copy()
X_test_s[:, :2] = scaler.transform(X_test[:, :2])

Define & Fit Bayesian Regression Model

Model:

  • α (intercept) and β (coefficients) receive weakly informative Normal priors.
  • σ (residual noise) has a HalfNormal prior to enforce positivity.
  • Observed costs follow Normal(α + X·β, σ).

Sampling: We draw 2,000 posterior samples with 1,000 tuning iterations, using target_accept=0.9 for robust exploration.

import pymc3 as pm

with pm.Model() as ticket_cost_model:
    # Priors
    α = pm.Normal("α", mu=0, sigma=100)                                # intercept
    β = pm.Normal("β", mu=0, sigma=50, shape=X_train_s.shape[1])       # coefficients
    σ = pm.HalfNormal("σ", sigma=50)                                   # noise scale

    # Linear predictor
    μ = α + pm.math.dot(X_train_s, β)

    # Likelihood
    Y_obs = pm.Normal("Y_obs", mu=μ, sigma=σ, observed=y_train)

    # MCMC sampling
    trace = pm.sample(
        draws=2000,       # posterior draws
        tune=1000,        # burn‑in
        target_accept=0.9,
        return_inferencedata=True
    )

Posterior Analysis & Point Predictions

  • Posterior Predictive: Sampling from the model yields predictive distributions (ppc) from which we extract mean forecasts and 94% HPD intervals for new inputs.
  • Evaluation: Mean Absolute Error (MAE) on held-out tickets quantifies the average point-forecast error.
import arviz as az
from sklearn.metrics import mean_absolute_error

# Summarize posterior distributions
az.summary(trace, round_to=2)

# Posterior predictive sampling
with ticket_cost_model:
    ppc = pm.sample_posterior_predictive(trace, var_names=["Y_obs"])

# Compute posterior means of parameters
α_post = trace.posterior["α"].mean().item()
β_post = trace.posterior["β"].mean(dim=["chain","draw"]).values

# Point predictions on the test set
y_pred = α_post + X_test_s.dot(β_post)

# Evaluate MAE
mae = mean_absolute_error(y_test, y_pred)
print(f"Test MAE: ${mae:.2f}")

Visualise Predictions & Credible Intervals

Sweeping time_to_first_response while holding other features at typical values, we plot the posterior mean cost curve with its credible band—illustrating both the expected cost reduction from faster responses and the uncertainty around that benefit.

import numpy as np
import matplotlib.pyplot as plt

# Sweep time_to_first_response; hold other features at median
grid_times = np.linspace(X_train_s[:,0].min(), X_train_s[:,0].max(), 100)
grid = np.median(X_train_s, axis=0)[None,:].repeat(100, axis=0)
grid[:,0] = grid_times

with ticket_cost_model:
    ppc_grid = pm.sample_posterior_predictive(trace,
                                              var_names=["Y_obs"],
                                              samples=1000)

preds     = ppc_grid["Y_obs"]
mean_pred = preds.mean(axis=0)
hpd       = az.hdi(preds, hdi_prob=0.94)

# Back‑transform time_to_first_response
time_orig = scaler.inverse_transform(grid)[:,0]

plt.figure(figsize=(8,5))
plt.plot(time_orig, mean_pred, label="Posterior mean")
plt.fill_between(time_orig, hpd[:,0], hpd[:,1], alpha=0.3,
                 label="94% credible interval")
plt.scatter(
    scaler.inverse_transform(X_test_s)[:,0],
    y_test, color="k", alpha=0.5, label="Test data"
)
plt.xlabel("Time to First Response (hours)")
plt.ylabel("Resolution Cost (USD)")
plt.title("Bayesian Regression: Cost vs. First Response Time")
plt.legend()
plt.tight_layout()
plt.show()

Summary

This Bayesian Regression pipeline for Support Ticket Cost Prediction provides:

1. Accurate point estimates of ticket resolution cost from early indicators.

2. Credible intervals quantifying forecast uncertainty—critical for SLA budgeting and staffing.

3. Actionable insights: managers can allocate resources, set response‑time targets, and price support SLAs with confidence bounds, optimising both cost efficiency and service quality.

Did we exceed your expectations?
If Yes, share your valuable feedback 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 *