Ich habe versucht, ADALINE in Python zu implementieren

Fortsetzung von Letztes Mal

2.4 ADALINE und Lernkonvergenz

Der Unterschied zum vorherigen Perceptron Der Punkt der Verwendung einer linearen Aktivierungsfunktion anstelle einer Einheitsschrittfunktion zum Aktualisieren von Gewichten

fig1

2.5 Minimierung der Kostenfunktion durch Gradientenabstiegsmethode

J(\mathbf{w}) = \frac{1}{2} \sum_{i} (y^{(i)} - \phi (z^{(i)}))^2

Lernen kann konvergiert werden, indem das Lernen so vorangetrieben wird, dass es zum Mindestwert der Kostenfunktion wird.

ADALINE kann das Gewicht ermitteln, das die Kostenfunktion minimiert, indem die Gradientenabstiegsmethode verwendet wird, indem eine differenzierbare Aktivierungsfunktion verwendet wird und die Summe der Fehlerquadrate als Kostenfunktion verwendet wird, um sie zu einer konvexen Funktion zu machen.

fig2

Ein Diagramm des Prinzips der Gradientenabstiegsmethode

Um die Gewichte mithilfe der Gradientenabstiegsmethode zu aktualisieren, gehen Sie einen Schritt zurück entlang des Gradienten $ \ nabla J (\ mathbf {w}) $ der Kostenfunktion $ J (\ mathbf {w}) $

\mathbf{w} := \mathbf{w} + \Delta \mathbf{w}
\Delta \mathbf{w} = - \eta \nabla J(\mathbf{w})
\frac{\partial J}{\partial w_j} = - \sum_i (y^{(i)} - \phi (z^{(i)})) x_j^{(i)}

Damit

\Delta w_j = - \eta \frac{\partial J}{\partial w_j} = \eta \sum_i (y^{(i)} - \phi (z^{(i)})) x_j^{(i)}

2.5.1 ADALINE in Python implementieren

Die Lernregeln von ADALINE sind Perceptron sehr ähnlich. Unten implementiert

import numpy as np
class AdalineGD(object):
    """ADAptive LInear NEuron-Klassifikator
    
Parameter
    -----------
    eta : float
Lernrate(0.Größer als 0 1.Wert kleiner oder gleich 0)
    n_iter : int
Anzahl der Trainings in Trainingsdaten
    random_state : int
Zufälliger Startwert für die Gewichtsinitialisierung
Attribut
    -----------
    w_ :1-dimensionales Array
Gewicht nach Anpassung
    cost_ :aufführen<- error_Ist kosten_Ändern
Kostenfunktion der Summe der Fehlerquadrate in jeder Epoche
    """
    def __init__(self, eta=0.01, n_iter=50, random_state=1):
        self.eta = eta
        self.n_iter = n_iter
        self.random_state = random_state
        
    def fit(self, X, y):
        """Passt zu Trainingsdaten
        
Parameter
        ------------
        X : {Array-ähnliche Datenstruktur}, shape = [n_samples, n_features]
Trainingsdaten
            n_Proben ist die Anzahl der Proben, n_Features ist die Anzahl der Features
        y :Array-ähnliche Datenstruktur, shape = [n_samples]
Objektive Variable
            
Rückgabewert
        ------------
        self : object
        """
        rgen = np.random.RandomState(self.random_state)
        self.w_ = rgen.normal(loc=0.0, scale=0.01, size=1 + X.shape[1])
        self.cost_ = []

        for _ in range(self.n_iter): #Wiederholen Sie die Trainingsdaten für die Anzahl der Trainings
            net_input = self.net_input(X) #Sie müssen nicht wie bei einer Perceptron-Implementierung für jedes Sample eine Schleife ausführen (ich bin mir nicht sicher, warum Perceptron für jedes Sample eine Schleife durchführt).
            #Weil die Aktivierungsmethode nur eine gleiche Funktion ist
            #Dieser Code hat keine Auswirkung. Implementiert als bloßes Konzept der Aktivierungsfunktion.
            #Bei der Implementierung der logistischen Regression scheint es nur notwendig zu sein, auf die Sigmoid-Funktion umzusteigen.
            output = self.activation(net_input)
            #Fehler y^(i) - φ(z^(i))Berechnung von
            errors = y - output
            #Gewicht w_1, ..., w_m Update
            self.w_[1:] += self.eta * X.T.dot(errors)
            #Gewicht w_Update 0
            self.w_[0] += self.eta * errors.sum()
            #Berechnung der Kostenfunktion
            cost = (errors ** 2).sum() / 2.0
            #Speicherung von Kosten
            self.cost_.append(cost)
        return self

    def net_input(self, X):
        """Berechnen Sie die Gesamteingabe"""
        return np.dot(X, self.w_[1:]) + self.w_[0] #Sie müssen nicht mit xi schleifen

    def activation(self, X):
        """Berechnen Sie die Ausgabe der linearen Aktivierungsfunktion"""
        return X
    
    def predict(self, X):
        """Gibt die Klassenbezeichnung nach einem Schritt zurück"""
        return np.where(self.activation(self.net_input(X)) >= 0.0, 1, -1)

