Article

Building SmartHabit: Predicting Smartphone Addiction with LightGBM, FastAPI & Kaggle

Discover how I built SmartHabit, an end-to-end machine learning application that predicts smartphone addiction risk using a LightGBM model trained on the Kaggle Playground Series dataset. This article covers exploratory data analysis, feature engineering, model comparison, FastAPI backend development, responsive web application design, automated testing, Docker deployment, and lessons learned while transforming a competition model into a production-ready AI application.

· 13 min read · Updated Aug 3, 2026

Smartphones are now deeply integrated into daily life. They support communication, education, entertainment, navigation, banking, work, and social interaction. At the same time, excessive and uncontrolled smartphone use can negatively affect sleep, concentration, productivity, relationships, and general wellbeing.

That tension inspired me to build SmartHabit, a complete machine-learning project that predicts the probability of the Kaggle target addicted_label from smartphone-use patterns, sleep, stress, work or study behaviour, and demographic information.

This project was developed for the CIS6005 Computational Intelligence module. It goes beyond training a model in a notebook: it includes data analysis, feature engineering, multiple model comparisons, cross-validation, a Kaggle submission, a production-style FastAPI backend, a responsive web application, automated tests, model explainability, security controls, and Docker configuration.

The complete source code is available on GitHub:

GitHub repository: github.com/SathiraSriSathsara/smartphone-addiction-project


Project overview

SmartHabit is an educational digital-wellbeing application. A user enters information such as daily screen time, social-media usage, gaming hours, sleep, stress, phone notifications, app-opening frequency, work or study time, and demographic details.

The application processes these inputs using the same feature-engineering and preprocessing pipeline used during training. It then generates:

  • a predicted class,
  • an addiction probability,
  • a non-addiction probability,
  • a Low, Moderate, or High risk band,
  • a short explanatory message,
  • and model factors that influenced the prediction.

The application is not a clinical system. It does not diagnose smartphone addiction or any medical or psychological condition.


Why I selected this problem

Smartphone addiction prediction is a strong computational-intelligence problem because it involves complex behavioural relationships rather than simple fixed rules.

A traditional rule-based system might say:

If daily screen time is above 8 hours, classify the user as addicted.

That approach is too simplistic. Two users may have the same screen time but very different usage patterns. One may use a phone mainly for work or education, while another may spend most of the time on gaming and social media with poor sleep and high stress.

Machine learning is more suitable because it can learn relationships among several variables simultaneously. It can capture nonlinear interactions such as:

  • high screen time combined with low sleep,
  • frequent notifications combined with repeated app openings,
  • high gaming or social-media usage relative to total screen time,
  • and differences between weekday and weekend behaviour.

This makes the problem suitable for models such as Logistic Regression, Random Forest, neural networks, and gradient-boosted decision trees.


The Kaggle competition

The project was based on the Kaggle competition:

Predicting Smartphone Addiction — Playground Series, Season 6, Episode 8

The target variable was:

addicted_label

The official evaluation metric was:

ROC AUC

ROC AUC evaluates how well a classifier ranks positive examples above negative examples across different decision thresholds. This was more appropriate than relying only on accuracy, especially because the target distribution was not perfectly balanced.

The final LightGBM submission achieved:

Kaggle public leaderboard ROC AUC: 0.96189

At the time the result was captured, the submission was ranked around 360 on the public leaderboard.

That score demonstrated that the complete pipeline—from preprocessing to probability generation and submission formatting—was working correctly.


Dataset scale

The training dataset contained:

691,369 rows

The final model used:

12 raw input features
4 engineered features
16 total model input columns

The dataset contained behavioural and demographic information related to:

  • smartphone usage,
  • social-media activity,
  • gaming,
  • work and study,
  • sleep,
  • stress,
  • notification frequency,
  • app-opening behaviour,
  • and user characteristics.

The id column was excluded from model training because it represented an identifier rather than a meaningful behavioural feature.


Exploratory data analysis

Before training any models, I performed exploratory data analysis to understand the dataset and identify potential modelling issues.

The analysis included:

  • dataset dimensions,
  • column types,
  • missing values,
  • duplicate records,
  • target distribution,
  • numerical feature distributions,
  • categorical feature distributions,
  • outlier inspection,
  • correlation analysis,
  • feature-to-target comparisons,
  • and train-versus-test distribution checks.

Several important design decisions came from this stage.

Stratified validation

The target classes were imbalanced, so I used stratified validation. This preserved a similar class distribution in the training and validation sets.

