Realizzazione di previsioni Guida per principianti alla regressione lineare in Python

Beginner's Guide to Linear Regression Implementation in Python

Scopri tutto sul più popolare algoritmo di Machine Learning, la Regressione Lineare, con la sua Intuizione Matematica e l’implementazione in Python.

La Regressione Lineare è l’algoritmo di Machine Learning più popolare e il primo che uno scienziato dei dati apprende quando inizia la sua carriera di data science. È l’algoritmo di apprendimento supervisionato più importante poiché stabilisce i blocchi di costruzione per tutti gli altri algoritmi avanzati di Machine Learning. Ecco perché dobbiamo imparare e capire chiaramente questo algoritmo.

In questo articolo, copriremo la Regressione Lineare da zero, la sua intuizione matematica e geometrica e la sua implementazione in Python. L’unico prerequisito è la vostra volontà di imparare e la conoscenza di base della sintassi di Python. Iniziamo.

Cos’è la Regressione Lineare?

La Regressione Lineare è un algoritmo di Machine Learning supervisionato che viene utilizzato per risolvere problemi di regressione. I modelli di regressione sono utilizzati per prevedere un output continuo basato su altri fattori. Ad esempio, prevedere il prezzo delle azioni dell’organizzazione del mese successivo considerando i margini di profitto, la capitalizzazione di mercato totale, la crescita annuale, etc. La Regressione Lineare può anche essere utilizzata in applicazioni come la previsione del tempo, i prezzi delle azioni, gli obiettivi di vendita, etc.

Come suggerisce il nome, la Regressione Lineare sviluppa una relazione lineare tra due variabili. L’algoritmo trova la migliore linea retta ( y=mx+c ) che può prevedere la variabile dipendente(y) in base alle variabili indipendenti(x). La variabile prevista è chiamata variabile dipendente o target, mentre le variabili utilizzate per la previsione sono chiamate variabili indipendenti o caratteristiche. Se viene utilizzata solo una variabile indipendente, allora è chiamata Regressione Lineare Univariata. In caso contrario, è chiamata Regressione Lineare Multivariata.

Per semplificare questo articolo, prenderemo solo una variabile indipendente(x) in modo da poterla visualizzare facilmente su un piano 2D. Nella sezione successiva, discuteremo la sua intuizione matematica.

Intuizione Matematica

Ora capiremo la geometria della Regressione Lineare e la sua matematica. Supponiamo di avere un insieme di coppie di valori X e Y di esempio,

Dobbiamo utilizzare questi valori per apprendere una funzione in modo che se diamo un valore (x) sconosciuto, possa prevedere un valore (y) in base agli apprendimenti. In regressione, molte funzioni possono essere utilizzate per la previsione, ma la funzione lineare è la più semplice tra tutte.

L’obiettivo principale di questo algoritmo è trovare la linea migliore tra questi punti dati, come indicato nella figura precedente, che fornisce il minore errore residuo. L’errore residuo è la differenza tra il valore previsto e il valore effettivo.

Assunzioni per la Regressione Lineare

Prima di procedere, dobbiamo discutere alcune assunzioni della Regressione Lineare che devono essere prese in considerazione per ottenere previsioni accurate.

  1. Linearità: Linearità significa che le variabili indipendenti e dipendenti devono seguire una relazione lineare. In caso contrario, sarà difficile ottenere una linea retta. Inoltre, i punti dati devono essere indipendenti l’uno dall’altro, cioè i dati di una osservazione non dipendono dai dati di un’altra osservazione.
  2. Omoschedasticità: Afferma che la varianza degli errori residui deve essere costante. Significa che la varianza dei termini di errore dovrebbe essere costante e non cambia anche se i valori della variabile indipendente cambiano. Inoltre, gli errori nel modello devono seguire una distribuzione normale.
  3. No multicollinearità: La multicollinearità significa che c’è una correlazione tra le variabili indipendenti. Quindi, nella Regressione Lineare, le variabili indipendenti non devono essere correlate tra di loro.

Funzione Ipotetica

Ipotizziamo che esisterà una relazione lineare tra la nostra variabile dipendente(Y) e la variabile indipendente(X). Possiamo rappresentare la relazione lineare come segue.