Versuchen Sie es mit gut klassifizierten Daten von Perceptron.

import numpy as np
from sklearn.datasets import load_iris
import pandas as pd
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['target'] = iris.target
df2 = df.query("target != 1").copy() #Etikett 1 ausschließen
df2["target"] -= 1 #Etikett 1-Auf 1 ausrichten
X = df2[['petal width (cm)', 'sepal width (cm)']].values
Y = df2['target'].values

import matplotlib.pyplot as plt
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 4))

ada1 = AdalineGD(n_iter=10, eta=0.01).fit(X, Y)
ax[0].plot(range(1, len(ada1.cost_)+1), np.log10(ada1.cost_), marker='o')
ax[0].set_xlabel('Epochs')
ax[0].set_ylabel('log(Sum-squared-error)')
ax[0].set_title('Adaline - Learning rate 0.01')

ada2 = AdalineGD(n_iter=10, eta=0.0001).fit(X, Y)
ax[1].plot(range(1, len(ada2.cost_)+1), ada2.cost_, marker='o')
ax[1].set_xlabel('Epochs')
ax[1].set_ylabel('Sum-squared-error')
ax[1].set_title('Adaline - Learning rate 0.0001')

output_5_1.png

← ist das Protokoll der Summe der Fehlerquadrate für die Anzahl der Epochen bei einer Lernrate von 0,01 und → ist die Summe der Fehlerquadrate für die Anzahl der Epochen bei einer Lernrate von 0,0001.

Es stellt sich heraus, dass wenn Sie η nicht gut auswählen, es nicht gut konvergiert.

fig3

Wenn die Lernrate hoch ist, streben wir den in der Abbildung gezeigten Mindestwert an, springen jedoch über den Mindestwert und klettern zur gegenüberliegenden Bank.

2.5.2 Verbessern Sie den Gradientenabstieg durch Feature-Skalierung

Skalieren Sie Funktionen für die optimale Leistung von Algorithmen für maschinelles Lernen.

Diesmal standardisierte $ \ mathbf {x} '\ _j = \ frac {\ mathbf {x} \ _ j- \ mu_j} {\ sigma_j} $

Dies gibt den Daten die Eigenschaften einer Standardnormalverteilung und ermöglicht eine schnelle Konvergenz des Lernens.

#Standardisierung
X_std = np.copy(X)
X_std[:, 0] = (X[:, 0] - X[:, 0].mean()) / X[:, 0].std()
X_std[:, 1] = (X[:, 1] - X[:, 1].mean()) / X[:, 1].std()

from sklearn import preprocessing
ss = preprocessing.StandardScaler()
X_std2 = ss.fit_transform(X)

print(X_std[:3])
print(X_std2[:3]) #das Gleiche
[[-1.02461719  0.71907625]
 [-1.02461719 -0.4833924 ]
 [-1.02461719 -0.00240494]]