Missing-value handling

Numerical values were imputed using the median. Median imputation was selected because it is less sensitive to extreme values than the mean.

Categorical values were imputed using the most frequent category.

Feature scaling

Numerical scaling was used for models that benefit from normalized feature ranges, especially Logistic Regression and the multilayer perceptron.

Categorical encoding

Categorical variables were transformed using one-hot encoding with:

handle_unknown="ignore"

This prevents the application from crashing when it receives a category that was not present during model training.

Nonlinear relationships

The EDA suggested that behavioural factors interact in nonlinear ways. This supported testing tree-based ensemble models, particularly Random Forest and LightGBM.


Feature engineering

The project includes a shared feature-engineering module used by both training and inference.

Four derived features were created from the raw inputs. These features capture relationships such as usage ratios rather than treating every variable independently.

Examples of useful engineered concepts include:

  • social-media usage as a proportion of total screen time,
  • gaming time relative to daily screen time,
  • notifications per screen-time hour,
  • and app openings per screen-time hour.

This is important because raw values alone may not describe behaviour accurately.

For example, 200 notifications per day may mean something different for a user with 12 hours of screen time compared with a user with 2 hours of screen time.

The reusable feature-engineering logic is stored separately so that the API applies the same transformations used during model development.


Models compared

I compared four machine-learning approaches.

Logistic Regression

Logistic Regression was used as an explainable linear baseline.

Its main strengths were:

  • simplicity,
  • fast training,
  • interpretable coefficients,
  • and efficient probability prediction.

Its limitation was that it could not capture complex nonlinear feature interactions as effectively as tree-based models.

Random Forest

Random Forest represented a bagging-based ensemble method.

Its strengths included:

  • nonlinear decision boundaries,
  • robustness to feature interactions,
  • and reduced variance through multiple decision trees.

Its disadvantages included larger memory requirements and slower inference compared with simpler models.

MLP neural network

A multilayer perceptron was included as a neural-network comparison.

It was capable of learning nonlinear relationships, but it required:

  • scaled inputs,
  • careful tuning,
  • more computational effort,
  • and less straightforward interpretation.

For structured tabular data, the neural network did not provide enough advantage to justify selecting it as the final model.

LightGBM

LightGBM was the strongest model in the comparison.

It is a gradient-boosting framework that builds decision trees sequentially. Each new tree attempts to reduce the errors made by the previous trees.

LightGBM worked particularly well because:

  • the dataset was large,
  • the features were tabular,
  • relationships were nonlinear,
  • interactions between behavioural variables mattered,
  • and probability predictions were required.

The verified model results were:

Holdout ROC AUC: 0.9597828493
Three-fold mean ROC AUC: 0.9603813962
Cross-validation standard deviation: 0.0004852321
Kaggle public ROC AUC: 0.96189

The small cross-validation standard deviation indicated stable performance across folds.


Why LightGBM was selected

The final model was not chosen only because it had the highest score.

I also considered:

  • cross-validation stability,
  • training time,
  • inference speed,
  • suitability for structured tabular data,
  • probability support,
  • ease of deployment,
  • and compatibility with model explainability.

LightGBM offered the best balance of performance and practicality.

It also produced a relatively compact saved model, making it appropriate for a web API.


Preventing preprocessing mismatch

One of the most common mistakes in machine-learning deployment is applying different preprocessing during training and production.

To avoid this, I saved the full pipeline using Joblib.

The saved artifact includes:

feature preprocessing
        ↓
categorical encoding
        ↓
numerical processing
        ↓
LightGBM classifier

The application loads the trusted local pipeline at startup and uses the exact same transformations for every prediction.

This helps prevent problems such as:

  • incorrect feature ordering,
  • missing encoders,
  • unknown categories,
  • different imputation rules,
  • and training-versus-inference inconsistencies.

System architecture

The project separates experimentation, production code, presentation, testing, and documentation.

Kaggle data
    ↓
Google Colab notebook
    ↓
EDA and feature engineering
    ↓
Model comparison and cross-validation
    ↓
LightGBM pipeline
    ↓
Joblib model artifact
    ↓
FastAPI backend
    ↓
HTML/CSS/JavaScript frontend
    ↓
Prediction result

The repository structure includes:

api/          FastAPI application and routes
data/         Kaggle files
docs/         Architecture, API, model and demo documentation
models/       Saved model and runtime metadata
notebooks/    Training and evaluation notebook
outputs/      Results, figures and submissions
screenshots/  Assignment and application evidence
src/          Shared feature engineering
tests/        Unit and integration tests
web/          Frontend pages and assets

