Machine Learning

Adaline – Neuroni adattivi lineari

Il modello Adaline fu una scoperta incredibile nel mondo del Machine Learning perché avvenne solo pochi anni dal Perceptron di Rosenblatt. Questo tipo di algoritmo permette di definire e successivamente minimizzare le funzioni di costo le quali stanno alla base dei successivi algoritmi di Machine Learning avanzati, come quelli a regressione logistica e delle macchine vettoriali di supporto.

La differenza sostanziale tra il Perceptron e la regola Adaline sta nell’aggiornamento dei pesi che, nel primo caso avviene tramite l’utilizzo di una funzione a passo unitario mentre per il restante caso attraverso una funzione di attivazione lineare.

Nel modello Adaline inoltre, viene utilizzato un quantizzatore, che permette di prevedere le etichette delle classi.

Adaline

La differenza sostanziale che troviamo tra i due modelli – Perceptron – e Adaline sta nell’utilizzo dell’output continuo messo a disposizione dalla funzione di attivazione lineare per calcolare l’errore del modello e aggiornare i pesi, invece che contare sulle etichette binarie di una classe.

Minimizzare le funzioni di costo

Uno degli scopi principali degli algoritmi di Machine Learning con supervisione sta nel definire una funzione obbiettivo. Essa è spesso e volentieri una funzione di costo che dobbiamo minimizzare. Nel caso di Adaline la nostra funzione di costo sarà J e servirà per apprendere i pesi in termini di somma dei quadrati degli errori (SSE) fra il risultato calcolato e la vera etichetta della classe:

Adaline

Definiamo un po’ meglio ciò che abbiamo scritto nell’equazione. Il valore numerico che precede la sommatoria è aggiunto solo per comodità. Attraverso questo tipo di funzione lineare continua, la funzione di costo è differenziabile. Essa inoltre è anche di tipo convesso, ciò permette di utilizzare un tipo di algoritmo di ottimizzazione chiamato gradient descent – discesa del gradiente.

Leggi articolo   Titanic dataset - esercizio di Machine Learning

Essa viene utilizzata per trovare i pesi che minimizzano la funzione di costo per classificare i campioni contenuti nel dataset Iris.

Adaline

Una discesa lungo il pendio che permette di trovare un minimo dei costi. A ogni iterazione eseguiamo un passo di allontanamento dal gradiente, dove l’entità del peso è determinata dal valore del tasso di apprendimento, così come dalla discesa del gradiente.

Implementiamo il modello Adaline in Python

Partiamo dal fatto che il codice del modello del Perceptron e quello del modello Adaline sono molto simili. Per questo motivo andremo a riutilizzare il vecchio codice dove effettueremo qualche modifica al metodo fit in modo che i pesi vengano aggiornati minimizzando la funzione di costo tramite la discesa del gradiente:

class AdalineGD(object):
    """ADAptive LInear NEuron classifier.

    Parameters
    ------------
    eta : float
        Learning rate (between 0.0 and 1.0)
    n_iter : int
        Passes over the training dataset.

    Attributes
    -----------
    w_ : 1d-array
        Weights after fitting.
    cost_ : list
        Sum-of-squares cost function value in each epoch.

    """
    def __init__(self, eta=0.01, n_iter=50):
        self.eta = eta
        self.n_iter = n_iter

    def fit(self, X, y):
        """ Fit training data.

        Parameters
        ----------
        X : {array-like}, shape = [n_samples, n_features]
            Training vectors, where n_samples is the number of samples and
            n_features is the number of features.
        y : array-like, shape = [n_samples]
            Target values.

        Returns
        -------
        self : object

        """
        self.w_ = np.zeros(1 + X.shape[1])
        self.cost_ = []

        for i in range(self.n_iter):
            net_input = self.net_input(X)
           
            output = self.activation(X)
            errors = (y - output)
            self.w_[1:] += self.eta * X.T.dot(errors)
            self.w_[0] += self.eta * errors.sum()
            cost = (errors**2).sum() / 2.0
            self.cost_.append(cost)
        return self

    def net_input(self, X):
        """Calculate net input"""
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def activation(self, X):
        """Compute linear activation"""
        return self.net_input(X)

    def predict(self, X):
        """Return class label after unit step"""
        return np.where(self.activation(X) >= 0.0, 1, -1)

Tramite il comando self.eta * error.sum( ) per il peso-zero tramite self.eta * X.T.dot(errors) per i pesi da 1 a m, dove X.T.dot(errors) è una moltiplicazione matrice-vettore fa la matrice delle caratteristiche e il vettore degli errori, calcoliamo il gradiente sulla base dell’intero dataset di addestramento invece di aggiornare i pesi, cosa che facciamo per addestrare un modello Perceptron.

Per verificare se l’algoritmo converge dopo l’addestramento, raccogliamo i valori dei costi in una lista self.cost_ .

Leggi articolo   Scambio di variabili

Condividi il post

Condividi su facebook
Condividi su google
Condividi su twitter
Condividi su email
Condividi su whatsapp