[[-1.02461719  0.71907625]
 [-1.02461719 -0.4833924 ]
 [-1.02461719 -0.00240494]]
#Grenzplotfunktion früher implementiert

from matplotlib.colors import ListedColormap

def plot_decision_regions(X, y, classifier, resolution=0.02):
    
    #Vorbereitung von Markern und Farbkarten
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])
    
    #Entscheidungsbereichsdiagramm
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    #Generieren Sie Rasterpunkte
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                           np.arange(x2_min, x2_max, resolution))
    #Vorhersage durch Konvertieren jedes Features in ein eindimensionales Array
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    #Konvertieren Sie Vorhersageergebnisse in die ursprüngliche Größe der Rasterpunktdaten
    Z = Z.reshape(xx1.shape)
    #Rasterpunktkonturdiagramm
    plt.contourf(xx1, xx2, Z, alpha=0.3, cmap=cmap)
    #Einstellung des Achsenbereichs
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())
    
    #Zeichnen Sie die Proben nach Klassen
    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0],
                    y=X[y == cl, 1],
                    alpha=0.8,
                    c=colors[idx],
                    marker=markers[idx],
                    label=cl,
                    edgecolor='black')
ada = AdalineGD(n_iter=15, eta=0.01)
ada.fit(X_std, Y)

plot_decision_regions(X_std, Y, classifier=ada)
plt.title('Adaline - Gradient Descent')
plt.xlabel('petal width [standardized]')
plt.ylabel('sepal width [standardized]')
plt.legend(loc='upper left')
plt.tight_layout()
plt.show()

