mobility-team / mobility

Mobility, an open-source library for mobility modelisation
MIT License
16 stars 11 forks source link

Implémenter le modèle de mobilité #15

Closed FlxPo closed 7 months ago

FlxPo commented 2 years ago

J'ai créé une nouvelle branche pour travailler sur le modèle de mobilité (https://github.com/mobility-team/mobility/tree/radiation-model), avec un squelette de fonction radiation_model, et le pseudo-code de l'algorithme.

Cette version du modèle nécessite de calculer un équilibrage des flux à l'échelle d'un ensemble de zones de transport (communes, IRIS...) pour prendre en compte la "concurrence" entre origines, qui n'est pas du tout prise en compte dans le modèle de radiation base. Elle permet de garantir que le volume au niveau des destinations ne sera pas dépassé par les flux entrants : pas plus d'employés que d'emplois, par exemple.

Cette version est itérative : à chaque itération, les individus sont supposés se comporter selon le modèle de radiation classique, en fonction des opportunités disponibles aux différentes destinations et des coûts pour atteindre ces destinations. Si une destination sature, une partie des individus ne peut pas la sélectionner. Ils se reportent donc sur les destinations non saturées restantes, et ainsi de suite jusqu'à convergence.

On peut dans un premier temps rester sur un modèle unimodal, l'extension multimodale devrait être assez facile.

AntoineGauchot commented 2 years ago

J'ai implémenté une 1ère version de modèle de mobilité (https://www.nature.com/articles/s41598-020-61613-y). La fonction _radiationmodel calcule les volumes de flux pour chaque O/D prenant en argument :

La fonction calcule les flux en normalisant selon les origines (ie le volume de chaque origine est entièrement converti en flux, autrement dit tous les individus de chaque origine choisissent une destination selon les opportunités disponibles et les coûts pour chaque destination). Puis on regarde les destinations qui reçoivent plus que leur capacité et on soustrait le surplus de chaque destination au flux : une partie des individus ayant choisi leur destination se retrouvent alors sans destination. La fonction renvoie

Il est possible de relancer la fonction _radiationmodel avec le volume de demande restant et le volume d'opportunités restant pour essayer d'attribuer les actifs restants à un lieu d'emploi restant. Et on peut encore répéter l'opération autant de fois que l'on souhaite (idéalement jusqu'à que tous les actifs aient un lieu d'emploi ou que tous les emplois aient été pourvus)

Pour la phase de test de la fonction, j'ai utilisé le nombre d'emplois et le nombre d'actifs à l'échelle nationale à l'échelle de la commune. On peut alors afficher le nombre d'actifs ayant un lieu d'emploi et le nombre d'emplois pourvus en fonction du nombre d'itérations (ie combien de fois on a appliqué la fonction _radiationmodel) :

image pour un nombre total d'actifs de 490 806 et un nombre total d'emplois de 475 549.

À la 10ème itération, il reste 50 703 actifs sans lieu d'emploi et 35 503 emplois non pourvus. Après quelques itérations, le modèle a du mal à attribuer des lieux d'emplois à des actifs soit car les lieux d'emploi restants sont très peu attractifs pour les actifs restants, soit car il n'y a pas de coût pour les OD correspondants.

