Wellness Tourism Purchase Prediction Model

This model estimates whether a customer will purchase a wellness tourism package. It is the promoted model from an MLOps workflow covering versioned data, model comparison, MLflow experiment tracking, skops serialization, Hugging Face model storage, and Jenkins-managed application deployment.

Try the deployed application at pesapaygateway.com:9450.

Model Details

Property Value
Task Binary tabular classification
Target ProdTaken
Positive class 1 - customer purchased the package
Negative class 0 - customer did not purchase the package
Estimator GradientBoostingClassifier
Artifact Complete preprocessing and classifier pipeline
Serialization skops
Selection metric F1 score
Random state 42

The fitted classifier uses 200 estimators, a learning rate of 0.1, maximum tree depth of 5, and min_samples_split=2.

Intended Use

The model is intended for:

  • Demonstrating an end-to-end MLOps workflow for tabular classification.
  • Estimating package-purchase propensity from a customer profile and sales interaction.
  • Supporting prioritization or follow-up decisions when a person reviews the prediction alongside business context.

It is not intended to make autonomous eligibility, pricing, credit, health, employment, or other high-impact decisions. A probability is a model estimate, not a guarantee that a customer will or will not purchase.

Training Data

The processed data comes from the Wellness Tourism Dataset. Customer identifiers and the source index column were removed before a stratified 80/20 train/test split.

Split Rows Negative (0) Positive (1)
Train 3,302 2,664 638
Test 826 667 159

The positive class represents approximately 19% of each split. F1 was selected as the primary optimization metric so model comparison would account for both precision and recall under this class imbalance.

Preprocessing

The artifact contains preprocessing and prediction in one scikit-learn Pipeline:

  • Numerical missing values are imputed with the median.
  • Categorical missing values are imputed with the most frequent value.
  • Categorical features are one-hot encoded with unknown categories ignored.
  • The transformed features are passed to the Gradient Boosting classifier.

Keeping preprocessing in the artifact ensures that training and application inference use the same transformations.

Input Schema

The model uses inference schema 1.0.0, published as inference_schema.v1.json. This machine-readable JSON Schema defines required fields, types, ranges, categorical values, target metadata, and rejection of unknown fields. The model expects a pandas DataFrame with these 18 case-sensitive columns in schema order.

Feature Type Description / observed values
Age Numeric Customer age
TypeofContact Categorical Self Enquiry, Company Invited
CityTier Integer City tier: 1, 2, or 3
DurationOfPitch Numeric Sales pitch duration in minutes
Occupation Categorical Salaried, Small Business, Free Lancer, Large Business
Gender Categorical Primarily Male or Female; source data also contains Fe Male
NumberOfPersonVisiting Integer Number of travelers
NumberOfFollowups Numeric Number of sales follow-ups
ProductPitched Categorical Basic, Standard, Deluxe, Super Deluxe, King
PreferredPropertyStar Numeric Preferred property rating: 3, 4, or 5
MaritalStatus Categorical Single, Married, Divorced, Unmarried
NumberOfTrips Numeric Number of trips taken per year
Passport Integer 0 for no, 1 for yes
PitchSatisfactionScore Integer Satisfaction score from 1 to 5
OwnCar Integer 0 for no, 1 for yes
NumberOfChildrenVisiting Numeric Number of children traveling
Designation Categorical Executive, Manager, Senior Manager, AVP, VP
MonthlyIncome Numeric Customer monthly income

Model Selection

Decision Tree, Random Forest, and Gradient Boosting pipelines were tuned and compared. Hyperparameter search used five-fold GridSearchCV with F1 as the scoring function. The selected Gradient Boosting configuration achieved a mean cross-validation F1 of 0.7481 and the strongest held-out F1 among the candidate pipelines.

Experiments, parameters, metrics, and serialized pipelines were tracked with MLflow.

Test Performance

Metrics below were calculated once on the held-out test split.

Metric Score
Accuracy 0.9274
Precision 0.9160
Recall 0.6855
F1 0.7842
ROC-AUC 0.9495

The default classifier threshold was used. These results describe this test split and may not transfer unchanged to new populations or later time periods.

Promotion Policy

Deployment is blocked unless the candidate passes the versioned policy below on the fixed test split:

Check Requirement Current model
Accuracy At least 0.90 0.9274
Precision At least 0.85 0.9160
Recall At least 0.65 0.6855
F1 At least 0.75 0.7842
ROC-AUC At least 0.90 0.9495
F1 regression No more than 0.01 below incumbent Pass

The gate pins inference schema 1.0.0, validates the schema version, ordered model and test-data features, and every test value. It also rejects unexpected serialized types. Jenkins runs the evaluator and its rejection tests before replacing the deployed container, then archives the JSON decision report with the build.

Inference

Install compatible runtime packages:

pip install pandas scikit-learn skops huggingface_hub

Download and load the artifact:

import pandas as pd
import skops.io as sio
from huggingface_hub import hf_hub_download

model_path = hf_hub_download(
        repo_id="motidev/wellness-tourism-model",
        filename="wellness_tourism_model.skops",
)

# Review these types before trusting an artifact from an unfamiliar publisher.
trusted_types = sio.get_untrusted_types(file=model_path)
model = sio.load(model_path, trusted=trusted_types)

customer = pd.DataFrame(
        [
                {
                        "Age": 35,
                        "TypeofContact": "Self Enquiry",
                        "CityTier": 1,
                        "DurationOfPitch": 15.0,
                        "Occupation": "Salaried",
                        "Gender": "Male",
                        "NumberOfPersonVisiting": 2,
                        "NumberOfFollowups": 3.0,
                        "ProductPitched": "Basic",
                        "PreferredPropertyStar": 3.0,
                        "MaritalStatus": "Single",
                        "NumberOfTrips": 2.0,
                        "Passport": 0,
                        "PitchSatisfactionScore": 3,
                        "OwnCar": 0,
                        "NumberOfChildrenVisiting": 0.0,
                        "Designation": "Executive",
                        "MonthlyIncome": 25000.0,
                }
        ]
)

prediction = int(model.predict(customer)[0])
purchase_probability = float(model.predict_proba(customer)[0, 1])

For reproducible production inference, pin revision in hf_hub_download to a tested Hugging Face commit instead of following main.

Limitations and Risks

  • The dataset is relatively small and the positive class is underrepresented.
  • Recall is lower than precision, so the model misses some customers who purchase the package.
  • The source includes demographic and socioeconomic fields. Performance and fairness have not been audited across demographic groups.
  • The source contains a gender-label inconsistency (Female and Fe Male).
  • Probability calibration, data drift, and concept drift have not been tested.
  • The app accepts a constrained set of values, but the pipeline itself ignores previously unseen categories rather than rejecting them.
  • Results should be monitored and re-evaluated before use with a different customer population or business process.

Deployment

The Streamlit application downloads this artifact from Hugging Face and serves predictions from a Docker container. Jenkins builds the image, replaces the running container, and verifies Streamlit's health endpoint. Hugging Face is used as the model registry; it is not the application runtime.

Live application: https://pesapaygateway.com:9450/

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Dataset used to train motidev/wellness-tourism-model