Partage
  • Partager sur Facebook
  • Partager sur Twitter

Plotter un fit d'une fonction prédéfinie

Fit de courbe

Sujet résolu
    21 juin 2021 à 13:52:23

    Bonjour,

    Je vous écris ce message afin de vous demander de l'aide concernant un fit d'une fonction prédéfinie que je dois effectuer sur un de mes codes.

    Ainsi, ayant les données expérimentales, je ne peut qu'avoir accès qu'aux courbes contenus les mesures expérimentales.

    Etant débutant sur Python, je vous mets ci-dessous les 2 expressions des fonctions.

    Voici ci-dessous les deux fonctions prédéfinies :

    Pour finir, pourriez-vous me dire les étapes que je dois entreprendre afin d'effectuer ces deux fits sachant que pour l'expression contenant les trois termes avec des exponentielles, il faut que je puisse tracer la courbe en échelle semi-log, s'il vous plaît.

    Répondez-moi quand vous aurez du temps libre.

    Je vous en serai très reconnaissant.

    Merci de votre compréhension.

    • Partager sur Facebook
    • Partager sur Twitter
      22 juin 2021 à 3:10:45

      Tu ne t'en doutes pas, mais depuis le début, tu te fais aider par un aveugle (vois mon profil)
      Tu es capable d'écrire en Python les expressions correspondant à tes fonctions.
      a puissance b s'écrit a**b et exp(n) est la base des log Népériens exposant n.
      2**3 donne 8 et exp(1) donne 2.718281828459045
      Qu'appelles-tu un "fit"? Est-ce une forme de régression?
      Ou bien, est-ce ce qu'on appelle une moyenne flottante?
      Si une de tes coordonnées contient des exponentielles et si les valeurs sont grandes, calcules le log pour cette coordonnée seulement.
      exemple:
      from math import log
      X = [log(x) for x in X]
      J'ai déjà réussi des choses avec matplotlib. Je ne sais pas si c'est ce que tu voulais utiliser.
      • Partager sur Facebook
      • Partager sur Twitter

      Le Tout est souvent plus grand que la somme de ses parties.

        22 juin 2021 à 17:40:21

        Bonsoir,

        Tout d'abord, merci pour tout l'aide que vous m'avez apporté même dans les autres sujets que j'ai posté sur le forum.

        Ainsi, il s'agit bien ici d'une régression.

        Pour finir, il faut que j'essaie de voir cela calmement.

        N.B : Cela me fais plaisir d'échanger avec tous les internautes, d'avoir leurs idées afin que je puisse résoudre lorsque je n'y arrive pas (après avoir passé du temps là-dessus), les problèmes sur mes code.

        Répondez-moi quand vous aurez du temps libre.

        Je vous en serai très reconnaissant.

        Merci de votre compréhension.

        • Partager sur Facebook
        • Partager sur Twitter
          24 juin 2021 à 7:11:54

          Bonjour,
          À la lumière de tes autres posts, il s'agirait d'une régression linéaire entre une variable et le log d'une autre variable.
          S'il s'agit seulement de tracer les points en semi-log, un autre intervenant t'a montré comment faire.
          Mais si tu veux calculer la droite de régression, tu n'auras pas le choix que de calculer ces log pour toutes les valeurs (de Y je suppose).
          Je t'ai montré comment ci-haut.
          Voici un texte qui devrait t'aider, je l'espère
          http://www.bibmath.net/dico/index.php?action=affiche&quoi=./r/reglin.html

          • Partager sur Facebook
          • Partager sur Twitter

          Le Tout est souvent plus grand que la somme de ses parties.

            25 juin 2021 à 7:12:29

            Dans le lien suivant:
            https://calculis.net/droite-regression-lineaire
            On a ce qui suit:
            b = [n(∑xiyi) − (∑xi)(∑yi) ] / [ n(∑xi2) − (∑xi)2 ] et a = y − bx
            où x et y sont les moyennes respectives des xi et yi. L'équation de la droite de régression est obtenue par la méthode des moindres carrés.
            -
            Voici quelques astuces:
            Pour avoir la moyenne, il faut le nombre d'éléments:
            n = len(x)   # je suppose que c'est la même longueur pour les deux listes.
            La moyenne est la somme divisée par le nombre:
            xm = sum(x)/n
            ym = sum(y1)/n
            La somme des carrés serait:
            xs = sum(i**2 for i in x)
            ys = sum(i**2 for i in y1)
            Et que fait-on avec une expression ayant les deux variables? Ça peut ressembler à ceci:
            bb =[i**2 + j**2 for i, j in zip(x, y1)]
            C'est une liste, pas un simple élément.

            • Partager sur Facebook
            • Partager sur Twitter

            Le Tout est souvent plus grand que la somme de ses parties.

              25 juin 2021 à 10:06:06

              Salut,

              je doute qu'il s'agisse d'une régression linéaire. J'ai plutôt l'impression qu'on cherche à déterminer les paramètres dans les différentes fonctions. Pour cela, tu pourras utiliser une approche par Moindres Carrés (c'est ce qui est fait avec une régression linéaire, sauf que la fonction utilisée pour le "fit" est une droite). La bonne nouvelle, c'est qu'il y a une fonction pour ça dans la librairie scipy : ici et il y a même un exemple de "fit" à la fin de la page. Pour comprendre rapidement ce qui se passe, en prenant l'exemple de la seconde fonction : supposons que tu as une collection de mesures qu'on va appeler y_i à un ensemble de points de mesure x_i où i est un indice, on cherche A1, A2, A3, B qui permettent d'approximer au mieux tes mesures. Une manière de faire ça est de les chercher comme minimum de la fonction

              J(A1,A2,A3,B) = 1/2 * somme_i (y_i - f(x_i,A1,A2,A3,B))^2

              où f est bien la fonction dont tu cherches les paramètres. La fonction que je t'ai envoyé permet de faire ça en boîte noire.

              • Partager sur Facebook
              • Partager sur Twitter

              Avez-vous entendu parler de Julia ? Laissez-vous tenter ...

                28 juillet 2021 à 12:42:38

                Bonjour,

                Je vous écris ce message afin de vous demander de l'aide pour le fit de la courbe de saturation donné par P (voir expression mentionnée précédemment).

                Ainsi, j'ai utilisé ici la fonction scipy.optimize.least_squares.

                Voici ci-dessous mon code :

                ############################################################################################################################
                #Courbe de saturation - fit
                ############################################################################################################################
                import matplotlib.pyplot as plt
                from scipy.optimize import curve_fit
                
                
                x = np.load('Sin_Psat4.npy')
                yexp = np.load('Sout_Psat4.npy')
                
                
                def func(x, xsat, a, b):
                    return a * (1-np.exp(-x/xsat)) + b*x
                
                
                y = func(x, 2.5, 1.3, 0.5)
                plt.plot(x, yexp, 'b:', label='Experimental')
                plt.plot(x, y, 'r-', label='Theory')
                
                popt, pcov = curve_fit(func, x, y)
                print(popt)
                
                
                plt.plot(x, func(x, *popt), 'g--', label='Fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt))
                plt.xlabel('Power')
                plt.ylabel('Intensity')
                plt.legend()
                plt.show()plt.xlabel('x')
                plt.ylabel('y')
                plt.legend()
                plt.show()

                Ainsi, il y un problème dans mes deux lignes de code : y = func(x, 2.5, 1.3, 0.5) et plt.plot(x, func(x, *popt), 'g--', label='Fit: a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt)) car j'obtiens 2 courbes constantes.

                Voici ci-dessous le résultat attendu :

                Pour finir, pourriez-vous m'éclaircir sur les étapes que je dois entreprendre afin de résoudre ce problème, s'il vous plaît.


                N.B : Voici ci-contre le lien de mes données : https://we.tl/t-4gjWGTSWOw (il expire dans une semaine).



                Répondez-moi quand vous aurez du temps libre.

                Je vous en serai très reconnaissant.


                Merci de votre compréhension.

                • Partager sur Facebook
                • Partager sur Twitter
                  28 juillet 2021 à 14:13:27

                  Salut,

                  de ce que j'en vois, ce que tu dis être constant n'est pas du tout constant (il suffit d'afficher les valeurs pour s'en rendre compte), et le curve_fit fonctionne très bien, c'est juste que tu le calcul par rapport à 'func' à qui tu as passé des valeurs de paramètre absurdes par rapport à tes données expérimentales. Il faudrait passer en argument 'yexp' au lieu de 'y' à curve_fit.

                  Edit: J'ai réalisé que tu risquais d'avoir quelques surprises avec mes modifications, en particulier un 'fit' qui ressemble à une droite. Il y a une excellente raison à cela et elle est inhérente à la méthode des moindres carrés non-linéaires qui fait que plusieurs ensembles de paramètres sont possibles (je renvoie à la page wiki pour des explications/exemples). Au niveau de ce que j'ai remarqué, je me retrouve avec le paramètre 'xsat' négatif ce qui est aberrant puisqu'on s'attend à une exponentielle qui tend vers 0. Dans la documentation de curve_fit, on voit qu'il y a un paramètre 'bounds' qui permet d'indiquer dans quel intervalle on souhaite rechercher la solution. Il faudra donc imposer \([0,\infty[\) au moins pour 'xsat'. A toi de voir si ça suffit ou pas.

                  -
                  Edité par Nozio 28 juillet 2021 à 16:56:02

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Avez-vous entendu parler de Julia ? Laissez-vous tenter ...

                    28 juillet 2021 à 17:10:24

                    Bonsoir,

                    Merci pour votre aide. Je vous mets néanmoins mon nouveau code et la courbe obtenue afin d'avoir une vérification de votre part.

                    Voici ci-dessous mon nouveau code :

                    ############################################################################################################################
                    #Courbe de saturation - fit
                    ############################################################################################################################
                    #Importation de données d'un fichier NPY
                    
                    #Importation du module numpy afin de lire le contenu du fichier csv et simplification en np
                    import numpy as np
                    
                    #Importation du module matplotlib.pyplot pour construire le graphique et simplification en plt
                    import matplotlib.pyplot as plt
                    
                    #Importation du module curve_fit 
                    #Utilisation de la méthoe des moindres carrés non linéaires pour ajuster une fonction, f, aux données
                    from scipy.optimize import curve_fit
                    
                    #Lecture des abscisses/ordonnées x/yexp du fichier npy
                    #Les données se retrouveront dans une liste ou autre objet
                    x = np.load('Sin_Psat4.npy')
                    yexp = np.load('Sout_Psat4.npy')
                    
                    
                    def func(x, a, b, c):
                        return a*(1-np.exp(-x/b))+c*(x/b)
                    
                    #popt : liste (valeurs optimales pour les paramètres)
                    #pcov : tableau de deux lignes (covariance estimée de popt)
                    popt, pcov = curve_fit(func, x, yexp)
                    print(popt)
                    
                    
                    plt.gca().xaxis.set_ticklabels([0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1]) # Redéfini les ticklabels de l'axe x
                    plt.xlabel('Power (W.$\mu m^{-2}$)') # Affiche la légende sur l'axe des abscisses
                    plt.ylabel('I/Isat') # Affiche la légende sur l'axe des ordonnées
                    plt.plot(x, yexp, 'b o', label='Experimental') # Trace des points en bleu
                    plt.plot(x, func(x, *popt), 'r-', label='Fit : a=%5.3f, b=%5.3f, c=%5.3f' % tuple(popt)) # Trace une liaison entre des points en rouge
                    plt.legend() # Affiche les légendes des courbes
                    plt.show() # Montre le graphique à l'écran

                    Ainsi, j'obtiens la liste suivante pour popt :

                    [4.42243816e-01 1.85154576e-05 1.28531735e-01] correspondant à a, b et c, respectivement (si je ne me trompe).

                    Voici ci-dessous la courbe obtenue :

                                                                                 

                    Pour finir, pourriez-vous me faire des retours, s'il vous plaît.


                    Répondez-moi quand vous aurez du temps libre.

                    Je vous en serai très reconnaissant.


                    Merci de votre compréhension.

                    -
                    Edité par MilinoKEROWGODAGE 28 juillet 2021 à 17:12:13

                    • Partager sur Facebook
                    • Partager sur Twitter
                      29 juillet 2021 à 10:09:38

                      Ca m'a l'air tout à fait correct.

                      Cela dit, garde à l'esprit ce que je t'ai dit dans mon post précédent sur l'aspect "moindres carrés non-linéaires" et la nécessité, dans certains cas, de mieux cadrer les intervalles dans lesquels tu cherches tes paramètres. Quand j'ai fait un essai chez moi, je ne trouvais pas du tout la même régression qu'avec ton code. On n'a pas ce genre de blague avec les moindres carrés linéaires. Si je garde ta formule précédente

                      \(f(x) = a\cdot(1-e^{-x/b}) + c\cdot x\)

                      qui n'est pas très éloignée de la première, j'obtiens l'image ci-dessous si je ne rajoute pas les bornes

                      Si je mets les bornes, pas de soucis.

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Avez-vous entendu parler de Julia ? Laissez-vous tenter ...

                        29 juillet 2021 à 12:44:55

                        Bonsoir,

                        Merci pour votre aide. Le problème a été résolu.

                        -
                        Edité par MilinoKEROWGODAGE 29 juillet 2021 à 17:13:50

                        • Partager sur Facebook
                        • Partager sur Twitter

                        Plotter un fit d'une fonction prédéfinie

                        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                        • Editeur
                        • Markdown