Possiamo osservare che la linea retta dipende dai parametri Θ0 e Θ1. Quindi, per ottenere la linea migliore, dobbiamo regolare o adattare questi parametri. Questi sono anche chiamati i pesi del modello. E per calcolare questi valori, useremo la funzione di perdita, nota anche come funzione di costo. Calcola l’Errore Quadratico Medio tra i valori previsti e quelli effettivi. Il nostro obiettivo è minimizzare questa funzione di costo. I valori di Θ0 e Θ1, in cui la funzione di costo è minimizzata, formeranno la nostra linea migliore. La funzione di costo è rappresentata da (J)

Dove,

N è il numero totale di campioni

La funzione di errore al quadrato è scelta per gestire i valori negativi (cioè se il valore previsto è inferiore al valore effettivo). Inoltre, la funzione è divisa per 2 per facilitare il processo di differenziazione.

Ottimizzatore (Gradient Descent)

L’ottimizzatore è un algoritmo che minimizza l’MSE aggiornando iterativamente gli attributi del modello come i pesi o il tasso di apprendimento per ottenere la linea migliore. Nella regressione lineare, l’algoritmo Gradient Descent viene utilizzato per minimizzare la funzione di costo aggiornando i valori di Θ0 e Θ1.

è un iperparametro chiamato tasso di apprendimento. Determina quanto i nostri pesi sono regolati rispetto alla perdita del gradiente. Il valore del tasso di apprendimento dovrebbe essere ottimale, non troppo alto o troppo basso. Se è troppo alto, è difficile per il modello convergere al minimo globale, e se è troppo piccolo, ci vuole più tempo per convergere.

Traceremo un grafico tra la funzione di costo e i pesi per trovare il Θ0 e il Θ1 ottimali.

Inizialmente, assegneremo valori casuali a Θ0 e Θ1, quindi calcoleremo la funzione di costo e il gradiente. Per un gradiente negativo (una derivata della funzione di costo), dobbiamo muoverci nella direzione dell’aumento di Θ1 per raggiungere il minimo. E per un gradiente positivo, dobbiamo muoverci all’indietro per raggiungere il minimo globale. Miriamo a trovare un punto in cui il gradiente sia quasi uguale a zero. In questo punto, il valore della funzione di costo è minimo.

Adesso, hai capito il funzionamento e la matematica della regressione lineare. La sezione seguente vedrà come implementarla da zero utilizzando Python su un dataset di esempio.

Implementazione di Regressione Lineare in Python

In questa sezione, impareremo come implementare l’algoritmo di regressione lineare da zero utilizzando solo librerie fondamentali come Numpy, Pandas e Matplotlib. Implementeremo la regressione lineare univariata, che contiene solo una variabile dipendente e una indipendente.

Il dataset che utilizzeremo contiene circa 700 coppie di (X, Y) in cui X è la variabile indipendente e Y è la variabile dipendente. Questo dataset è stato fornito da Ashish Jangra, e puoi scaricarlo da qui.

Importazione di Librerie

# Importazione di Librerie Necessarie
import pandas come pd
import numpy come np
import matplotlib.pyplot come plt
import matplotlib.axes come ax
dall'IPython.display import clear_output

Pandas legge il file CSV e ottiene il dataframe, mentre Numpy esegue operazioni di matematica e statistiche di base. Matplotlib è responsabile della tracciatura di grafici e curve.

Caricamento del Dataset

# Link del Dataset:
# https://github.com/AshishJangra27/Machine-Learning-with-Python-GFG/tree/main/Linear%20Regression

df = pd.read_csv("lr_dataset.csv")
df.head()

# Elimina i valori nulli
df = df.dropna()

# Divisione tra Train-Test
N = len(df)
x_train, y_train = np.array(df.X[0:500]).reshape(500, 1), np.array(df.Y[0:500]).reshape(
    500, 1
)
x_test, y_test = np.array(df.X[500:N]).reshape(N - 500, 1), np.array(
    df.Y[500:N]
).reshape(N - 500, 1)

