Codificatori automatici convoluzionali: codificare la complessità in semplicità

Il codice seguente mostra un esempio di codificatore automatico convoluzionale, che è un tipo di codificatore automatico che funziona bene con le immagini. Utilizzeremo il popolare set di dati MNIST (LeCun, Y., Cortes, C., & Burges, CJ (1998). Il database MNIST di cifre scritte a mano. Estratto da TensorFlowCC BY 4.0), che contiene immagini in scala di grigi da 28×28 pixel di cifre scritte a mano. Il codificatore svolge un ruolo cruciale riducendo la dimensionalità dei dati da 784 elementi a una forma più piccola e condensata. Il decodificatore mira quindi a ricostruire i dati originali ad alta dimensione da questa rappresentazione a dimensione inferiore. Tuttavia questa ricostruzione non è perfetta e alcune informazioni vanno perse. Il codificatore automatico supera questa sfida imparando a dare priorità alle caratteristiche più importanti dei dati.

import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras.datasets import mnist
import matplotlib.pyplot as plt

# Load MNIST dataset
(x_train, _), (x_test, _) = mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((len(x_train), 28, 28, 1))
x_test = x_test.reshape((len(x_test), 28, 28, 1))

# Define the convolutional autoencoder architecture
input_img = layers.Input(shape=(28, 28, 1))

# Encoder
x = layers.Conv2D(16, (3, 3), activation='relu', padding='same')(input_img)
x = layers.MaxPooling2D((2, 2), padding='same')(x)
x = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(x)
encoded = layers.MaxPooling2D((2, 2), padding='same')(x)

# Decoder
x = layers.Conv2D(8, (3, 3), activation='relu', padding='same')(encoded)
x = layers.UpSampling2D((2, 2))(x)
x = layers.Conv2D(16, (3, 3), activation='relu', padding='same')(x)
x = layers.UpSampling2D((2, 2))(x)
decoded = layers.Conv2D(1, (3, 3), activation='sigmoid', padding='same')(x)

# Autoencoder model
autoencoder = tf.keras.Model(input_img, decoded)
autoencoder.compile(optimizer='adam', loss='binary_crossentropy')
autoencoder.fit(x_train, x_train, epochs=10, batch_size=64, validation_data=(x_test, x_test))

# Visualization
# Sample images
sample_images = x_test(:8)
# Reconstruct images
reconstructed_images = autoencoder.predict(sample_images)

# Plot original images and reconstructed images
fig, axes = plt.subplots(nrows=2, ncols=8, figsize=(14, 4))
for i in range(8):
axes(0, i).imshow(sample_images(i).squeeze(), cmap='gray')
axes(0, i).set_title("Original")
axes(0, i).axis('off')
axes(1, i).imshow(reconstructed_images(i).squeeze(), cmap='gray')
axes(1, i).set_title("Reconstructed")
axes(1, i).axis('off')
plt.show()

Immagine dell’autore

L’output sopra mostra il funzionamento del codificatore automatico. Visualizza coppie di immagini: le immagini digitali originali e le loro ricostruzioni dopo la codifica e la decodifica. Questo esempio dimostra che il codificatore cattura l’essenza dei dati in una forma più piccola e il decodificatore può avvicinarsi all’immagine originale, anche se alcune informazioni vengono perse durante la compressione.

Ora andiamo oltre e visualizziamo lo spazio latente appreso (il collo di bottiglia). Utilizzeremo PCA e t-SNE, due tecniche per ridurre le dimensioni, per mostrare i punti dati compressi su un piano 2D. Questo passaggio è importante perché ci aiuta a vedere come l’autocodificatore organizza i dati nello spazio latente e mostra eventuali cluster naturali di cifre simili. Abbiamo utilizzato PCA e t-SNE insieme solo per confrontare il loro funzionamento.

# Encode all the test data
encoded_imgs = encoder.predict(x_test)

# Reduce dimensionality using PCA
pca = PCA(n_components=2)
pca_result = pca.fit_transform(encoded_imgs)

# Reduce dimensionality using t-SNE
tsne = TSNE(n_components=2, perplexity=30, n_iter=300)
tsne_result = tsne.fit_transform(encoded_imgs)

# Visualization using PCA
plt.figure(figsize=(20, 10))
plt.subplot(1, 2, 1)
plt.scatter(pca_result(:, 0), pca_result(:, 1), c=y_test, cmap=plt.cm.get_cmap("jet", 10))
plt.colorbar(ticks=range(10))
plt.title('PCA Visualization of Latent Space')

# Visualization using t-SNE
plt.subplot(1, 2, 2)
plt.scatter(tsne_result(:, 0), tsne_result(:, 1), c=y_test, cmap=plt.cm.get_cmap("jet", 10))
plt.colorbar(ticks=range(10))
plt.title('t-SNE Visualization of Latent Space')

plt.show()

Immagine dell’autore

Confrontando i due grafici risultanti, t-SNE è migliore di PCA nel separare diverse classi di cifre nella visualizzazione dello spazio latente (cattura la non linearità). Crea cluster distinti con una sovrapposizione minima tra le classi. Il codificatore automatico comprime le immagini in uno spazio dimensionale inferiore ma cattura comunque informazioni sufficienti per distinguere tra cifre diverse, come mostrato nel grafico t-SNE.

Una nota importante qui è che t-SNE è una tecnica non lineare utilizzata per visualizzare dati ad alta dimensione. Conserva le strutture dei dati locali, rendendolo utile per identificare visivamente cluster e modelli. Tuttavia, in genere non viene utilizzato per la riduzione delle funzionalità nell’apprendimento automatico.

Ma cosa probabilmente impara questo codificatore automatico?

In generale, si può dire che un codificatore automatico come questo apprende i bordi e le trame di base e semplici, spostandosi su parti delle cifre come anelli e linee e il modo in cui sono disposte, e infine comprendendo intere cifre (caratteristiche gerarchiche), tutto questo mentre cattura l’essenza unica di ogni cifra in una forma compatta. Può indovinare le parti mancanti di un’immagine e riconoscere modelli comuni nel modo in cui vengono scritte le cifre.

Fonte: towardsdatascience.com

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *