Régression linéaire Polynomiale

Régression linéaire Polynomiale

Nous cherchons toujours l’équation d’un modèle à une variable ( n=1 ).
Nous disposons de m échantillons.
Etant donné la dispersion des points d’échantillons, l’utilisation d’une droite pour représenter ce modèle n’est pas satisfaisante.
Nous allons utiliser un modèle polynomial de la forme f(x)=a.x2+b.x+c f(x)=a.x^2+b.x+c
Les équations matricielles précédentes sont toujours valables :

F=X.Θ \boxed{ F = X.\Theta }

J(Θ)=12.mi=0m1(XΘY)2 \boxed{ J(\Theta) =\frac{1}{2.m}\sum_{i=0}^{m-1}\left(X \Theta-Y\right)^2 } J(Θ)Θ=1m.XT.(X.ΘY) \boxed{ \frac{\partial J(\Theta) }{\partial \Theta} = \frac{1}{m}.\mathrm{X}^T.(X.\Theta-Y) } Θ=Θα.J(Θ)Θ \boxed{ \Theta = \Theta - \alpha.\frac{\partial J(\Theta) }{\partial \Theta} }

Avec :

X=[x2(1)x(1)1x2(2)x(2)1...x2(m)x(m)1]X = \begin{bmatrix} x^{2 (1)} & x^{(1)} & 1 \\x^{2 (2)} & x^{(2)} & 1 \\ . & . & . \\ x^{2 (m)} & x^{(m)} & 1 \end{bmatrix}θ=[abc]\theta = \begin{bmatrix} a\\b\\c \end{bmatrix}

Génération du Dataset

# Nombre de données 
m = 50

import numpy as np
from sklearn.datasets import make_regression
%matplotlib
import matplotlib.pyplot as plt
import random

# la fonction make_regression de sklearn permet de fournir un jeu de valeurs aléatoires 
x, y = make_regression(n_samples = m, n_features = 1, noise = 50)

print('x.shape = ', x.shape)
print('y.shape = ', y.shape)

# Reshape et tri des données
y=y.reshape(y.shape[0],1)

x = np.sort(x, axis=0)
y = np.sort(y, axis=0)

rd = random.randint(-50,50)
y=y-rd # Ajout d'une ordonnée à l'origine non nulle
y = y + abs(y/2) # dataset non-linéaire

plt.scatter(x,y)

for i in range(0,len(x),1):
    print(f'point_{i} :  {x[i][0]} {y[i][0]}')
x.shape =  (50, 1)
y.shape =  (50,)
point_0 :  -2.220435270316647 -105.09025457906677
point_1 :  -1.4034747831939485 -94.87939123662954
point_2 :  -1.2978345629304653 -71.342578784267
point_3 :  -1.227396573720367 -58.83669753100486
point_4 :  -1.1446418088253871 -55.03571336580174
point_5 :  -1.0296799147151325 -54.979404448115794
...

png


Initialisation du Modèle

X = np.hstack((x, np.ones(x.shape)))
X = np.hstack((x**2, X)) 
print(X.shape)
print('X=\n',X[:5])
THETA = np.random.randn(3, 1)
print('THETA =\n', THETA)
(50, 3)
X=
 [[ 4.93033279 -2.22043527  1.        ]
 [ 1.96974147 -1.40347478  1.        ]
 [ 1.68437455 -1.29783456  1.        ]
 [ 1.50650235 -1.22739657  1.        ]
 [ 1.31020487 -1.14464181  1.        ]]
THETA =
 [[-0.69716599]
 [ 0.26633098]
 [ 0.61224388]]

Algorithme de descente du gradient

#-----------------------------------------------------------------
def model( X, theta ):
    return X.dot(theta)
#-----------------------------------------------------------------
# Fonction coût
def J(X, y, theta):
    m=len(y)
    return 1/(2*m) * np.sum((model(X,theta) - y)**2)
#-----------------------------------------------------------------
# Calcul du Gradient
def grad(X,y ,theta):
    m = len(y)
    return (1/m) * X.T.dot( model(X, theta) - y)
#-----------------------------------------------------------------
def gradient_descent(X, y, theta, alpha, n_iterations):
    
    J_history = np.zeros(n_iterations) 
    
    for i in range(0, n_iterations):
        theta = theta - alpha * grad(X, y, theta) 
        J_history[i] = J(X, y, theta)
        
    return theta, J_history
#-----------------------------------------------------------------
#-----------------------------------------------------------------
n_iterations = 1000
alpha = 0.01 # learning rate

THETA_final, J_hist = gradient_descent(X, y, THETA, alpha, n_iterations)

print('THETA_final =\n',THETA_final)

plt.figure(figsize=(10, 6))
plt.scatter(x, y, label="Nuage de points", color="blue", alpha=0.6)
plt.plot(x,model(X,THETA_final), label="Courbe de tendance $y = ax^2 + bx + b$", color="red", linewidth=2)
# Ajout des barres entre les points réels et la courbe de tendance
for i in range(len(x)):
    plt.plot([x[i][0], x[i][0]], [y[i][0], model(X,THETA_final)[i][0]], color="gray", linestyle="--", linewidth=0.8)
plt.xlabel("X")
plt.ylabel("Y")
plt.title("Modèle déterminé par l'algorithme de la descente du gradient")
plt.legend()
plt.grid(True)
plt.show()
THETA_final =
 [[24.06231677]
 [89.50071808]
 [ 6.42995304]]

png

plt.figure()
plt.plot(J_hist)
plt.xlabel("n_iterations")
plt.ylabel("J")
plt.title("Evolution de J")
plt.grid(True)
plt.show()

png