Je développe un coach sportif qui envoie des relances sur Telegram. Une question s’est posée très tôt, et elle est moins simple qu’elle en a l’air : non pas quoi écrire, mais quand et combien de fois dans la journée. Trop de rappels deviennent un bruit que l’on ignore. Trop peu n’ont aucun effet. Et la bonne dose dépend de la personne : quelqu’un d’assidu n’a pas besoin du même rythme que quelqu’un qui n’a pas bougé depuis plusieurs jours.

Des horaires fixes (8 h, 13 h, 18 h tous les jours) règlent le problème en apparence, mais ils sont mécaniques : mêmes heures chaque jour, indifférents à ce que fait la personne. Mon objectif était l’inverse : que le coach relance comme le ferait un vrai coach humain. Un humain n’écrit pas à heure fixe. Il relance à des moments un peu imprévisibles, sans déranger en pleine nuit ni harceler, et il insiste davantage quand la personne décroche. Autrement dit : des horaires aléatoires, mais sous contraintes.

C’est exactement ce que décrit un processus ponctuel aléatoire. Le premier modèle que j’ai retenu est un processus de Poisson non-homogène. Il a fait tourner le coach en production pendant plusieurs semaines avant que je le remplace. Cet article décrit ce modèle : son intuition, ce qu’il fait, et ce qui m’a amené à en changer.

Un rappel comme un événement aléatoire

Un processus de Poisson décrit des événements qui surviennent au fil du temps à un certain débit : en moyenne, tant d’événements par unité de temps. Ici, les événements sont les rappels. La version la plus simple suppose un débit constant, par exemple deux rappels par jour répartis uniformément.

Ce débit constant ne convient pas. Il placerait un rappel à trois heures du matin avec la même probabilité qu’à midi. Or l’opportunité d’une séance n’est pas uniforme dans la journée : elle se concentre sur quelques moments. Il faut donc un débit qui dépend de l’heure. C’est ce que signifie « non-homogène ».

Une intensité qui suit la journée

On remplace le débit constant par une fonction du temps, $\mu(t)$, appelée intensité. Elle est proche de zéro la nuit et plus élevée autour des créneaux où une séance est plausible.

Je construis cette intensité comme une somme de trois courbes gaussiennes, centrées sur le matin, le midi et le soir. Chaque courbe a sa position, sa largeur et son poids. Dans ma configuration, les centres sont 7 h 30, 12 h 30 et 18 h. Le soir a le poids le plus élevé : c’est le moment où l’on s’entraîne le plus, une fois la journée de travail terminée.

Formellement, cette intensité est une somme de trois gaussiennes, à un facteur d’échelle global $\lambda$ près (le débit, fixé à la section suivante) :

$$ \mu(t) = \lambda \sum_{k=1}^{3} w_k \, \exp\!\left(-\frac{(t - c_k)^2}{2\,\sigma_k^2}\right) $$

avec les centres $c = (\text{7h30},\ \text{12h30},\ \text{18h00})$, les largeurs $\sigma = (45,\ 45,\ 60)$ minutes et les poids $w = (1.2,\ 0.8,\ 1.5)$.

Dans un processus de Poisson, le nombre de rappels ne dépend pas de la hauteur de l’intensité à un instant donné, mais de l’aire sous la courbe : sur une plage horaire, ce nombre suit une loi de Poisson dont la moyenne est cette aire. C’est donc l’aire, pas le trait, qu’il faut lire sur le graphe ci-dessous.

La planification est bornée à une fenêtre active. Avant 6 h et après 20 h (zones hachurées sur le graphe), l’intensité est nulle : aucun rappel n’est tiré. Dans la fenêtre, l’intensité reste strictement positive ; elle descend bas entre les bosses (vers 10 h, environ 0,5 % du pic) sans toutefois s’annuler.

Intensité des rappels sur 24 heures : trois pics à 7 h 30, 12 h 30 et 18 h, plancher la nuit

L’aire sous μ(t) donne le nombre de rappels. La planification est bornée à une fenêtre active (hachurée en dehors) ; trois zones autour de 7h30, 12h30 et 18h, le soir la plus large.

C’est un processus de Poisson pur, pas un processus auto-excitant (de type Hawkes). Un rappel ne rend pas le suivant plus probable. L’intensité ne dépend que de l’heure et de l’état de la personne, jamais des rappels déjà envoyés.

Un débit global qui s’adapte au comportement

La forme indique quand relancer. Reste à fixer combien : le débit $\lambda$, le facteur d’échelle de l’intensité. Je le module avec deux indicateurs du comportement récent : le taux de suivi des rappels (la compliance, notée $C$) et l’inactivité (le nombre de jours consécutifs sans séance, noté $D$) :

$$ \lambda = 2.2 + 1.5\,(1 - C) + 0.4\,D $$

