Bildentrauschen mit Kernel PCA#

Dieses Beispiel zeigt, wie KernelPCA zum Entrauschen von Bildern verwendet wird. Kurz gesagt, wir nutzen die während des fit gelernten Näherungsfunktion, um das Originalbild zu rekonstruieren.

Wir vergleichen die Ergebnisse mit einer exakten Rekonstruktion mittels PCA.

Wir verwenden den USPS-Datensatz für Ziffern, um die in Abschnitt 4 von [1] dargestellten Ergebnisse zu reproduzieren.

Referenzen

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

Laden des Datensatzes über OpenML#

Die USPS-Datensätze für Ziffern sind auf OpenML verfügbar. Wir verwenden fetch_openml, um diesen Datensatz zu erhalten. Zusätzlich normalisieren wir den Datensatz, sodass alle Pixelwerte im Bereich (0, 1) liegen.

import numpy as np

from sklearn.datasets import fetch_openml
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler

X, y = fetch_openml(data_id=41082, as_frame=False, return_X_y=True)
X = MinMaxScaler().fit_transform(X)

Die Idee ist, eine PCA-Basis (mit und ohne Kernel) auf verrauschten Bildern zu lernen und diese Modelle dann zum Rekonstruieren und Entrauschen dieser Bilder zu verwenden.

Somit teilen wir unseren Datensatz in einen Trainings- und einen Testdatensatz auf, bestehend aus 1.000 Stichproben für das Training und 100 Stichproben für den Test. Diese Bilder sind rausfrei und wir werden sie verwenden, um die Effizienz der Entrauschungsansätze zu bewerten. Zusätzlich erstellen wir eine Kopie des ursprünglichen Datensatzes und fügen ein Gaußsches Rauschen hinzu.

Die Idee dieser Anwendung ist zu zeigen, dass wir korrumpierte Bilder entrauschen können, indem wir eine PCA-Basis auf einigen unkorrumpierten Bildern lernen. Wir werden sowohl eine PCA als auch eine kernelbasierte PCA verwenden, um dieses Problem zu lösen.

X_train, X_test, y_train, y_test = train_test_split(
    X, y, stratify=y, random_state=0, train_size=1_000, test_size=100
)

rng = np.random.RandomState(0)
noise = rng.normal(scale=0.25, size=X_test.shape)
X_test_noisy = X_test + noise

noise = rng.normal(scale=0.25, size=X_train.shape)
X_train_noisy = X_train + noise

Zusätzlich erstellen wir eine Hilfsfunktion, um die Bildrekonstruktion qualitativ zu bewerten, indem wir die Testbilder plotten.

import matplotlib.pyplot as plt


def plot_digits(X, title):
    """Small helper function to plot 100 digits."""
    fig, axs = plt.subplots(nrows=10, ncols=10, figsize=(8, 8))
    for img, ax in zip(X, axs.ravel()):
        ax.imshow(img.reshape((16, 16)), cmap="Greys")
        ax.axis("off")
    fig.suptitle(title, fontsize=24)

Zusätzlich verwenden wir den mittleren quadratischen Fehler (MSE), um die Bildrekonstruktion quantitativ zu bewerten.

Betrachten wir zunächst den Unterschied zwischen rausfreien und verrauschten Bildern. Wir werden diesbezüglich den Testdatensatz überprüfen.

plot_digits(X_test, "Uncorrupted test images")
plot_digits(
    X_test_noisy, f"Noisy test images\nMSE: {np.mean((X_test - X_test_noisy) ** 2):.2f}"
)
  • Uncorrupted test images
  • Noisy test images MSE: 0.06

Lernen der PCA-Basis#

Wir können nun unsere PCA-Basis sowohl mit einer linearen PCA als auch mit einer Kernel-PCA, die einen radialen Basisfunktions-Kernel (RBF) verwendet, lernen.

from sklearn.decomposition import PCA, KernelPCA

pca = PCA(n_components=32, random_state=42)
kernel_pca = KernelPCA(
    n_components=400,
    kernel="rbf",
    gamma=1e-3,
    fit_inverse_transform=True,
    alpha=5e-3,
    random_state=42,
)

pca.fit(X_train_noisy)
_ = kernel_pca.fit(X_train_noisy)

Rekonstruktion und Entrauschen von Testbildern#

Nun können wir den verrauschten Testdatensatz transformieren und rekonstruieren. Da wir weniger Komponenten als die Anzahl der ursprünglichen Merkmale verwendet haben, erhalten wir eine Annäherung an den ursprünglichen Datensatz. Tatsächlich hoffen wir, Rauschen zu entfernen, indem wir die Komponenten verwerfen, die die geringste Varianz in der PCA erklären. Ein ähnlicher Gedanke findet sich bei der Kernel-PCA; wir erwarten jedoch eine bessere Rekonstruktion, da wir einen nichtlinearen Kernel verwenden, um die PCA-Basis zu lernen, und einen Kernel-Ridge, um die Abbildungsfunktion zu lernen.

X_reconstructed_kernel_pca = kernel_pca.inverse_transform(
    kernel_pca.transform(X_test_noisy)
)
X_reconstructed_pca = pca.inverse_transform(pca.transform(X_test_noisy))
plot_digits(X_test, "Uncorrupted test images")
plot_digits(
    X_reconstructed_pca,
    f"PCA reconstruction\nMSE: {np.mean((X_test - X_reconstructed_pca) ** 2):.2f}",
)
plot_digits(
    X_reconstructed_kernel_pca,
    (
        "Kernel PCA reconstruction\n"
        f"MSE: {np.mean((X_test - X_reconstructed_kernel_pca) ** 2):.2f}"
    ),
)
  • Uncorrupted test images
  • PCA reconstruction MSE: 0.01
  • Kernel PCA reconstruction MSE: 0.03

Die PCA hat eine niedrigere MSE als die Kernel-PCA. Die qualitative Analyse begünstigt jedoch möglicherweise nicht die PCA gegenüber der Kernel-PCA. Wir beobachten, dass die Kernel-PCA Hintergrundrauschen entfernen und ein glatteres Bild liefern kann.

Es sollte jedoch angemerkt werden, dass die Ergebnisse des Entrauschens mit Kernel-PCA von den Parametern n_components, gamma und alpha abhängen.

Gesamtlaufzeit des Skripts: (0 Minuten 5,967 Sekunden)

Verwandte Beispiele

Merkmalsagglomeration

Merkmalsagglomeration

Kernel PCA

Kernel PCA

Erkennung handschriftlicher Ziffern

Erkennung handschriftlicher Ziffern

Online-Lernen eines Diktionärs von Gesichtsteilen

Online-Lernen eines Diktionärs von Gesichtsteilen

Galerie generiert von Sphinx-Gallery