This structure keeps the project easier to maintain and demonstrate.


FastAPI backend

The backend was built using FastAPI.

The main endpoints include:

GET  /
GET  /api/health
GET  /api/model/info
GET  /api/model/schema
POST /api/predict

Health endpoint

The health endpoint confirms that the API is running.

Model-information endpoint

This exposes safe information such as:

  • model name,
  • target,
  • feature count,
  • official metric,
  • and application version.

It does not expose internal file paths or sensitive environment details.

Model-schema endpoint

The frontend retrieves the model schema from the API. This reduces hardcoded assumptions and helps ensure the form matches the model’s real inputs.

Prediction endpoint

The prediction workflow is:

JSON request
    ↓
Pydantic validation
    ↓
Pandas DataFrame
    ↓
Feature engineering
    ↓
Saved pipeline
    ↓
predict_proba
    ↓
Risk response

The API returns probabilities rather than only a class label.

A response may look like:

{
  "predicted_class": 1,
  "addiction_probability": 0.824,
  "non_addiction_probability": 0.176,
  "risk_level": "High",
  "risk_message": "The model detected a high predicted likelihood based on the supplied usage pattern.",
  "disclaimer": "This result is generated by an educational machine-learning model and is not a medical diagnosis."
}

Input validation

The API uses Pydantic to validate user input.

Validation checks include:

  • required fields,
  • expected data types,
  • allowed categorical values,
  • realistic numeric limits,
  • rejection of NaN and infinity,
  • and rejection of extra untrained fields.

This is important because machine-learning models often fail silently or produce unreliable outputs when given invalid inputs.

The application returns clear validation errors rather than allowing invalid values to reach the model.


Risk bands

The frontend displays the probability using three non-clinical bands:

Low: probability below 0.35
Moderate: probability from 0.35 to below 0.65
High: probability 0.65 or above

These thresholds are only presentation categories.

They are not medical thresholds and do not diagnose addiction.


Model explainability

The application includes per-prediction LightGBM contribution explanations.

It returns up to five readable factors that influenced the model’s output.

The interface labels these as:

Model factors influencing this prediction

This wording is deliberate.

The application does not claim that these factors caused addiction. Model contribution is not the same as real-world causation.

Explainability improves transparency, but it must still be interpreted cautiously.


Frontend design

The frontend uses plain:

  • HTML,
  • CSS,
  • and JavaScript.

It includes:

  • a responsive landing page,
  • a prediction form,
  • model information,
  • a project page,
  • a disclaimer page,
  • loading states,
  • error messages,
  • and a prediction-result dashboard.

The visual identity uses:

  • dark teal and navy backgrounds,
  • coral action elements,
  • clear typography,
  • responsive layouts,
  • and accessible controls.

The application does not require login or registration because it is a public educational prototype.


Privacy and security

Although this is a university project, I designed it using production-oriented practices.

The API includes:

  • restricted CORS,
  • request-size protection,
  • safe JSON errors,
  • request IDs,
  • structured logging,
  • security headers,
  • and singleton model loading.

The model is loaded once during application startup rather than for every request.

The project does not include:

  • user accounts,
  • a user database,
  • or permanent prediction storage.

This reduces unnecessary collection of personal behavioural information.

The repository also recommends applying rate limiting at the deployment boundary if the application is published publicly.


Automated testing

The project contains automated tests for:

  • feature engineering,
  • API health,
  • model loading,
  • schema generation,
  • input validation,
  • prediction output,
  • probability ranges,
  • explainability,
  • safe failures,
  • CORS,
  • request limits,
  • request IDs,
  • and security headers.

The verified documentation-stage test result was:

39 tests passed

The source code can also be checked using:

python -m compileall -q api src

These tests make it easier to detect regressions when changing the API or frontend.


Running the project locally

The model was saved using Python 3.12, so Python 3.12 is recommended.

Create the virtual environment

python -m venv .venv
.\.venv\Scripts\Activate.ps1

Install dependencies

python -m pip install --upgrade pip
python -m pip install -r requirements.txt
Copy-Item .env.example .env

Start the application

python -m uvicorn api.main:app --host 127.0.0.1 --port 8000

Then open:

Landing page:
http://127.0.0.1:8000/

Prediction page:
http://127.0.0.1:8000/predict.html

Swagger documentation:
http://127.0.0.1:8000/docs