plt.plot(range(1, len(ada.cost_) + 1), ada.cost_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Sum-squared-error')
plt.tight_layout()
plt.show()

output_9_0.png output_9_1.png

Es ist zu sehen, dass es konvergiert hat und die Grenzen der Klassifizierung fest geschlossen sind.

Es kann bestätigt werden, dass die Standardisierung effektiv ist, da sie bei derselben Lernrate nicht gut konvergierte.

ada1 = AdalineGD(n_iter=15, eta=0.01)
ada1.fit(X, Y)

plot_decision_regions(X, Y, classifier=ada1)
plt.title('Adaline - Gradient Descent')
plt.xlabel('petal width [standardized]')
plt.ylabel('sepal width [standardized]')
plt.legend(loc='upper left')
plt.tight_layout()
plt.show()

plt.plot(range(1, len(ada1.cost_) + 1), ada1.cost_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Sum-squared-error')
plt.tight_layout()
plt.show()

output_11_0.png

output_11_1.png

↑ Auch wenn ich versucht habe, nicht standardisierte Daten zu verwenden, hat es nicht funktioniert.

Danach werde ich es mit den Daten versuchen, die beim letzten Mal nicht klassifiziert werden konnten.

import numpy as np
import matplotlib.pyplot as plt
df3 = df.query("target != 0").copy() #Label 0 ausschließen
y = df3.iloc[:, 4].values
y = np.where(y == 1, -1, 1) #Etikett 1-Stellen Sie 1 auf 1 und andere (Etikett 2) auf 1.

# plt.scatter(df3.iloc[:50, 1], df3.iloc[:50, 0], color='orange', marker='o', label='versicolor')
# plt.scatter(df3.iloc[50:, 1], df3.iloc[50:, 0], color='green', marker='o', label='virginica')
# plt.xlabel('sepal width [cm]')
# plt.ylabel('sepal length [cm]')
# plt.legend(loc='upper left')
# plt.show()

X2 = df3[['sepal width (cm)', 'sepal length (cm)']].values
from sklearn import preprocessing
sc = preprocessing.StandardScaler()
X2_std = sc.fit_transform(X2)

ada2 = AdalineGD(n_iter=15, eta=0.01)
ada2.fit(X2_std, y)

plot_decision_regions(X2_std, y, classifier=ada2)
plt.title('Adaline - Gradient Descent')
plt.xlabel('sepal width [standardized]')
plt.ylabel('sepal length [standardized]')
plt.legend(loc='upper left')
plt.tight_layout()
plt.show()

plt.plot(range(1, len(ada2.cost_) + 1), ada2.cost_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Sum-squared-error')
plt.tight_layout()
plt.show()

output_13_0.png output_13_1.png

Natürlich ist es nicht linear und vollständig trennbar, aber da die Grenze an einer vernünftigen Position gezogen wird, kann sie zu den minimalen Kosten konvergiert haben.


2.6 Maschinelles Lernen in großem Maßstab und probabilistische Gradientenabstiegsmethode

Wenn die Anzahl der Daten groß ist, werden die Berechnungskosten der Methode bis zu diesem Punkt (Batch-Gradienten-Abstiegsmethode) hoch.

→ Verwenden Sie die probabilistische Gradientenabstiegsmethode

\Delta \mathbf{w} = \eta \sum_i (y^{(i)} - \phi (z^{(i)})) \mathbf{x}^{(i)}

Aktualisieren Sie stattdessen die Gewichte Schritt für Schritt für jede Probe

\eta (y^{(i)} - \phi (z^{(i)})) \mathbf{x}^{(i)}

Es ist wichtig, die Proben in zufälliger Reihenfolge zu sortieren. Die Vorteile dieser Methode sind, dass sie mit hoher Geschwindigkeit konvergiert, dass sie leicht aus flachen Mindestwerten herauskommt (es gibt viel Rauschen auf der Fehleroberfläche) und dass sie für das Online-Lernen verwendet werden kann.

Online-Lernen… Wenn neue Trainingsdaten eintreffen, trainieren Sie vor Ort und aktualisieren Sie das Modell. Sie können sich schnell an Änderungen anpassen.

Implementieren Sie ADALINE mithilfe der folgenden probabilistischen Gradientenabstiegsmethode

import numpy as np
from numpy.random import seed

class AdalineSGD(object):
    """ADAptive LInear NEuron-Klassifikator
    
Parameter
    -----------
    eta : float
Lernrate(0.Größer als 0 1.Wert kleiner oder gleich 0)
    n_iter : int
Anzahl der Trainings in Trainingsdaten
    shuffle : bool (Standardwert True)
Wenn dies der Fall ist, mischen Sie die Trainingsdaten pro Epoche, um eine Zirkulation zu vermeiden
    random_state : int
Zufälliger Startwert für die Gewichtsinitialisierung
Attribut
    -----------
    w_ :1-dimensionales Array
Gewicht nach Anpassung
    cost_ :aufführen
Die Fehlersumme der Quadrate kostet, um alle Trainingsmuster in jeder Epoche zu mitteln
    """
    def __init__(self, eta=0.01, n_iter=10, shuffle=True, random_state=None):
        self.eta = eta
        self.n_iter = n_iter
        self.w_initialized = False #Gewichtsinitialisierungsflag
        self.shuffle = shuffle
        self.random_state = random_state
        
    def fit(self, X, y):
        """Passt zu Trainingsdaten
        
Parameter
        ------------
        X : {Array-ähnliche Datenstruktur}, shape = [n_samples, n_features]
Trainingsdaten
            n_Proben ist die Anzahl der Proben, n_Features ist die Anzahl der Features
        y :Array-ähnliche Datenstruktur, shape = [n_samples]
Objektive Variable
            
Rückgabewert
        ------------
        self : object
        """
        #Erzeugung eines Gewichtsvektors
        self._initialize_weights(X.shape[1])
        self.cost_ = []
        #Wiederholen Sie dies für die Anzahl der Schulungen
        for i in range(self.n_iter):
            #Mische Trainingsdaten, falls angegeben
            if self.shuffle:
                X, y = self._shuffle(X, y)
            #Erstellen Sie eine Liste, um die Kosten für jede Probe zu speichern
            cost = []
            #Berechnung für jede Probe
            for xi, target in zip(X, y):
                #Gewichtsaktualisierung und Kostenberechnung mit Merkmal xi und Zielvariable y
                cost.append(self._update_weights(xi, target))
            #Berechnung der durchschnittlichen Kosten der Probe
            avg_cost = sum(cost)/len(y)
            #Lagerung der Durchschnittskosten
            self.cost_.append(avg_cost)
        return self

    def partial_fit(self, X, y):
        """Passen Sie die Trainingsdaten an, ohne die Gewichte neu zu initialisieren"""
        #Führen Sie die Initialisierung durch, wenn sie nicht initialisiert wurde
        if not self.w_initialized:
            self._initialize_weights(X.shape[1])
        #Wenn die Anzahl der Elemente der Zielvariablen y 2 oder mehr beträgt
        #Aktualisieren Sie die Gewichte mit den Merkmalsmengen xi und dem Ziel für jede Probe
        if y.ravel().shape[0] > 1:
            for xi, target in zip(X, y):
                self._update_weights(xi, target)
        #Wenn die Anzahl der Elemente der Zielvariablen y 1 ist.
        #Aktualisieren Sie die Gewichte mit Merkmal X und Zielvariable y für die gesamte Stichprobe
        else:
            self._update_weights(X, y)
        return self

    def _shuffle(self, X, y):
        """Mische Trainingsdaten"""
        r = self.rgen.permutation(len(y))
        return X[r], y[r] #Das Mischen kann erreicht werden, indem ein Array an den Index übergeben wird

    def _initialize_weights(self, m):
        """Initialisieren Sie Gewichte mit kleinen Zufallszahlen"""
        self.rgen = np.random.RandomState(self.random_state)
        self.w_ = self.rgen.normal(loc=0.0, scale=0.01, size=1 + m)
        self.w_initialized = True
        
    def _update_weights(self, xi, target):
        """Aktualisieren Sie die Gewichte mithilfe der ADALINE-Lernregeln"""
        #Berechnung der Ausgabe der Aktivierungsfunktion
        output = self.activation(self.net_input(xi))
        #Fehlerberechnung
        error = target - output
        #Gewichtsaktualisierung
        self.w_[1:] += self.eta * xi.dot(error)
        self.w_[0] += self.eta * error
        #Kostenkalkulation
        cost = 0.5 * error**2
        return cost

    def net_input(self, X):
        """Berechnen Sie die Gesamteingabe"""
        return np.dot(X, self.w_[1:]) + self.w_[0]

    def activation(self, X):
        """Berechnen Sie die Ausgabe der linearen Aktivierungsfunktion"""
        return X
    
    def predict(self, X):
        """Gibt die Klassenbezeichnung nach einem Schritt zurück"""
        return np.where(self.activation(self.net_input(X)) >= 0.0, 1, -1)

ada = AdalineSGD(n_iter=15, eta=0.01, random_state=1)
ada.fit(X_std, y)
plot_decision_regions(X_std, y, classifier=ada)
plt.title('Adaline - Stochastic Gradient Descent')
plt.xlabel('petal width [standardized]')
plt.ylabel('sepal width [standardized]')
plt.legend(loc='upper left')
plt.tight_layout()
plt.show()

plt.plot(range(1, len(ada.cost_) + 1), ada.cost_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Average Cost')
plt.show()

output_17_0.png output_17_1.png

Die durchschnittlichen Kosten sinken bald. Die Grenze entspricht der Batch-Gradienten-Abstiegsmethode.

Für das Online-Lernen können Sie ein Update durchführen, indem Sie teilweise_fit aufrufen.

Nachdem ich Perceptron und ADALINE gelernt habe, habe ich mein Verständnis erheblich vertieft, sodass ich denke, dass es mit dieser Anwendung in Zukunft einfacher sein wird, andere Algorithmen für maschinelles Lernen zu verstehen. Es war also gut zu studieren.

Bis jetzt habe ich andere Algorithmen als Black Boxes verwendet, daher war es gut, den Inhalt kennen zu können.

Ich habe ein Notizbuch in Gist.

(Konzeptdiagramme usw. werden wie zuvor aus Kapitel 2 von "Theorie und Praxis von Python Data Learning Expert Data Scientists" zitiert.)

Recommended Posts

Ich habe versucht, ADALINE in Python zu implementieren
Ich habe versucht, PLSA in Python zu implementieren
Ich habe versucht, Permutation in Python zu implementieren
Ich habe versucht, PLSA in Python 2 zu implementieren
Ich habe versucht, PPO in Python zu implementieren
Ich habe versucht, TOPIC MODEL in Python zu implementieren
Ich habe versucht, eine selektive Sortierung in Python zu implementieren
Ich habe versucht, einen Pseudo-Pachislot in Python zu implementieren
Ich habe versucht, GA (genetischer Algorithmus) in Python zu implementieren
Ich habe versucht, einen eindimensionalen Zellautomaten in Python zu implementieren
Ich habe versucht, die Mail-Sendefunktion in Python zu implementieren
Ich habe versucht, das Blackjack of Trump-Spiel mit Python zu implementieren
Ich habe versucht, ein missverstandenes Gefangenendilemma in Python zu implementieren
Ich habe versucht, StarGAN (1) zu implementieren.
Ich habe versucht, die Bayes'sche lineare Regression durch Gibbs-Sampling in Python zu implementieren
Ich habe versucht, Trumps Kartenspiel in Python zu implementieren
Ich habe versucht, die in Python installierten Pakete grafisch darzustellen
Ich möchte Timeout einfach in Python implementieren
Ich habe versucht, Mine Sweeper auf dem Terminal mit Python zu implementieren
Ich habe versucht, künstliches Perzeptron mit Python zu implementieren
Ich habe versucht zusammenzufassen, wie man Pandas von Python benutzt
Ich habe versucht, Deep VQE zu implementieren
Ich habe versucht, Python zu berühren (Installation)
Ich habe versucht, eine kontroverse Validierung zu implementieren
Ich habe versucht, Realness GAN zu implementieren
Ich habe Line Benachrichtigung in Python versucht
Ich habe versucht, die Zusammenführungssortierung in Python mit möglichst wenigen Zeilen zu implementieren
Ich habe versucht, ein scheinbar Windows-Snipper-Tool mit Python zu implementieren
Ich habe versucht, API list.csv mit Python aus swagger.yaml zu erstellen
Ich habe versucht "Wie man eine Methode in Python dekoriert"
Ich habe eine Stoppuhr mit tkinter mit Python gemacht
Ich habe versucht, die Behandlung von Python-Ausnahmen zusammenzufassen
Ich habe versucht, Autoencoder mit TensorFlow zu implementieren
Python3-Standardeingabe habe ich versucht zusammenzufassen
Ich habe versucht, die Bayes'sche Optimierung von Python zu verwenden
Ich wollte ABC159 mit Python lösen
Ich habe versucht, CVAE mit PyTorch zu implementieren
[Python] Ich habe versucht, TF-IDF stetig zu berechnen
Ich habe versucht, Python zu berühren (grundlegende Syntax)
Ich habe Python> autopep8 ausprobiert
Implementieren Sie XENO mit Python
Ich habe versucht zu debuggen.
Implementieren Sie sum in Python
Ich habe Python> Decorator ausprobiert
Implementieren Sie Traceroute in Python 3
Ich habe versucht, das Lesen von Dataset mit PyTorch zu implementieren
Ich möchte Dunnetts Test in Python machen
Versuchen Sie, Oni Mai Tsuji Miserable mit Python zu implementieren
Ich möchte mit Python ein Fenster erstellen
Ich habe versucht, mit Python ein Tippspiel zu spielen
So implementieren Sie Shared Memory in Python (mmap.mmap)
Ich habe versucht, Keras in TFv1.1 zu integrieren
Ich habe versucht, "Birthday Paradox" mit Python zu simulieren
Ich habe die Methode der kleinsten Quadrate in Python ausprobiert
Geschrieben "Einführung in die Effektüberprüfung" in Python
Ich habe versucht, LLVM IR mit Python auszugeben