Innanzitutto, otterremo il dataframe df e poi elimineremo i valori nulli. Successivamente divideremo i dati in training e testing x_train , y_train , x_test e y_test.

Costruzione del Modello

class LinearRegression:
    def __init__(self):
        self.Q0 = np.random.uniform(0, 1) * -1  # Intercept
        self.Q1 = np.random.uniform(0, 1) * -1  # Coefficient of X
        self.losses = []  # Storing the loss of each iteration

    def forward_propogation(self, training_input):
        predicted_values = np.multiply(self.Q1, training_input) + self.Q0  # y = mx + c
        return predicted_values

    def cost(self, predictions, training_output):
        return np.mean((predictions - training_output) ** 2)  # Calcolo del costo

    def finding_derivatives(self, cost, predictions, training_input, training_output):
        diff = predictions - training_output
        dQ0 = np.mean(diff)  # d(J(Q0, Q1))/d(Q0)
        dQ1 = np.mean(np.multiply(diff, training_input))  # d(J(Q0, Q1))/d(Q1)
        return dQ0, dQ1

    def train(self, x_train, y_train, lr, itrs):
        for i in range(itrs):
            # Trovare i valori previsti (Utilizzando l'equazione lineare y=mx+c)
            predicted_values = self.forward_propogation(x_train)

            # Calcolo della Perdita
            loss = self.cost(predicted_values, y_train)
            self.losses.append(loss)

            # Back Propagation (Trovare le Derivate dei Pesi)
            dQ0, dQ1 = self.finding_derivatives(
                loss, predicted_values, x_train, y_train
            )

            # Aggiornamento dei Pesi
            self.Q0 = self.Q0 - lr * (dQ0)
            self.Q1 = self.Q1 - lr * (dQ1)

            # Aggiorna dinamicamente la trama della linea retta
            line = self.Q0 + x_train * self.Q1
            clear_output(wait=True)
            plt.plot(x_train, y_train, "+", label="Valori effettivi")
            plt.plot(x_train, line, label="Equazione Lineare")
            plt.xlabel("Train-X")
            plt.ylabel("Train-Y")
            plt.legend()
            plt.show()
        return (
            self.Q0,
            self.Q1,
            self.losses,
        )  # Restituzione dei pesi finali del modello e delle perdite

Abbiamo creato una classe chiamata LinearRegression() in cui sono costruite tutte le funzioni necessarie.

__init__ : Si tratta di un costruttore e inizializzerà i pesi con valori casuali quando l’oggetto di questa classe viene creato.

forward_propogation() : Questa funzione troverà l’output previsto utilizzando l’equazione della linea retta.

cost() : Questo calcolerà l’errore residuo associato ai valori previsti.

finding_derivatives() : Questa funzione calcola la derivata dei pesi, che possono essere utilizzati successivamente per aggiornare i pesi per minimizzare gli errori.

train() : Questa funzione prenderà in input i dati di addestramento, il tasso di apprendimento e il numero totale di iterazioni. Aggiorna i pesi utilizzando la back-propagation fino al numero specificato di iterazioni. Alla fine, restituisce i pesi della linea di best-fit.

Addestramento del modello

lr = 0.0001  # Tasso di apprendimento
itrs = 30  # Numero di iterazioni
model = LinearRegression()
Q0, Q1, losses = model.train(x_train, y_train, lr, itrs)

# Output Numero di Iterazione vs Perdita
for itr in range(len(losses)):
    print(f"Iterazione = {itr+1}, Perdita = {losses[itr]}")

Output:

Iterazione = 1, Perdita = 6547.547538061649
Iterazione = 2, Perdita = 3016.791083711492
Iterazione = 3, Perdita = 1392.3048668536044
Iterazione = 4, Perdita = 644.8855797373262
Iterazione = 5, Perdita = 301.0011032250385
Iterazione = 6, Perdita = 142.78129818453215
.
.
.
.
Iterazione = 27, Perdita = 7.949420840198964
Iterazione = 28, Perdita = 7.949411555664398
Iterazione = 29, Perdita = 7.949405538972356
Iterazione = 30, Perdita = 7.949401025888949

