CoolFace
Modelpublic

alianassmaaa/notification-bad-timing-detector

sourceHugging Faceupdated 5mo agoView on Hugging Face
0likes
Model Card

๐Ÿ”” Notification Bad-Timing Probability Detector

Overview

Predicts the probability that now is a bad time to send a push notification. Uses 21 contextual signals: user activity patterns, battery status, and notification interaction history.

Performance

MetricCalibrated Model5-Model Ensemble
ROC-AUC0.83380.8344
PR-AUC0.85250.8595
Brier Score0.1657โ€”
Accuracy0.7583โ€”
F10.7766โ€”

Architecture

  • โ€”Base model: LightGBM gradient boosted trees โ€” SOTA for tabular data per Grinsztajn et al. 2022 and TabArena 2025
  • โ€”Calibration: Isotonic regression for well-calibrated probability output
  • โ€”Ensemble: 5 models with different random seeds (averaged for best robustness)
  • โ€”Hyperparameter tuning: Random search over 40 configurations with early stopping

Features (21 input signals)

CategoryFeatures
Timehourofday, dayofweek, hoursin, hourcos, isweekend, isnight
Batterybatterylevel, ischarging, batterychangerate
Activityscreenon, screenonduration30min, appopenslasthour, sessionlengthcurrent, timesincelastinteraction
Notificationsnotifshownlast30min, notifclickedlast30min, notifdismissedlast30min, notifignoredlast30min, notifshownlast24h, notifctrlast7d, recentnotificationdensity

Top Features by Importance

  1. 1.notif_ctr_last_7d โ€” 7-day notification click-through rate
  2. 2.time_since_last_interaction โ€” seconds since last user action
  3. 3.battery_level โ€” current battery percentage
  4. 4.notif_shown_last_30min โ€” notification fatigue signal
  5. 5.battery_change_rate โ€” battery drain rate

Usage

python
import pickle, numpy as np

with open("calibrated_model.pkl", "rb") as f:
    model = pickle.load(f)

# Feature order: hour_of_day, day_of_week, hour_sin, hour_cos, is_weekend, is_night,
# battery_level, is_charging, battery_change_rate, screen_on, screen_on_duration_30min,
# app_opens_last_hour, session_length_current, time_since_last_interaction,
# notif_shown_last_30min, notif_clicked_last_30min, notif_dismissed_last_30min,
# notif_ignored_last_30min, notif_shown_last_24h, notif_ctr_last_7d, recent_notification_density

features = np.array([[14, 2, 0.97, -0.22, 0, 0, 85.0, 0, -1.0, 1, 800, 6, 300, 15, 1, 1, 0, 0, 22, 0.4, 1.0]])
bad_timing_prob = model.predict_proba(features)[:, 1][0]
print(f"Bad timing probability: {bad_timing_prob:.3f}")  # ~0.07 = good time!

Decision Thresholds

ProbabilityAction
P < 0.3โœ… Send notification
0.3 โ‰ค P โ‰ค 0.5โš ๏ธ Consider priority
P > 0.5๐Ÿšซ Delay notification
P > 0.8๐Ÿ”ด Definitely delay

Training Details

  • โ€”Based on C-3PO (Cheetah Mobile, 600M MAU production system)
  • โ€”100K synthetic samples with realistic correlation patterns from mobile behavior research
  • โ€”70/15/15 train/val/test split
  • โ€”Dataset: alianassmaaa/notification-timing-dataset

Files

FileDescription
calibrated_model.pklCalibrated model (recommended for deployment)
ensemble_models.pkl5-model ensemble (best accuracy)
model_metadata.jsonFeatures, hyperparameters, metrics
feature_importances.csvFeature importance rankings
sweep_results.csvFull hyperparameter sweep results