Méthode de Monte-Carlo

Bonjour,

je suis en train de lire le chapitre sur les méthodes de Monte-Carlo dans le livre de Walter Appel "probabilités pour les non-probabilistes" et il y a un détail qui me laisse perplexe.

Afin de situer le contexte, je paraphrase le livre. On dispose d'une fonction $\varphi$ de $[a,b]$ dans $\R$, que l'on suppose intégrable et on veut estimer $\int_a^b \varphi(x)dx$. Dans un premier temps, le théorème de transfert montre que si $X$ est une va qui suit la loi uniforme sur $[a,b]$, alors $\int_a^b \varphi = (b - a) \mathbb E(\varphi(X))$. Puis, la loi des grands nombres permet d'obtenir informatiquement une estimation de $\mathbb E(\varphi(X))$.
Ensuite, si $\varphi$ est comprise entre $0$ et un réel $M$, on peut aussi remarquer que l'intégrale que l'on veut calculer est l'aire du domaine $A$ délimité par la courbe de $\varphi$, l'axe des abscisses et les droites d'équation $x=a$ et $x=b$, ce qui peut s'écrire $\iint_{A} dxdy$. Pour estimer cette intégrale, il utilise une méthode de rejet : on choisit un couple $(x,y)$ selon la loi uniforme sur $[a,b]\times[0,M]$ et on décide si ce couple appartient à $A$. Une estimation de l'aire de $A$ est alors la proportion des points tirés dans $[a,b]\times[0,M]$ qui sont dans $A$.

Enfin, on en arrive à ce qui me pose problème, le cas d'une fonction $\varphi$ de $\R^d$ dans $\R$, dont on veut calculer l'intégrale sur un domaine $K$ de $\R^d$.
- si le domaine d'intégration $K$ est un pavé de volume $V$, alors on a comme précédemment $\int_{K} \varphi = V \mathbb E(\varphi(X))$ où $X$ suit la loi uniforme sur le pavé.
- si le domaine d'intégration $K$ est plus compliqué de la forme $K = \{F(x_1,...,x_d) \leq 0\}$ et que l'on connaît un pavé $Q$ qui contient $K$, alors on utilise la méthode du rejet et l'auteur donne un algorithme de calcul que je mets en pièce jointe.
C'est cet algorithme qui me pose problème. D'après ce que j'ai compris de la méthode du rejet, on tire un grand nombre $n$ de fois un vecteur $(x_1,...,x_d)$ uniformément dans le pavé $Q$. Si ce vecteur appartient à $K$, alors on incrémente un sommeur de $\varphi(x_1,...,x_d)$. On renvoie ce sommeur multiplié par le volume du pavé $Q$ que l'on divise par $n$. Mais l'auteur ne donne pas cet algorithme : il tire $n$ vecteurs dans $K$ (en les tirant dans $Q$ et ne gardant que ceux qui sont dans $K$), calcule la somme des images par $\varphi$ de ces vecteurs et renvoie comme moi la somme multiplié par le volume du pavé $Q$ que l'on divise par $n$.
J'ai testé cet algorithme sur un exemple simple d'intégrale d'une fonction de deux variables et le test me donne raison, mais j'aimerais bien avoir confirmation que je n'ai pas compris de travers.83428

