alianassmaaa/notification-bad-timing-detector
0
๐ 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
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)
Top Features by Importance
- notif_ctr_last_7d โ 7-day notification click-through rate
- time_since_last_interaction โ seconds since last user action
- battery_level โ current battery percentage
- notif_shown_last_30min โ notification fatigue signal
- battery_change_rate โ battery drain rate
Usage
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
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
