Zifferklassifizierung mit RBM-Features

Beginner

This tutorial is from open-source community. Access the source code

Einführung

In diesem Lab geht es um die Verwendung der Bernoulli Restricted Boltzmann Machine (RBM) zur Klassifizierung von handschriftlichen Ziffern. Der RBM-Feature-Extraktor wird mit einem logistischen Regressionsklassifizierer kombiniert, um die Ziffern vorherzusagen. Der verwendete Datensatz ist ein Graustufen-Bild-Datensatz, wobei die Pixelwerte als Schwarzgrad auf einem weißen Hintergrund interpretiert werden können.

Tipps für die VM

Nachdem der VM-Start abgeschlossen ist, klicken Sie in der oberen linken Ecke, um zur Registerkarte Notebook zu wechseln und Jupyter Notebook für die Übung zu nutzen.

Manchmal müssen Sie einige Sekunden warten, bis Jupyter Notebook vollständig geladen ist. Die Validierung von Vorgängen kann aufgrund der Einschränkungen in Jupyter Notebook nicht automatisiert werden.

Wenn Sie bei der Lernphase Probleme haben, können Sie Labby gerne fragen. Geben Sie nach der Sitzung Feedback, und wir werden das Problem für Sie prompt beheben.

Datenvorbereitung

In diesem Schritt bereiten wir die Daten für das Training und die Tests vor. Wir verwenden die Funktion load_digits aus sklearn.datasets, um den Datensatz zu erhalten. Anschließend erzeugen wir künstlich mehr markierte Daten, indem wir die Trainingsdaten um eine lineare Verschiebung von 1 Pixel in jeder Richtung stören. Wir skalieren die Daten zwischen 0 und 1.

import numpy as np
from scipy.ndimage import convolve
from sklearn import datasets
from sklearn.preprocessing import minmax_scale
from sklearn.model_selection import train_test_split

def nudge_dataset(X, Y):
    """
    Dies erzeugt einen Datensatz, der 5-mal größer als der ursprüngliche ist,
    indem die 8x8-Bilder in X um 1 Pixel nach links, rechts, unten, oben verschoben werden
    """
    direction_vectors = [
        [[0, 1, 0], [0, 0, 0], [0, 0, 0]],
        [[0, 0, 0], [1, 0, 0], [0, 0, 0]],
        [[0, 0, 0], [0, 0, 1], [0, 0, 0]],
        [[0, 0, 0], [0, 0, 0], [0, 1, 0]],
    ]

    def shift(x, w):
        return convolve(x.reshape((8, 8)), mode="constant", weights=w).ravel()

    X = np.concatenate(
        [X] + [np.apply_along_axis(shift, 1, X, vector) for vector in direction_vectors]
    )
    Y = np.concatenate([Y for _ in range(5)], axis=0)
    return X, Y

X, y = datasets.load_digits(return_X_y=True)
X = np.asarray(X, "float32")
X, Y = nudge_dataset(X, y)
X = minmax_scale(X, feature_range=(0, 1))  ## 0-1 Skalierung

X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=0)

Modelldefinition

In diesem Schritt definieren wir die Klassifizierungs-Pipeline mit einem BernoulliRBM-Feature-Extraktor und einem logistischen Regressionsklassifizierer. Wir verwenden die Klassen BernoulliRBM und LogisticRegression aus den Modulen sklearn.neural_network und sklearn.linear_model respective. Anschließend erstellen wir ein Pipeline-Objekt rbm_features_classifier, um die beiden Modelle zu kombinieren.

from sklearn import linear_model
from sklearn.neural_network import BernoulliRBM
from sklearn.pipeline import Pipeline

logistic = linear_model.LogisticRegression(solver="newton-cg", tol=1)
rbm = BernoulliRBM(random_state=0, verbose=True)

rbm_features_classifier = Pipeline(steps=[("rbm", rbm), ("logistic", logistic)])

Training

In diesem Schritt trainieren wir das in dem vorherigen Schritt definierte Pipeline-Modell. Wir setzen die Hyperparameter des Modells (Lernrate, Größe der versteckten Schicht, Regularisierung) und passen dann die Trainingsdaten an das Modell an.

from sklearn.base import clone

## Hyperparameter. Diese wurden durch Kreuzvalidierung festgelegt,
## unter Verwendung eines GridSearchCV. Hier führen wir keine Kreuzvalidierung durch,
## um Zeit zu sparen.
rbm.learning_rate = 0.06
rbm.n_iter = 10

## Mehr Komponenten tendieren dazu, eine bessere Vorhersageleistung zu liefern, aber eine längere
## Anpassungszeit
rbm.n_components = 100
logistic.C = 6000

## Training des RBM-Logistic-Pipelines
rbm_features_classifier.fit(X_train, Y_train)

Evaluation

In diesem Schritt evaluieren wir die Leistung des Modells auf dem Testdatensatz. Wir verwenden die Funktion classification_report aus dem Modul sklearn.metrics, um den Klassifikationsbericht sowohl für das Pipeline-Modell als auch für das logistische Regressionsmodell zu generieren.

from sklearn import metrics

Y_pred = rbm_features_classifier.predict(X_test)
print(
    "Logistische Regression mit RBM-Features:\n%s\n"
    % (metrics.classification_report(Y_test, Y_pred))
)

## Direktes Training des logistischen Regressionsklassifizierers auf den Pixeln
raw_pixel_classifier = clone(logistic)
raw_pixel_classifier.C = 100.0
raw_pixel_classifier.fit(X_train, Y_train)

Y_pred = raw_pixel_classifier.predict(X_test)
print(
    "Logistische Regression mit rohen Pixel-Features:\n%s\n"
    % (metrics.classification_report(Y_test, Y_pred))
)

Plotting

In diesem Schritt plotten wir die 100 Komponenten, die von der RBM extrahiert wurden. Wir verwenden das Modul matplotlib.pyplot, um die Bilder zu plotten.

import matplotlib.pyplot as plt

plt.figure(figsize=(4.2, 4))
for i, comp in enumerate(rbm.components_):
    plt.subplot(10, 10, i + 1)
    plt.imshow(comp.reshape((8, 8)), cmap=plt.cm.gray_r, interpolation="nearest")
    plt.xticks(())
    plt.yticks(())
plt.suptitle("100 Komponenten, die von der RBM extrahiert wurden", fontsize=16)
plt.subplots_adjust(0.08, 0.02, 0.92, 0.85, 0.08, 0.23)

plt.show()

Zusammenfassung

In diesem Lab haben wir gelernt, wie man die Bernoulli Restricted Boltzmann Machine (RBM) mit logistischer Regression für die Klassifizierung von handschriftlichen Ziffern verwendet. Wir haben auch gelernt, wie man die Leistung des Modells mit Hilfe des Klassifikationsberichts 计算 und wie man die von der RBM extrahierten Komponenten plotten kann.