Réponses

  • Bonjour,

    Je n'ai pas très bien compris à quel endroit l'auteur commettrait une boulette ou à quel endroit c'est toi qui a raison.

    Est-ce que ton objection est sur le fait qu'on multiplie à la fin par le Volume(Q) au lieu de multiplier par Volume(K) (dans le cas d'un ensemble K "compliqué") ? Le "V" du programme, selon moi, est bien le volume de l'ensemble d'intégration que ce soit Q (cas simples) ou K (cas compliqués).
    Et la méthode algorithmique est de choisir d'abord dans Q un élément puis de vérifier s'il est dans K avant de sommer.

    Pardon si je suis à côté de la plaque..
  • L’algorithme que tu donnes est bon : on tire des points au hasard jusqu'à en avoir $n$ dans le domaine de validité.
  • Pas de souci, c'est peut-être moi qui suis à côté de la plaque :-D

    Pas d'objection sur le volume. Mon objection est sur la manière de sommer :
    - moi, je dirais qu'on choisit n points dans Q, qu'on prend ceux qui sont dans K et qu'on somme la valeur de $\varphi$ sur ces $k$ points (avec $k$ qui est donc inférieur ou égal à $n$)
    - l'auteur dit qu'on choisit $n$ points dans K (en choisissant $k \geq n$ points dans Q et ne retenant que les n qui sont dans K) puis qu'on somme la valeur de $\varphi$ sur ces $n$ points.
    Dans les deux cas, on renvoie la somme calculée que l'on multiplie par volume(Q)/n.

    Pour prendre un exemple, je calcule l'intégrale de $f(x,y) = x^2y$ sur le domaine $K = \{(x,y)\in\R^2\mid 0\leq x\leq 2, 0\leq y\leq x^2\}$. Je trouve 64/7 en faisant le calcul formellement.
    Avec la méthode de Monte-Carlo, je choisis le pavé $Q = [0,2]\times[0,4]$ qui contient K. Mon algo avec $10^5$ points donne à peu près 9.065, ce qui a l'air cohérent tandis que l'algo de l'auteur donne à peu près 27.5. En fait, j'ai l'impression que l'algo de l'auteur donne un résultat qui tient compte du pavé Q qui contient le domaine d'intégration. Son algo m'irait si on renvoie la somme multiplié par volume(Q)/k où $k$ est le nombre de points qu'il a dû tirer dans $Q$ pour en avoir $n$ dans $K$.
  • J'ai répondu avant de lire le message de rebellin : je ne sais pas de quel algorithme tu parles, le mien ou celui du livre ? J'ai l'impression que c'est plutôt celui du livre, mais est ce qu'il ne faut pas diviser à la fin par le nombre de points tirés (probablement supérieur à $n$) et pas par $n$ ?
  • Le compteur est "dans la boucle de ceux qui sont dans K".
    Ainsi, on a tiré dans l'algorithme du livre, $n$ points dans K, à la fin.
    Mais on en a probablement tiré plus de $n$ points dans Q, et ça on ne le compte pas.

    Edit : et non, il ne faut pas diviser par les nombre de points tirés car certains n'étaient pas dans K.
    En gros ceux qui tombent dans Q\K, on ne les compte (évidemment) pas, ils sont hors jeu.
    D'ailleurs, la fonction n'est a priori pas forcément définie sur Q tout entier.

    Edit2 : En fait, tirer aléatoirement dans un pavé, c'est facile, les logiciels de programmation ont une fonction implémentée, même parfois uniquement "le nombre entre 0 et 1". Mais si on veut tirer au hasard un point dans une étoile par exemple, ce n'est pas facile, alors on choisit un rectangle pas trop grand et on teste si on est dans l'étoile ou pas. C'est juste "une astuce du programmeur" à mon sens.
    C'est comme si avec un dé on ne voulait obtenir que des 1 et des 2 : on peut s'arrager à faire du "pair/impair" ou alors jeter le dé et disqualifier tous les lancers qui donnent autre chose que 1 et 2.
  • Mais il y a quelque chose que je ne comprends pas : le pavé $Q$ dans lequel on inclut le domaine $K$ d'intégration ne change évidemment pas le résultat. J'ai programmé l'algorithme de l'auteur en Python sur ma fonction $f(x,y) = x^2y$ à intégrer sur $K = \{(x,y) \in R^2 \mid 0\leq x\leq 2, 0\leq y \leq x^2\}$ après avoir importé le module random :
    n = 10**5
    somme = 0
    compteur = 0
    
    while compteur < n:
        x = [random.uniform(pave[k][0], pave[k][1]) for k in range(len(pave))]
        if x[1] - x[0]**2 <= 0:
            somme += x[0]**2*x[1]
            compteur += 1
                
    #calcul du volume du pavé : 
    volume = 1
    for k in range(len(pave)):
        volume = volume*(pave[k][1] - pave[k][0])
            
    print(somme*volume/compteur)
    

    Si je marque pave = 0, 2], [0, 4 avant ce script, j'obtiens à peu près 27 ; si je marque pave = 0, 2], [0, 10 avant le script, j'obtiens (en plus de temps, ce qui est normal) à peu près 68 :-S
  • Je reprends l'edit2 de Domi : "C'est comme si avec un dé on ne voulait obtenir que des 1 et des 2 : on peut s'arranger à faire du "pair/impair" ou alors jeter le dé et disqualifier tous les lancers qui donnent autre chose que 1 et 2."

    Si j'utilise l'algo :
    - je tire un dé et je regarde s'il est pair
    - dans ce cas, j'incrémente un compteur et je regarde s'il s'agit d'un 6
    - je renvoie le nombre de 6 divisé par le compteur.
    J'obtiens la probabilité d'avoir un 6 sachant que j'ai obtenu un nombre pair.

    Alors que si j'utilise l'algo :
    - je tire un dé et je regarde s'il est pair
    - dans ce cas, je regarde s'il s'agit d'un 6
    - je renvoie le nombre de 6 divisé par le nombre de dé que j'ai tiré.
    J'obtiens la probabilité d'avoir un 6 (et d'avoir un nombre pair mais c'est un peu idiot ici).

    Il me semble que l'algorithme de l'auteur fait justement ce conditionnement (dans ce cas par l'événement "être dans K")
  • Je m'interroge sur ton test, il ne vérifie que l'inégalité $y-x^2 \leq 0$ sauf erreur... et donc ton "K" ne serait "pas borné" (pour le dire vite).
  • Je parlais bien de l'algorithme du livre. On prend plein de points jusqu'à en avoir eu $n$ dans le domaine de validité. (On a donc des tirages non exploités.) A chaque fois qu'on a un "bon" point, on fait le calcul. A la fin on a donc $n$ bons points et $n$ calculs. Il est alors normal de diviser par $n.$
  • Comme je choisis (x,y) dans le pavé et que j'ai mis $[0,2]$ comme première composante du pavé à chaque fois, il me semble qu'il n'y a pas de besoin d'autre test. Mais effectivement, c'est sûrement maladroit pour la lisibilité.
  • Un petit changement d'indentation et tout rentre dans l'ordre (ce n'est sans doute pas la meilleure façon d'écrire l'algorithme).
    import numpy as np
    
    pave=[[0,2],[0,4]]
    
    n = 10**5
    somme = 0
    compteur = 0
    
    while compteur < n:
        x = [np.random.uniform(pave[k][0], pave[k][1]) for k in range(len(pave))]
        if x[1] - x[0]**2 <= 0:
            somme += x[0]**2*x[1]
        compteur += 1
                
    #calcul du volume du pavé : 
    volume = 1
    for k in range(len(pave)):
        volume = volume*(pave[k][1] - pave[k][0])
            
    print(somme*volume/compteur)
    
  • Fichtre ! Les indentations sont donc des éléments de programmation et pas seulement de lisibilité pour le programmeur ?
  • En python, oui.
    La différence entre les deux est de savoir si l'incrémentation du compteur est conditionnée par le "if" ou pas. Ça se comprend assez bien visuellement.
  • Merci GaBuZoMeu, tu confirmes donc qu'il y a un souci avec l'algo du bouquin (l'incrémentation du compteur est bien dans le test d'appartenance à K) et on divise par le compteur et pas par le nombre de points fixés par l'utilisateur (égaux dans la version du livre)

    Je n'ai pas forcément cherché à écrire le mieux possible mon algo (et je ne suis pas sûr de faire mieux), mais je suis curieux maintenant ! Comment aurais-tu écrit l'algo ?
    Une question que je me suis posé en l'écrivant : si $n$ est le nombre de points demandés par l'utilisateur, est-ce qu'il vaut mieux :
    - tirer $n$ points dans le pavé, auquel cas on peut avoir un résultat qui n'a aucun sens si l'utilisateur a "mal borné" le domaine d'intégration
    - tirer $n$ points dans le domaine d'intégration, auquel cas le calcul peut être très long pour la même raison
  • Oui, il y a une erreur dans le bouquin.
    Ma remarque tenait juste au fait que dans l'algorithme modifié, le compteur est inutile.
    Tu as raison dans le fait que cette méthode donne de très mauvais résultatS si le domaine d'intégration est de taille petite par rapport au pavé qui le contient.
  • OK merci de tes réponses.
  • @GaBuZoMeu
    Merci pour cette information ! (indentations en Python)

    @Alban_
    Au sujet du domaine K que je disais "non borné" : en effet, je disais des bêtises, la condition $0\leq y$ était bien réalisée puisque ton pavé contenait cette condition.

    @tous les deux
    Je ne comprends pas l'erreur du coup.
    Le programme est donné "en français" (on dit pseudo-code je crois) sur le cliché posté.
    On voit même des traits de rappel tels des indentations, non ?
    Dites-moi tout.
  • L'erreur est dans le pseudo-code du bouquin : elle consiste à ne compter que les "bons coups".
  • Mince, justement je trouvais que c'était une bonne stratégie.
    Voilà ce que je comprends en lisant l'algorithme du bouquin : on souhaite tirer $n$ coups dans K.

    Pour tirer $n$ coups dans K, on tire des coups dans Q (pas de jeu de mots graveleux je vous prie), et on s'arrête lorsque l'on a $n$ coups dans K tout en ayant sommé les $n$ bons coups. On a pu tirer beaucoup plus de $n$ coups...mais on jette à la poubelle ces jets.

    Ce n'est pas ça qu'il est judicieux de faire ?
  • En faisant ce que tu dis, ce n'est sûrement pas $\dfrac{SV}{n}$ qui donne une estimation de l'intégrale, si $V$ est le volume du pavé.
    Une question à Alban_ : dans le bouquin, $V$ est bien le volume du pavé $Q$ et pas celui de $K$ ? Tu es sûr ?
  • (En effet, ta question sur ce qu'est $V$, je me l'étais demandé justement, c'était ma première interrogation ici.
    Je comprends maintenant ta remarque si $V_Q$ est grand par rapport à $V_K$)
  • Je confirme que V est bien le volume du pavé dans le livre, preuve à l'appui (c'est le passage du livre juste avant le passage cité dans mon tout premier message).83432
  • En effet, si ce V n'est pas le volume de K, la limite probabiliste n'est pas l'intégrale voulue.

    Remarque : on peut estimer le volume de K avec Monte-Carlo, est-ce le sens de l'expression "combiner les deux approches" ?
  • Ce n'est pas clair, Alban _. Je ne vois rien qui dit que $V$ n'est pas le volume de $K$ !
  • Effectivement, j'ai mal lu : comme il y a écrit $V=\prod_{}^{} (b_k-a_k)$ plus haut (mais en parlant du cas où le domaine d'intégration est simple), j'ai supposé que $V$ était le volume du pavé dans la suite, mais il n'y a aucune raison en fait : $V$ peut très bien être le volume du domaine d'intégration (évaluable avec la méthode du rejet) et dans ce cas, l'algo m'a l'air correct. Et effectivement, la phrase "combiner les deux approches" doit être pour ce principe. Désolé de ma mauvaise lecture !
Connectez-vous ou Inscrivez-vous pour répondre.