vendredi 18 décembre 2020

Régression linéaire avec Pytorch (deep learning)

 Après  avoir exposé différentes manières de mettre en œuvre des ajustements par régressions linéaires en Python, je terminerai par le framework de l'apprentissage automatique ou profond Python. Pytorch est soutenu par facebook. Son approche est différente que celle de Keras/Tensorflow , elle se veut plus programmatique et moins 'boite noire'.

Comme dans les autres billets, je vais commencer par préparer Jupyter pour Pytorch.

Les opérations sont les mêmes que pour tensorflow.

  • Création d'un environnement virtuel Python (voir billet )
  •  Ajout d'un noyau à Jupyter

Installation de Pytoch 

Il suffit de sélectionner  les bonnes options sur la grille et en retour , il vous générera la ligne de commande pour PIP



Apres l'installation il suffira d'ajouter un noyau Pytorch à Jupyter (voir billet).

Sur mon PC cela donne: 



Premier essai de résolution de regression linéaire avec Pytorch

En reprenant le même jeu de donnée que dans les billets précédents:

import torch
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from torch.autograd import Variable
class linearRegression(torch.nn.Module):
    def __init__(self, inputSize, outputSize):
        super(linearRegression, self).__init__()
        self.linear = torch.nn.Linear(inputSize, outputSize)

    def forward(self, x):
        out = self.linear(x)
        return out
On importe les modules de base.
Et on déclare une classe qui doit fournir l'initialisation d'une classe de regression linéaire et comment propager le modèle.

Après initialisation des variables (nombre de tenseur) 
inputDim = 1        # takes variable 'x' 
outputDim = 1       # takes variable 'y'
learningRate = 0.01 
epochs = 150

model = linearRegression(inputDim, outputDim)
criterion = torch.nn.MSELoss() 
optimizer = torch.optim.SGD(model.parameters(), lr=learningRate)
Il faut définir comment le modèle va évaluer l'ecart (loss function)  et comment arriver à un optimum.

On revient ensuite à une recherche de solution conventionnelle dans une boucle:


history = []

for epoch in range(epochs):
    # Converting inputs and labels to Variable
    inputs = Variable(torch.from_numpy(X_train))
    labels = Variable(torch.from_numpy(y_train))
    # Clear gradient buffers because we don't want any gradient from previous epoch to carry forward, dont want to cummulate gradients
    optimizer.zero_grad()

    # get output from the model, given the inputs
    outputs = model(inputs)

    # get loss for the predicted output
    loss = criterion(outputs, labels)
   # print(loss.item())
    history.append(loss.item())
    # get gradients w.r.t to parameters
    loss.backward()

    # update parameters
    optimizer.step()
   
   # print('epoch {}, loss {}'.format(epoch, loss.item()))
[w, b] = model.parameters()
print(w)
print(b)
print('intercept :' ,0 - model.linear.bias.data.numpy()[0])
print('slope :' , model.linear.weight.data.numpy()[0][0])

Il est possible de visualiser l'évolution de la fonction de perte : 

Avec un résultat final semblable à nos autres méthodes : 


Il est possible d'obtenir des évaluations: 

ww = -model.linear.bias.data.numpy()[0]
with torch.no_grad(): # we don't need gradients in the testing phase
    v =  torch.tensor([3.5])
    w = torch.tensor([7.0])
    orig = torch.tensor([ww ])
    test1 = model(v) 
    test2 = model(w)
    test3 = model(orig)
print(test1*10000,test2*10000, test3 * 10000)    

A noter qu'il n'a pas été nécessaire de normaliser ou de remettre à l'échelle des données. 

Pytorch propose un mix entre tensorflow (apprentissage profond) et l'approche en apprentissage automatique.


Le notebook est disponible ici sur github 

Les sites consultés et sources sont:
et



Aucun commentaire: