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.