Utilisation de la régression linéaire simple pour les courbes exponentielles

Publié: 08-06-2019
Le code de ce post est écrit avec Python version 3.7.3 à l'aide du logiciel Spyder.

Dans le précédent post <Introduction à la régression linéaire simple>, j’avais introduit la régression linéaire simple en utilisant Python. Nous avons vu que la régression linéaire peut être appliquée à de nombreux problèmes linéaires.

Cependant, un avantage important de la régression linéaire est qu’elle peut également s’appliquer aux problèmes qui ne semblent pas linéaires au début. Dans ce post, nous allons cibler les problèmes exponentiels.

Graphes d'augmentation exponentielle

Les graphes en lignes droites représentent des augmentations constantes, mais les graphes à courbes exponentielles montrent que la croissance se produit à un rythme de plus en plus rapide.

Il y a beaucoup de croissance exponentielle dans la vie réelle:

  • Croissance exponentielle des bactéries
  • Ventes de téléphones intelligents
  • Croissance exponentielle de la dette
  • Libération d'énergie exponentielle
  • Croissance de la population humaine

Loi de Moore

La loi de Moore stipule que les transistors sur une puce doublent tous les deux ans environ. Doubler tous les deux ans indique que nous avons une courbe exponentielle.
La question est: qu'est-ce que cela a à voir avec la régression linéaire?

Le truc ici est que nous ne mesurerons pas les comptes de transistors directement, mais nous allons mesurer le logarithme naturel des comptes de transistors. Simulons ce problème en python. Importons d'abord les bibliothèques nécessaires.

            
                import numpy as np
                import matplotlib.pyplot as plt
                import math
                import random

                #08/06/2019
                #Version python  → 3.7.3
                #version numpy   → 1.16.2
                #version matplotlib  → 3.0.3
            
        

Le premier microprocesseur (Intel 4004) a été inventé en 1971. Il s’agissait d’une unité de calcul de 4 bits, cadencée à 740 kHz et intégrant 2300 transistors. Nous allons maintenant simuler la loi de Moore en générant des données représentant l'évolution du nombre de transistors sur 70 ans. Nous allons commencer par 2300 transistors et doubler ce nombre de deux tous les deux ans. Notez que les données générées ici ne représentent pas les données dans la réalité et ceci est juste à des fins de démonstration.

            
                #Générer nos données
                X=[]
                Y=[]

                #Nous commençons par 2300 transistors et
                #doublons ce nombre tous les deux ans

                start=2300
                for i in range(1,70,2):
                    X.append(i)
                    Y.append(start)
                    start *= 2
            
        

Nous allons transformer X et Y en tableaux numpy et imprimer le nombre de transistors pour la 5ème année

            
                X=np.array(X)
                Y=np.array(Y)

                #le troisième élément de X (indice = 2) représente la cinquième année.
                #Dans la boucle ci-dessus, nous avons commencé par un
                #et nous incrémentons de deux.
                #Les éléments dans X seront comme ceci [1,3,5,7, ..., 69].

                print(X[2])
                # → 5
                print(Y[2])
                # → 9200
            
        

Maintenant, tracé les données.

            
                plt.scatter(X,Y)
                plt.show()
            
        

On peut remarquer que les données de Y ont la forme d’une courbe exponentielle.

L'astuce ici est que nous ne voulons pas appliquer la régression linéaire à ces données, mais nous allons calculer le logarithme naturel de Y qui semble linéaire.

            
                Y=np.log(Y)

                plt.scatter(X,Y)
                plt.show()
            
        

Nous avons maintenant des données qui semblent linéaires. Nous pouvons appliquer ce que nous avons fait dans le post précédent <Introduction à la régression linéaire simple> et calculer a et b.

            
                denominator=X.dot(X) - X.mean() * X.sum()
                a=(X.dot(Y)-Y.mean()*X.sum())/denominator
                b=(Y.mean()* X.dot(X)-X.mean()*X.dot(Y))/denominator


                Yhat=a*X + b

                plt.scatter(X,Y)
                plt.plot(X,Yhat,'r')
                plt.show()
            
        

Nous avons maintenant une ligne droite qui ajuste parfaitement le logarithme des données.

Nous allons maintenant calculer le R-carré pour montrer à quel point notre ligne est bonne pour ajuster les données.

            
                d1=Y-Yhat
                d2=Y-Y.mean()
                r2=1-(d1.dot(d1)/d2.dot(d2))

                print("a:",a,"b:",b)
                print("R-carre est :",r2)
                # → R-carre est : 1.0
            
        

Nous avons une valeur de 1, ce qui signifie que nous avons une ligne parfaite. Notez que les données ici sont simulées et que dans les problèmes réels, vous n’obtiendrez pas la valeur 1, car les données contiennent du bruit.

Faisons maintenant notre prédiction. Rappelez-vous que nous avons 9200 transistors pour la cinquième année. Maintenant que nous avons a et b, nous allons calculer le nombre de transistors pour x = 5.

            
                pred=a*X[2]+b

                #Notez que nous devrions calculer l’exponentielle
                #de la prédiction pour obtenir le nombre de transistors.

                print(math.exp(pred))
                # → 9200.000
            
        

Nous pouvons voir que nous avons parfaitement obtenu le nombre de transistors.

Nous allons maintenant répéter le même exemple mais en ajoutant du bruit aux données.

            

                import numpy as np
                import matplotlib.pyplot as plt
                import math
                import random


                X=[]
                Y=[]

                start=2300
                for i in range(1,70,2):
                    X.append(i)
                    Y.append(start)
                    #Bruit ajouté ici
                    start *= (2 + 2*random.uniform(0, 1))

                X=np.array(X)
                Y=np.array(Y)

                print(X[2])
                # → 5
                print(Y[2])
                # → 19412.444
                #Notez que vous aurez un numéro différent du mien.

                #Tracer les données exponentielles
                plt.scatter(X,Y)
                plt.show()

                #Calcul du log des données
                Y=np.log(Y)

                #Tracer le log des données (il devrait être linéaire)
                plt.scatter(X,Y)
                plt.show()


                #Calculer a et b
                denominator=X.dot(X) - X.mean() * X.sum()
                a=(X.dot(Y)-Y.mean()*X.sum())/denominator
                b=(Y.mean()* X.dot(X)-X.mean()*X.dot(Y))/denominator


                Yhat=a*X + b

                #Tracer la ligne de meilleur ajustement
                plt.scatter(X,Y)
                plt.plot(X,Yhat,'r')
                plt.show()

                #Calculer le R-carré
                d1=Y-Yhat
                d2=Y-Y.mean()
                r2=1-(d1.dot(d1)/d2.dot(d2))

                print("a:",a,"b:",b)
                print("R-carre est :",r2)
                # → 0.99
                #Vous n'obtiendrez pas 1 maintenant

                #Faire la prédiction
                pred=a*X[2]+b
                print(math.exp(pred))
                # → 14362.320
                #Notez que vous aurez un numéro différent du mien.

                #Vous pouvez remarquer ici que lorsque nous avons
                #ajouté du bruit aux données, nous n’avions
                #pas le nombre exact de transistors.