avec $C \in [0, 1]$ et $D \geq 0$. La règle se lit directement : quand quelqu’un ignore les rappels ($C$ bas) et ne s’entraîne plus ($D$ élevé), $\lambda$ monte ; quand quelqu’un est assidu, $\lambda$ baisse. Le nombre de rappels d’une journée suit alors une loi de Poisson de moyenne $\Lambda = \int \mu(t)\,dt$ sur la fenêtre active. En l’absence de données (démarrage à froid), on part d’un état neutre.

$C$ et $D$ sont deux scalaires : ils résument le comportement passé en deux nombres. Ce point a son importance pour la suite.

La même intensité mise à l'échelle par le débit lambda selon trois comportements : assidu, moyen, décroché

La même forme, mise à l’échelle par le débit λ. Plus la personne décroche (compliance basse, inactivité élevée), plus l’intensité monte, et donc le nombre attendu de rappels. Les heures des pics ne changent pas ; seul le niveau change.

Des horaires concrets : l’amincissement

Une intensité continue ne suffit pas ; il faut en tirer des horaires précis. La méthode classique est l’amincissement (thinning), due à Lewis et Shedler (1979).

Le principe est le suivant. On simule d’abord un processus homogène au débit maximum $\mu_{\max}$, ce qui est facile : c’est une suite de délais exponentiels. On garde ensuite chaque candidat tiré à l’instant $t$ avec probabilité $\mu(t)/\mu_{\max}$, et on jette les autres. Les instants conservés suivent exactement l’intensité voulue :

μ_max = max_t μ(t)
t = 0
tant que t < T :
    t += Exponentielle(μ_max)        # candidat tiré au débit maximum
    si Uniforme(0,1) < μ(t) / μ_max : # test d'acceptation
        émettre un rappel à l'instant t

Quelques ajustements pratiques

L’amincissement brut peut placer deux rappels à quelques minutes d’intervalle, ou tomber sur une heure ronde qui fait mécanique. Trois ajustements suffisent :

  • un écart minimum (30 minutes) entre deux rappels ;
  • un décalage aléatoire (jitter, ±15 minutes) pour éviter des horaires trop réguliers ;
  • un plafond sur le nombre de rappels par jour.

À graine aléatoire fixée, le résultat est déterministe : mêmes indicateurs, même journée générée. Il est donc reproductible et testable.

Ce que produit le modèle

Une journée typique donne deux ou trois rappels, concentrés autour des créneaux plausibles, avec davantage de rappels si la personne a décroché. Surtout, les horaires ont l’allure de ceux d’un coach humain : variés d’un jour à l’autre, jamais en pleine nuit, plus fréquents quand la personne décroche. C’était l’objectif de départ. Le modèle est simple, transparent, et toute sa logique tient en quelques formules. Pour un premier modèle, c’est une base correcte.

Les limites du modèle

Les horaires avaient l’allure de ceux d’un humain. Mais un coach humain ne fait pas que varier ses heures : il se souvient de ce que la personne a fait et décide s’il vaut mieux la laisser tranquille. Ce modèle n’a rien de tel. Il résume tout le passé en deux nombres, $C$ et $D$, et rejoue la même mécanique chaque matin.

Le défaut le plus net est apparu en rejouant l’historique. En simulant un grand nombre de fois vingt-deux journées actives réelles, j’ai constaté que dans près de 5 % des cas, le processus ne tirait aucun rappel. C’est une propriété d’un processus de Poisson : même avec un débit strictement positif, la probabilité de tirer zéro événement n’est jamais nulle. Cela donne des journées où le coach reste silencieux alors que la personne attend une relance.

La cause est plus générale que ce symptôme. Un processus de Poisson est fait pour modéliser un flux exogène : des événements qui arrivent du monde extérieur et que l’on se contente d’observer. Or envoyer un rappel n’est pas un événement que j’observe. C’est une décision que je prends, pour une personne précise, sous contraintes : ne pas saturer, rester prudent, m’adapter à son état. Un modèle d’arrivées exogènes ne correspond pas à un problème de décision.

Reformulé, le problème n’est pas « simuler un flux », mais « décider quand et à quelle dose intervenir auprès d’une personne dont je ne connais l’état qu’indirectement ». C’est ce que la littérature appelle une intervention adaptative au bon moment (JITAI), et cela se modélise comme un processus de décision sous observation partielle, un POMDP. C’est le sujet du prochain article.

Conclusion

Le processus de Poisson non-homogène répartit des rappels adaptatifs sur une journée de manière simple, peu coûteuse et reproductible. Sa logique tient en quelques formules. Il a fait tourner mon coach pendant plusieurs semaines et reste disponible comme repli dans le système.

Mais il ne répond qu’à « quand ». La question « faut-il relancer, et à quelle dose » demande un modèle qui tient à jour une estimation de l’état de la personne et qui pèse le coût de chaque rappel. C’est le sujet de l’article suivant.