Accueil Algorithme Machine Learning pour débutant : Régression linéaire avec une seule variable partie...

Machine Learning pour débutant : Régression linéaire avec une seule variable partie I

3305
0

Prérequis

Pour suivre et comprendre cet article dans les meilleurs conditions, il est recommandé de :

Introduction

Cet article est la première partie des deux articles dans lesquels on traite de la régression linéaire avec une variable. La régression linéaire fait partie de la catégorie des techniques d’apprentissage supervisé. Dans cet article, nous commencerons par parler du dataset (le comprendre et l’explorer) avant de représenter notre modèle pour ainsi terminer par la l’implémentation de la fonction d’erreur.

Comprendre le dataset

Nous allons réaliser un modèle qui permet de prédire le profit d’un food-truck à partir du nombre d’habitants de la ville où il sera stationné. Pour ce faire, nous disposons d’un dataset qui contient les profits de plusieurs food-truck stationnés dans plusieurs villes.

Le dataset a été téléchargé depuis Coursera. Il s’agit d’un fichier csv(food-truck_profits.txt) qui contient deux champs qui portent sur les profits de différents food truck dans des villes. Chaque ligne représente un food truck dans une ville.

Les deux champs sont :

  • Le premier champ représente le nombre d’habitant de la ville.
  • Le deuxième champ représente le profit (en dollars) d’un food truck sur cette ville.
Maintenant, allons recupérer ces deux champs et voir à quoi ils ressemblent.
import numpy as np
tab = np.genfromtxt('food-truck_profits.txt', delimiter=',')

# recuperation des nombres d'habitants des villes
X = tab[:,0];

# recuperation des profits des food truck respectivement sur ces villes
Y = tab[:,1];

dataset = np.ones((np.size(X),2))
dataset[:,0] = X
dataset[:,1] = Y

# on affiche les 10 premiers food truck
print(dataset[0:9,:])

Ce qui nous donne le résultat suivant :

[[ 6.1101 17.592 ]
 [ 5.5277  9.1302]
 [ 8.5186 13.662 ]
 [ 7.0032 11.854 ]
 [ 5.8598  6.8233]
 [ 8.3829 11.886 ]
 [ 7.4764  4.3483]
 [ 8.5781 12.    ]
 [ 6.4862  6.5987]]

On a recupéré le nombre d’habitants des villes (X) et le profit des food truck correspondant (Y) qu’on a mis sur un tableau à deux colonnes qui se nomme « dataset ».

On nomme m le nombre d’exemples (de food trucks) dans le dataset.On obtient ainsi l’ensemble \(E_m = \{(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),…,(x^{(m)},y^{(m)})\} \)

De ce fait \( (x^{(i)}, y^{(i)}) \) représente la i-ème ligne de la table « dataset » :  le nombre d’habitant \( x^{(i)} \) de la i-ème ville et le profits \( y^{(i)} \) de la i-ème food truck dans cette ville.

Si on visualise le dataset, on aura :

import matplotlib.pyplot as plt

plt.plot(dataset[:,0], dataset[:,1], 'rx')
plt.show()
Resultat du code ci-dessus (crédit : Mar Mbengue – Tous droits réservés)

Représenter le modèle

Représentation du modèle

Nous avons maintenant notre dataset qui représente les profits des food truck en sachant le nombre d’habitants des villes qui les accueillent. Pour realiser le modele de régression linéaire, il nous faut trouver (apprendre) une fonction \( h_\Theta : X \rightarrow Y \)

Cette fonction est appelé \( h_\Theta \) par convention (h pour se reférer au mot « hypothese » et \( \Theta \) pour faire référence aux paramètres de la fonction).

Puisqu’il s’agit d’une regression linéaire, la fonction \( h_\Theta \) sera linéaire et elle sera représentée par :

\( h_\Theta (x) = \Theta_0 + \Theta_1 x \)

Pour que notre modèle soit pertinent, la condition suivante doit être vraie :

quelque soit \( (x^{(i)}, y^{(i)}) \in E_m \) , on a : \( h_\Theta (x^{(i)}) \approx y^{(i)} \).

Pour que la condition ci-dessus soit vraie, il nous faut trouver des valeurs adéquates pour les paramètres (\( \Theta_0 \) et \( \Theta_1 \)) de la fonction \( h_\Theta \).

Maintenant, la question qu’on peut se poser est « comment trouver les bonnes valeurs pour les paramètres \( \Theta_0 \) et \( \Theta_1 \) ? ». Nous allons y répondre dans la deuxième partie de cette article.