Health endpoint:
http://127.0.0.1:8000/api/health

The repository includes complete setup and usage instructions.


Docker support

The project includes:

Dockerfile
docker-compose.yml
.dockerignore

The container is designed to:

  • use a Python 3.12 slim image,
  • run as a non-root user,
  • expose one application port,
  • serve both the frontend and API,
  • include a health check,
  • and exclude raw training data, notebooks, screenshots, and unnecessary output files.

The frontend and API are available through:

http://localhost:8000/

The repository notes that Docker commands still require final verification in an environment where Docker Engine or Docker Desktop is available.


Key challenges

Model compatibility

Scikit-learn Joblib artifacts can be sensitive to package versions.

The model was trained using a particular Scikit-learn version, so the project records environment metadata and validates pickle-critical versions during startup.

This prevented unsafe loading when the runtime version did not match the training version.

Large dataset

The dataset contained more than 690,000 training records.

This required balancing:

  • modelling quality,
  • cross-validation reliability,
  • memory usage,
  • and Colab runtime.

Keeping feature engineering consistent

Feature engineering had to behave identically in the notebook and API.

Moving the shared logic into a reusable module reduced duplication and inference errors.

Communicating predictions responsibly

A probability such as 82% can easily be misunderstood as medical certainty.

The application therefore:

  • uses a visible disclaimer,
  • avoids diagnostic language,
  • labels thresholds as display bands,
  • and describes model factors as influences rather than causes.

Limitations

Despite the strong Kaggle result, the project has important limitations.

Competition data may not represent real populations

The dataset may not reflect every age group, culture, occupation, or usage context.

Inputs may be self-reported

Users may estimate screen time, stress, notifications, or sleep inaccurately.

Kaggle performance is not clinical validation

A public ROC AUC of 0.96189 demonstrates competition performance, not medical reliability.

Risk thresholds are arbitrary display bands

The Low, Moderate, and High categories were designed for user communication. They were not clinically validated.

Distribution shift

Real-world users may have behaviour patterns that differ from the competition data.

Potential bias

The model may perform differently across demographic groups. A complete production system would need subgroup evaluation and fairness testing.

Explainability is not causality

Feature contributions show how the model arrived at a prediction. They do not prove why a person behaves in a certain way.


Future improvements

Several improvements could make SmartHabit stronger.

Probability calibration

Calibration would help assess whether predicted probabilities correspond closely to observed frequencies.

Fairness analysis

The model could be evaluated across demographic groups to identify unequal error rates.

Real-world external validation

A properly consented dataset from real users would provide stronger evidence of generalisability.

Temporal modelling

The current model uses structured summary features.

Future versions could use time-series data such as:

  • hourly screen-time patterns,
  • app-session sequences,
  • notification timing,
  • and sleep-related usage.

Recurrent neural networks or transformers may become more suitable for that type of sequential data.

Federated learning

A privacy-preserving mobile version could train or adapt models without centralizing raw user behaviour.

Drift monitoring

A deployed system should monitor whether incoming usage patterns differ from the training data.

Mobile application

The FastAPI backend could support a Flutter or native mobile client.


What I learned

This project taught me that a successful machine-learning solution requires much more than training a high-scoring model.

The full workflow included:

  • understanding the problem,
  • inspecting the data,
  • handling missing values,
  • comparing algorithms,
  • preventing leakage,
  • validating performance,
  • creating Kaggle submissions,
  • preserving preprocessing,
  • managing package compatibility,
  • developing an API,
  • building a frontend,
  • writing tests,
  • adding security controls,
  • and communicating limitations responsibly.

The most valuable lesson was the importance of consistency between experimentation and deployment.

A model that performs well in a notebook is not useful if the production application applies different transformations or accepts invalid input.


Final result

SmartHabit successfully combines:

  • a large structured dataset,
  • a LightGBM classification model,
  • stratified validation,
  • stable cross-validation,
  • a Kaggle public score of 0.96189,
  • a reusable feature-engineering pipeline,
  • a FastAPI prediction service,
  • a responsive web interface,
  • per-prediction explanations,
  • automated testing,
  • security controls,
  • and deployment documentation.

It demonstrates how a Kaggle experiment can be transformed into a complete computational-intelligence application.

The project remains an educational prototype, but it provides a strong foundation for future work in digital wellbeing, behavioural analytics, responsible AI, and privacy-aware mobile intelligence.

Source code

Explore the complete project on GitHub:

SmartHabit — Smartphone Addiction Prediction Project