De la même manière que l'on a normalisé les flux sur les volumes de demande, il est possible de normaliser les flux sur les volumes d'opportunités. On peut utiliser le même exemple pour tester le nombre d'emplois non pourvus en fonction du nombre d'itérations (le nombre d'emplois étant, au global, plus limitant que le nombre d'actif, on pourrait trouver logique de normaliser sur le nombre d'emplois pour minimiser la saturation) :

image

À la 10ème itération, il reste 60 594 actifs sans lieu d'emploi et 45 394 emplois non pourvus.

On peut aussi tester une alternance entre les deux : à l'itération i, on normalise selon les origines, à l'itération i+1, selon les destinations :

image

À la 10ème itération, il reste 47 516 actifs sans lieu d'emploi et 32 316 emplois non pourvus.

FlxPo commented 2 years ago

Toujours aussi rapide ! Tu as testé le modèle à l'échelle nationale, mais il n'y a que 500 000 emplois / actifs ?

Il y a peut être quelque chose de problématique dans les données d'entrée, qui bloque la convergence. Effectivement l'absence de coûts dans trips_average_unit_cost.csv pour certaines paires OD peut poser problème. Dans mon implémentation sur R et mes tests, l'algorithme converge bien, mais j'avais des coûts pour toutes les paires OD et c'était sur un plus petit territoire.

La normalisation selon les origines ne me semble pas correcte conceptuellement. Le besoin de normalisation des modèles de radiation émergerait si j'ai bien compris du fait qu'on travaille sur un système fini : il y a une chance qu'un individu "sorte de la carte" après avoir échappé à l'attraction de chaque puits d'opportunités. Dans un système infini, l'individu est absorbé à un moment ou un autre.

Cet article introduit un facteur de normalisation pour corriger le calcul, mais dans mes tests ça ne somme toujours pas à un, d'où la normalisation ad hoc faite jusqu'à présent p_ij = p_ij/sum_i(p_ij).

Cette normalisation par origine est correcte parce qu'elle s'applique à des probabilités conditionnelles par origine P(j | i). Si on voulait normaliser par destination il faudrait pouvoir calculer P(i | j), que le modèle de radiation ne donne pas ?

Tu peux peut être tester un cas très simple avec quelques sources, puits et coûts théoriques pour voir si cela fonctionne ?

Pour la raison du alpha = 0.3 / beta = 0.7, c'était juste des valeurs qui donnaient de bons résultats par rapport aux données INSEE, issues de l'extension du modèle de radiation proposée par Liu et Yan. Mais dans l'absolu ce serait pas mal de rester sur le modèle de radiation de base, pour éviter d'avoir des paramètres empiriques comme c'est le cas pour les modèles gravitaires.

AntoineGauchot commented 2 years ago

J'ai juste récupéré des fichiers csv qui me donnaient des emplois et des actifs par commune qui traînaient, je ne saurais pas dire à quoi ils correspondent exactement. C'était surtout pour vérifier que l'algo ne contenait pas de grosses erreurs.

Effectivement, j'ai retesté en hard-codant un coût sur toutes les OD qui n'en avaient pas et j'obtiens un algo qui converge (le plus petit volume entre le volume de demande et le volume d'offre tend rapidement vers 0). Donc pas de souci de ce côté là

Je comprends tes réserves sur le fait de normaliser par les origines (tout le volume de demande ne se dirige pas vers les destinations renseignées, il peut y avoir des destinations qui sont en-dehors de notre périmètre d'étude). Mais le fait d'itérer plusieurs fois le modèle de radiation va bien finir par attribuer une destination dans le périmètre d'étude à chaque demande, non ? Peut-être vaut-il mieux en parler de vive voix ? Ce n'est pas encore très clair dans ma tête

C'est noté pour la normalisation par destination, je l'enlèverai lors du prochain commit

Donc on reste sur alpha = 0.3 / beta = 0.7 ?

FlxPo commented 2 years ago

Top la convergence obtenue est rassurante (et normale vus les hypothèses, reste à voir la qualité du "fit" entre données INSEE et modèle...).

Désolé je me suis trompé en écrivant le message précédent : la normalisation par origine est OK (normalisation que j'avais bien décrite dans le pseudo code), mais pas celle par destination.

Et effectivement ça ne règle pas le problème des effets de bord. Il pose la question du périmètre et de la résolution de la modélisation, pour ne pas se retrouver à intégrer des zones de transport lointaines avec un très faible impact sur la mobilité locale. J'avais testé une stratégie d'augmentation de la taille des zones de transport en fonction de l'éloignement au centre de la zone d'étude, qui n'a pas très bien marché : commune -> EPCI -> Département...

Dans un premier temps j'aurais tendance à rester sur le modèle de radiation de base donc alpha = 0 / beta = 1, pour essayer d'expliquer les comportements uniquement via des variables explicites, qu'on peut faire varier : l'équilibre offre / demande local et les coûts de transport.

Mind-the-Cap commented 1 year ago

À faire en v0.2 : réintégrer les fonctions dans le code principal, et revoir les effets de bord possibles.