Implémentation vectorielle du modèle

Pour rendre notre fonction \( h_\Theta \). plus performante en temps de calcule, on peut le vectoriser. Selon wikipedia, « La vectorisation est le processus de conversion d’un programme informatique à partir d’une implémentation scalaire, qui traite une seule paire d’opérandes à la fois, à une implémentation vectorielle qui traite une opération sur plusieurs paires d’opérandes à la fois. »

Pour implémenter véctoriellement notre modèle :

  • On transforme d’abord les parametres \( \Theta_0 \) et \( \Theta_1 \) en vecteur \( \Theta = \begin{pmatrix}{\Theta_0}\\ {\Theta_1}\end{pmatrix} \).
  • Ensuite, on transforme x en vecteur \( x =\begin{pmatrix}{x_0}\\ {x_1}\end{pmatrix} \) avec \( x_0=1 \) et \( x_1= nombre \hspace{0.2cm} d’habitants \).

     

La fonction \( h_\Theta \) devient alors :

 \( h_\Theta (x) = \Theta^T x \)

\(\Theta^T \) est le vecteur transposé de \( \Theta \)

Dans le reste de l’article et de la série, on implémentera toujours les modèles de manière vectorielle.

Si on représente vectoriellement tout le dataset, on aura :
Pour tous les \( x^{(i)} \in X \) on aura \( x^{(i)} =\begin{pmatrix}{x^{(i)}_0}\\{x^{(i)}_1}\end{pmatrix} \) avec \( x^{(i)}_0=1 \) et \( x^{(i)}_1=x_1 \)

L’ensemble X des nombres d’habitants des villes va devenir : \( X = \begin{pmatrix} 1 & x^{(1)}_1\\ 1 & x^{(2)}_1\\  .&. \\  .&. \\  .&. \\ 1 & x^{(n)}_1\end{pmatrix} \)

Quand on fait une régréssion linéaire; on ajoute toujours (par convention) au debut du dataset une colonne dont toutes les valeurs sont égales à 1.

on modifie la varable dataset afin d’ajouter une colonne (avec des 1) devant. ce qui va nous donner :

datasetTemp = dataset

dataset = np.ones((np.size(X),3))
dataset[:,1] = datasetTemp[:,0]
dataset[:,2] = datasetTemp[:,1]

X = dataset[:,0:2]
Y = dataset[:,2]

print(X.shape)
print(X)
print(Y.shape)
print(Y)

Le résultat va ressembler à :

(97, 2)
[[ 1.      6.1101]
 [ 1.      5.5277]
 [ 1.      8.5186]
 [ 1.      7.0032]
 [ 1.      5.8598]
 [ 1.      8.3829]
 [ 1.      7.4764]
 [ 1.      8.5781]
         .
         .
         .         ]
(97,)
[17.592    9.1302  13.662   11.854    6.8233  11.886    4.3483  12.
  6.5987   3.8166   3.2522  15.505    3.1551   7.2258   0.71618  3.5129
  5.3048   0.56077  3.6518   5.3893   3.1386  21.767    4.263    . . .]

On peut ainsi implémenter la fonction python qui correspond à \(h_\Theta \). Cette fonction prend en paramètres deux vecteurs :

  • x (ou une matrice mx2).
  • \(\Theta \) correspondant aux paramètres de notre modèle.

On définit la fonction python qui représente notre modèle de la manière suivante :

def h_theta(X, theta):
    ret = np.dot(theta, X.T)
    return ret
allons voir ce que donne la fonction h_theta sur des exemples :
# pour theta = (0.5, 1)
theta = np.array([0.5, 1])

x = np.array([1, 6.1101])
print("pour theta = (0.5, 1), et x = (1, 6.1101) h_theta(x) vaut : ", h_theta(x,theta))

print("pour theta = (0.5, 1), et X est le dataset,  h_theta(x) vaut : ", h_theta(X,theta))

résultat :

