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.x^2+b.x+c $
Les équations matricielles précédentes sont toujours valables :
$$ \boxed{ F = X.\Theta } $$
$$ \boxed{ J(\Theta) =\frac{1}{2.m}\sum_{i=0}^{m-1}\left(X \Theta-Y\right)^2 } $$$$ \boxed{ \frac{\partial J(\Theta) }{\partial \Theta} = \frac{1}{m}.\mathrm{X}^T.(X.\Theta-Y) } $$$$ \boxed{ \Theta = \Theta - \alpha.\frac{\partial J(\Theta) }{\partial \Theta} } $$Avec :
$$X = \begin{bmatrix} x^{2 (1)} & x^{(1)} & 1 \\x^{2 (2)} & x^{(2)} & 1 \\ . & . & . \\ x^{2 (m)} & x^{(m)} & 1 \end{bmatrix}$$$$\theta = \begin{bmatrix} a\\b\\c \end{bmatrix}$$# 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
...
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]]
#-----------------------------------------------------------------
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]]
plt.figure()
plt.plot(J_hist)
plt.xlabel("n_iterations")
plt.ylabel("J")
plt.title("Evolution de J")
plt.grid(True)
plt.show()