Puoi osservare che nella prima iterazione, la perdita è massima e nelle iterazioni successive questa perdita diminuisce e raggiunge il suo valore minimo alla fine della trentesima iterazione.

Fig.3 Trovare la linea di best-fit | Immagine di autore

La gif sopra indica come la linea retta raggiunga la sua linea di best-fit dopo aver completato la trentesima iterazione.

Predizione Finale

# Predizione sui dati di test
y_pred = Q0 + x_test * Q1
print(f"Linea di best-fit: (Y = {Q1}*X + {Q0})")

# Plot della linea di regressione con i punti di dati effettivi
plt.plot(x_test, y_test, "+", label="Punti di dati")
plt.plot(x_test, y_pred, label="Valori previsti")
plt.xlabel("X-Test")
plt.ylabel("Y-Test")
plt.legend()
plt.show()

Questa è l’equazione finale della linea di best-fit.

Linea di best-fit: (Y = 1.0068007107347927*X + -0.653638673779529)

Fig.4 Output Effettivo vs Previsto | Immagine di autore

Il grafico sopra mostra la linea di best-fit (arancione) e i valori effettivi (blu +) del set di test. Puoi anche regolare gli iperparametri, come il tasso di apprendimento o il numero di iterazioni, per aumentare l’accuratezza e la precisione.

Regressione Lineare (Utilizzando la Libreria Sklearn)

Nella sezione precedente, abbiamo visto come implementare la Regressione Lineare Univariata da zero. Ma c’è anche una libreria integrata di sklearn che può essere utilizzata direttamente per implementare la Regressione Lineare. Vediamo brevemente come possiamo farlo.

Useremo lo stesso dataset, ma se vuoi, puoi utilizzarne uno diverso. È necessario importare due librerie aggiuntive come segue.

# Importazione di librerie aggiuntive
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

Caricamento del dataset

df = pd.read_csv("lr_dataset.csv")

# Eliminazione dei valori nulli
df = df.dropna()

# Divisione in training set e test set
Y = df.Y
X = df.drop("Y", axis=1)
x_train, x_test, y_train, y_test = train_test_split(
    X, Y, test_size=0.25, random_state=42
)

In precedenza, dovevamo eseguire manualmente la divisione tra training set e test set utilizzando la libreria numpy. Ma ora possiamo usare la funzione train_test_split() di sklearn per dividere direttamente i dati in training set e test set specificando solo la dimensione del test set.

Addestramento del modello e previsioni

model = LinearRegression()
model.fit(x_train, y_train)
y_pred = model.predict(x_test)

# Plot della linea di regressione con i dati effettivi
plt.plot(x_test, y_test, "+", label="Valori reali")
plt.plot(x_test, y_pred, label="Valori previsti")
plt.xlabel("X")
plt.ylabel("Y")
plt.legend()
plt.show()

Ora non dobbiamo più scrivere il codice per la propagazione in avanti, la propagazione all’indietro, la funzione di costo, ecc. Possiamo utilizzare direttamente la classe LinearRegression() e addestrare il modello sui dati in ingresso. Qui di seguito è riportato il grafico ottenuto sui dati di test dal modello addestrato. I risultati sono simili a quando abbiamo implementato l’algoritmo da soli.

Fig.5 Output del modello Sklearn | Immagine dell’autore

Riferimenti

  1. GeeksForGeeks: ML Linear Regression

Conclusione

Link a Google Colab per il codice completo – Tutorial di Regressione Lineare

In questo articolo abbiamo discusso approfonditamente cosa sia la Regressione Lineare, la sua intuizione matematica e la sua implementazione in Python sia da zero che utilizzando la libreria sklearn. Questo algoritmo è diretto e intuitivo, quindi aiuta i principianti a gettare una solida base e a acquisire competenze pratiche di codifica per fare previsioni accurate utilizzando Python.

Grazie per la lettura. Aryan Garg è uno studente di Ingegneria Elettrica, attualmente al suo ultimo anno di laurea triennale. Il suo interesse risiede nel campo dello sviluppo web e del machine learning. Ha coltivato questo interesse ed è entusiasta di lavorare di più in queste direzioni.