pour theta = (0.5, 1), et x = (1, 6.1101) h_theta(x) vaut :  6.6101
pour theta = (0.5, 1), et X est le dataset,  h_theta(x) vaut :  [ 6.6101  6.0277  9.0186  7.5032  6.3598  8.8829  7.9764  9.0781  6.9862
  5.5546  6.2107 14.664   6.234   8.9084  6.1407  5.8794  6.8654  5.6301
  6.9296  7.5708  6.6891 20.77    5.9901  6.8261  6.0649 19.445  13.328
 11.457  13.676  22.703   5.7524  7.0894  9.7482  6.3918  8.7111  8.4334
  8.5959  6.1063 13.336   6.8534  5.9069  7.3825 12.208   6.2737  8.3247
  7.5931  5.5702  6.3014 12.2     6.0416  8.0402  5.8077  7.9239  8.1031
  6.8328  6.8589  6.7742  6.1397  9.8102  9.9536  9.3254  5.6793 21.779
 15.408  19.459   7.7182  8.7951 10.736   5.9994 20.841  10.636   7.8345
  6.5062  7.7259  5.5269  7.0479  8.0386  5.5365 10.774   5.6077  6.2292
  5.6884  6.8557 10.2687  7.0159  9.0172  9.6802  6.502   6.0204  5.5594
  6.2077  8.1366  6.3707  5.8054  8.7934 13.894   5.9369]

On voit que pour le premier exemple (food truck), la nombre d’habitants de la ville est 6.1101 et le profit est 17.592.

Quand on se sert de notre modèle h_theta pour estimer le profit de ce food truck on trouve 6.6101, ce qui veut dire que notre modèle n’est pas encore au point.

Pour qu’il soit au point il faudra l’entrainer avec notre dataset.

Fonction d’erreur

On a vu que notre modèle fait des erreurs dans l’estimation des profits des food truck. En prenant l’exemple du premier food truck de notre dataset qui est 17.592, notre modèle l’estime à 6.1101.

On peut definir l’erreur de notre modèle sur le premier food truck par : \( (h_\Theta (x^{(1)}) – y^{(1)})^2 = (6.1101 – 17.592)^2 =131.83 \)

Ce qui représente une grosse erreur car le profit estimé par notre modèle est trés loin du profit réel.

On peut ainsi définir la fonction d’erreur comme la moyene des erreurs de notre modèle sur le dataset E_m, Ce qui nous donne :

 

\( J(\Theta ) = \frac{1}{2m}\sum_{i=1}^{m}(h_\Theta (x^{(i)}) – y^{(i)})^2 \)

 

Cette fonction est aussi appelé erreur quadratique.

Par convension et pour faciliter le calcul du gradiant, on multiplie cette moyène par 1/2.

Lors de l’entrainement du modèle, c’est cette fonction \( J(\Theta )\) qu’on va essayé de minimiser. Ce qui revient à trouver un vecteur de paramèttre \( \Theta = \begin{pmatrix}{\Theta_0}\\ {\Theta_1}\end{pmatrix} \) pour lequel \( J(\Theta )\) serait le plus proche de 0.

On peut ainsi implémenter la fonction python qui correspond à la fonction d’erreur \( J(\Theta )\).

Cette fonction prend en parametre :

  • x (vecteur ou matrice mx2).
  • Un vecteur theta.
  • Un vecteur Y (ou un scalaire \(y_i\)).

et retourne la valeur de \( J(\Theta )\).

def computeErrorFunction(x, y, theta):
    h_theta_de_x = h_theta(x,theta)
    vec_temp =  (h_theta_de_x - y)**2
    ret = np.sum(vec_temp)/(2*(y.size))
    return ret

on peut calculer l’erreur :

theta = np.array([0.5, 1])
print("pour theta = (0.5, 1), l'erreur de notre modèle sur notre dataset est :", computeErrorFunction(X, Y, theta))

theta = np.array([12, 30])
print("pour theta = (500, 1000), l'erreur de notre modèle sur notre dataset est :", computeErrorFunction(X, Y, theta))

résultat :

pour theta = (0.5, 1), l'erreur de notre modèle sur notre dataset est : 8.731188017156702
pour theta = (500, 1000), l'erreur de notre modèle sur notre dataset est : 37643.43989082003

On voit que l’erreur est plus petite avec theta = (0.5, 1) qu’avec theta = (500, 1000), donc notre modèle est plus performant avec le parametre theta = (0.5, 1).

Conclusion

Aprés avoir définit la fonction d’erreurs, exploré le dataset et donner une représentation de notre modèle, on peut dire que notre modèle n’est pas encore performant car n’ayant pas les bons paramètres. Pour retrouver les bons paramètres, il faudra entrainer le modèle. D’ou l’objet de la deuxième partie de cet article qui va porter sur l’entrainement d’un modèle.

Crédit de l’image de couverture : Chire – CC BY-SA 3.0