In het algemeen kun je auto-encoders beschouwen als een unsupervised leertechniek, omdat je geen expliciete labels nodig hebt om het model te trainen. Alles wat je nodig hebt om een auto-encoder te trainen, is ruwe inputdata.
In deze tutorial leer je over auto-encoders in deep learning en implementeer je een convolutionele en denoising auto-encoder in Python met Keras. Je werkt met de NotMNIST-alfabetdataset als voorbeeld.
Kort samengevat behandel je vandaag de volgende onderwerpen:
Eerst leer je meer over auto-encoders: wat ze zijn, hoe ze zich verhouden tot technieken voor dimensiereductie en de verschillende typen van dit algoritme;
Vervolgens focus je op de convolutionele auto-encoder: je ziet wat dit type auto-encoder doet en hoe je hem kunt opbouwen. Daarna implementeer je er zelf een! Je leert hoe je data in ubyte gzip-formaat laadt, vervolgens verken je de data, preprocess je de data, pas je de data in een model, visualiseer je de trainings- en validatieverliesgrafiek en voorspel je tot slot op de testset.
Daarna maak je kennis met de denoising auto-encoder en zie je hoe je er een kunt implementeren: je leert ruis aan de beelden toe te voegen. Vervolgens voer je deze beelden in je deep learning-model en train je het! Tot slot voorspel je op de ruisachtige testbeelden.
Auto-encoder
Zoals je in de introductie las, is een auto-encoder een unsupervised machine learning-algoritme dat een afbeelding als input neemt en probeert deze te reconstrueren met minder bits vanuit de bottleneck, ook wel de latente ruimte genoemd. De afbeelding wordt bij de bottleneck grotendeels gecomprimeerd. De compressie in auto-encoders wordt bereikt door het netwerk een tijd te trainen; naarmate het leert, probeert het de inputafbeelding zo goed mogelijk te representeren in de bottleneck. Algemene beeldcompressie-algoritmen zoals JPEG en JPEG lossless comprimeren afbeeldingen zonder enige vorm van training en doen dat behoorlijk goed.
Auto-encoders lijken op technieken voor dimensiereductie zoals Principal Component Analysis (PCA). Ze projecteren data van een hogere dimensie naar een lagere dimensie met lineaire transformaties en proberen de belangrijke kenmerken van de data te behouden terwijl ze de niet-essentiële delen verwijderen.
Het belangrijkste verschil tussen auto-encoders en PCA zit echter in de transformatie: zoals je al las, gebruikt PCA lineaire transformaties, terwijl auto-encoders niet-lineaire transformaties gebruiken.
Nu je een beetje begrip hebt van auto-encoders, laten we de term opsplitsen en er wat intuïtie bij krijgen!
De bovenstaande afbeelding is een vanilla auto-encoder met twee lagen en één verborgen laag. In deep learning-terminologie zul je vaak merken dat de inputlaag niet wordt meegeteld bij het bepalen van het totale aantal lagen in een architectuur. Het totaal aantal lagen in een architectuur bestaat alleen uit het aantal verborgen lagen en de outputlaag.
Zoals in de afbeelding te zien is, hebben de input- en outputlagen hetzelfde aantal neuronen.
Neem een voorbeeld. Je voert een afbeelding met slechts vijf pixelwaarden in de auto-encoder, die door de encoder wordt gecomprimeerd naar drie pixelwaarden bij de bottleneck (middelste laag) of latente ruimte. Met deze drie waarden probeert de decoder de vijf pixelwaarden of eigenlijk de inputafbeelding te reconstrueren die je als input aan het netwerk hebt gegeven.
In de praktijk zitten er meer verborgen lagen tussen de input en de output.
Een auto-encoder kun je in drie delen opdelen
Encoder: dit deel van het netwerk comprimeert of downsamplet de input naar een kleiner aantal bits. De ruimte die door dit kleinere aantal bits wordt vertegenwoordigd, wordt vaak de latente ruimte of bottleneck genoemd. De bottleneck heet ook wel het "maximale compressiepunt", omdat de input hier maximaal gecomprimeerd is. De gecomprimeerde bits die de oorspronkelijke input representeren, worden samen een “encoding” van de input genoemd.
Decoder: dit deel van het netwerk probeert de input te reconstrueren met alleen de encoding van de input. Als de decoder de input exact kan reconstrueren zoals die aan de encoder werd gevoerd, kun je zeggen dat de encoder de beste encodings voor de input kan produceren waarmee de decoder goed kan reconstrueren!
Er zijn verschillende soorten auto-encoders, zoals de convolutionele auto-encoder, denoising auto-encoder, variational auto-encoder en sparse auto-encoder. Zoals je in de introductie las, focus je in deze tutorial alleen op de convolutionele en denoising varianten.Convolutionele auto-encoders in Python met Keras
Omdat je inputdata uit afbeeldingen bestaat, is het een goed idee om een convolutionele auto-encoder te gebruiken. Het is geen auto-encoder-variant, maar eerder een traditionele auto-encoder met convolutionele lagen erbovenop: je vervangt in feite volledig verbonden lagen door convolutionele lagen. Convolutionele lagen, samen met max-pooling-lagen, zetten de input om van breed (een 28 x 28-afbeelding) en dun (één kanaal of grijswaarden) naar klein (7 x 7-afbeelding in de latente ruimte) en dik (128 kanalen).
Maak je geen zorgen als je het bovenstaande idee nog niet helemaal begrijpt! Het tweede deel van deze tutorial, waarin je focust op de implementatie hiervan, zal hopelijk al je twijfels wegnemen (als je die hebt!).
Tip: als je meer wilt weten over convolutionele neurale netwerken, bekijk dan deze tutorial.
Dit helpt het netwerk om visuele kenmerken uit de afbeeldingen te halen en zo een nauwkeurigere representatie in de latente ruimte te krijgen. Het reconstructieproces gebruikt upsampling en convoluties, die bekendstaan als een decoder. Het downsamplen is het proces waarin de afbeelding wordt gecomprimeerd naar een lage dimensie, ook wel een encoder genoemd.
Het is belangrijk om op te merken dat de encoder vooral de inputafbeelding comprimeert; bijvoorbeeld: als je inputafbeelding de afmeting 176 x 176 x 1 (~30976) heeft, dan kan het maximale compressiepunt een dimensie van 22 x 22 x 512 (~247808) hebben. In dit geval begon je met een grijswaardenafbeelding van 176 x 176 en door die door een paar convolutionele lagen en precies drie max-pooling-lagen te sturen, is je afbeelding uiteindelijk gedownsampeld naar een dimensie van 22 x 22, maar het aantal kanalen is toegenomen van 1 naar 512. Zoals hierboven vermeld, werd je input van breed (176 x 176) en dun (1) klein (22x22) en dik (512).
De data laden
De notMNIST-dataset is een beeldherkenningsdataset van lettertypeglyphs voor de letters A tot en met J. Ze lijkt sterk op de klassieke MNIST-dataset, die afbeeldingen bevat van handgeschreven cijfers 0 tot en met 9: in dit geval vind je dat de NotMNIST-dataset bestaat uit 28x28 grijswaardenafbeeldingen van 70.000 letters van A - J in totaal 10 categorieën, en 6.000 afbeeldingen per categorie.
Tip: als je wilt leren hoe je een Multi-Layer Perceptron (MLP) voor classificatietaken met de MNIST-dataset implementeert, bekijk dan deze tutorial.
De NotMNIST-dataset is niet vooraf gedefinieerd in het Keras- of TensorFlow-framework, dus je zult de data moeten downloaden van deze bron. De data wordt gedownload in ubyte.gzip-formaat, maar maak je daar nog geen zorgen over! Je leert zo hoe je bytestream-formaten leest en ze omzet naar een NumPy-array. Laten we beginnen!
Het netwerk wordt getraind op een Nvidia Tesla K40, dus als je op een GPU traint en Jupyter Notebook gebruikt, moet je drie extra regels code toevoegen waarin je de CUDA device order en CUDA visible devices specificeert met een module genaamd os.
In de onderstaande code stel je in feite omgevingsvariabelen in in de notebook met os.environ. Het is goed om het volgende te doen vóór je Keras initialiseert, om de Keras-backend TensorFlow te beperken tot de eerste GPU. Als de machine waarop je traint een GPU op 0 heeft, gebruik dan 0 in plaats van 1. Je kunt dat controleren door een eenvoudig commando in je terminal uit te voeren: bijvoorbeeld nvidia-smi
import os
os.environ["CUDA_DEVICE_ORDER"]="PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"]="1"#model will be trained on GPU 1Mogelijk gemaakt door
Vervolgens importeer je alle vereiste modules zoals numpy, matplotlib en vooral keras, aangezien je dat framework in deze tutorial gebruikt!
import keras
from matplotlib import pyplot as plt
import numpy as np
import gzip
%matplotlib inline
from keras.layers import Input,Conv2D,MaxPooling2D,UpSampling2D
from keras.models import Model
from keras.optimizers import RMSprop
Mogelijk gemaakt door
Hier definieer je een functie die het gzip-bestand opent en het bestand leest met bytestream.read(). Je geeft de afbeeldingsdimensie en het totale aantal afbeeldingen door aan deze functie. Vervolgens zet je met np.frombuffer() de string die is opgeslagen in variabele buf om naar een NumPy-array van type float32.
Daarna vorm je de array om naar een driedimensionale array of tensor, waarbij de eerste dimensie het aantal afbeeldingen is en de tweede en derde dimensie de dimensies van de afbeelding zijn. Tot slot retourneer je de NumPy-array data.
defextract_data(filename, num_images):with gzip.open(filename)as bytestream:
bytestream.read(16)
buf = bytestream.read(28*28* num_images)
data = np.frombuffer(buf, dtype=np.uint8).astype(np.float32)
data = data.reshape(num_images,28,28)return data
Mogelijk gemaakt door
Je roept nu de functie extract_data() aan door de trainings- en testbestanden door te geven, samen met hun bijbehorende aantal afbeeldingen:
train_data = extract_data('train-images-idx3-ubyte.gz',60000)
test_data = extract_data('t10k-images-idx3-ubyte.gz',10000)Mogelijk gemaakt door
Evenzo definieer je een functie om labels te extraheren die het gzip-bestand opent en het bestand leest met bytestream.read(), waaraan je de labeldimensie (1) en het totale aantal afbeeldingen doorgeeft. Vervolgens zet je met np.frombuffer() de string die is opgeslagen in variabele buf om naar een NumPy-array van type int64.
Dit keer hoef je de array niet te reshapen, omdat de variabele labels een kolomvector van dimensie 60.000 x 1 zal teruggeven. Tot slot retourneer je de NumPy-array labels.
defextract_labels(filename, num_images):with gzip.open(filename)as bytestream:
bytestream.read(8)
buf = bytestream.read(1* num_images)
labels = np.frombuffer(buf, dtype=np.uint8).astype(np.int64)return labels
Mogelijk gemaakt door
Je roept nu de functie voor het extraheren van labels aan door de trainings- en testlabelfiles door te geven, samen met hun bijbehorende aantal afbeeldingen:
train_labels = extract_labels('train-labels-idx1-ubyte.gz',60000)
test_labels = extract_labels('t10k-labels-idx1-ubyte.gz',10000)Mogelijk gemaakt door
Als je de trainings- en testdata eenmaal hebt geladen, ben je klaar om de data te analyseren om wat intuïtie te krijgen over de dataset waarmee je in deze tutorial gaat werken!
Data verkennen
Laten we nu analyseren hoe afbeeldingen in de dataset eruitzien en ook de dimensies van de afbeeldingen bekijken met behulp van het NumPy-arrayattribuut .shape:
# Shapes of training setprint("Training set (images) shape: {shape}".format(shape=train_data.shape))# Shapes of test setprint("Test set (images) shape: {shape}".format(shape=test_data.shape))Mogelijk gemaakt door
Training set(images) shape:(60000,28,28)
Test set(images) shape:(10000,28,28)Mogelijk gemaakt door
Uit de bovenstaande output zie je dat de trainingsdata een vorm heeft van 60000 x 28 x 28, omdat er 60.000 trainingsvoorbeelden zijn, elk een matrix van 28 x 28. Evenzo heeft de testdata een vorm van 10000 x 28 x 28, omdat er 10.000 testvoorbeelden zijn.
Let op dat je in deze taak de trainings- en testlabels niet zult gebruiken. De taak gaat alleen over de trainings- en testafbeeldingen. Maar voor verkenningsdoeleinden, wat je een betere intuïtie over de data kan geven, maak je wel gebruik van de labels.
Laten we een woordenboek maken dat klassennamen met hun bijbehorende categorische klasselabels bevat:
# Create dictionary of target classes
label_dict ={0:'A',1:'B',2:'C',3:'D',4:'E',5:'F',6:'G',7:'H',8:'I',9:'J',}Mogelijk gemaakt door
Bekijk nu een paar afbeeldingen in je dataset:
plt.figure(figsize=[5,5])# Display the first image in training data
plt.subplot(121)
curr_img = np.reshape(train_data[0],(28,28))
curr_lbl = train_labels[0]
plt.imshow(curr_img, cmap='gray')
plt.title("(Label: "+str(label_dict[curr_lbl])+")")# Display the first image in testing data
plt.subplot(122)
curr_img = np.reshape(test_data[0],(28,28))
curr_lbl = test_labels[0]
plt.imshow(curr_img, cmap='gray')
plt.title("(Label: "+str(label_dict[curr_lbl])+")")Mogelijk gemaakt door
De output van bovenstaande twee plots zijn een van de voorbeeldafbeeldingen uit zowel de trainings- als testdata, en deze afbeeldingen hebben respectievelijk een klasselabel 5 of F en 3 of D. Op dezelfde manier hebben andere letters verschillende labels, maar vergelijkbare letters hebben hetzelfde label. Dit betekent dat alle 6.000 afbeeldingen van klasse F een klasselabel 5 hebben.
Data preprocessing
De afbeeldingen in de dataset zijn inderdaad grijswaardenafbeeldingen met pixelwaarden van 0 tot 255 en een dimensie van 28 x 28. Voordat je de data in het model voert, is het heel belangrijk om te preprocessen. Je zet eerst elke 28 x 28-afbeelding van de train- en testset om naar een matrix van 28 x 28 x 1, die je in het netwerk kunt voeren:
train_data = train_data.reshape(-1,28,28,1)
test_data = test_data.reshape(-1,28,28,1)
train_data.shape, test_data.shape
Mogelijk gemaakt door
Controleer vervolgens het datatype van de trainings- en test-NumPy-arrays; dit moet float32 zijn. Zo niet, dan moet je het omzetten naar dit formaat, maar omdat je dat al hebt gedaan tijdens het inlezen van de data, hoeft dat nu niet meer. Je moet de pixelwaarden ook herschalen naar het bereik 0 - 1 inclusief. Laten we dat doen!
Vergeet niet de datatypes van de trainings- en testdata te verifiëren:
Na dit alles is het belangrijk om de data op te splitsen. Om je model goed te laten generaliseren, splits je de trainingsdata in twee delen: een train- en een validatieset. Je traint je model op 80% van de data en valideert op 20% van de overgebleven trainingsdata.
Dit helpt ook om de kans op overfitting te verkleinen, omdat je je model valideert op data die het niet heeft gezien tijdens de trainingsfase.
Je kunt de module train_test_split van scikit-learn gebruiken om de data goed te verdelen:
from sklearn.model_selection import train_test_split
train_X,valid_X,train_ground,valid_ground = train_test_split(train_data,
train_data,
test_size=0.2,
random_state=13)Mogelijk gemaakt door
Let op dat je voor deze taak geen trainings- en testlabels nodig hebt. Daarom geef je de trainingsafbeeldingen twee keer door. Je trainingsafbeeldingen fungeren zowel als input als als ground truth, vergelijkbaar met de labels die je hebt bij een classificatietaak.
Nu ben je klaar om het netwerk te definiëren en de data erin te voeren. Dus zonder verder oponthoud: door naar de volgende stap!
De convolutionele auto-encoder
De afbeeldingen hebben formaat 28 x 28 x 1 ofwel een 784-dimensionale vector. Je zet de afbeeldingsmatrix om naar een array, schaalt die tussen 0 en 1, vormt hem om naar 28 x 28 x 1 en voert dit als input aan het netwerk.
Ook gebruik je een batchgrootte van 128; een hogere batchgrootte van 256 of 512 is ook prima, het hangt af van het systeem waarop je je model traint. Dit draagt sterk bij aan het bepalen van de leerparameters en beïnvloedt de voorspellingsnauwkeurigheid. Je traint je netwerk 50 epochs.
batch_size =128
epochs =50
inChannel =1
x, y =28,28
input_img = Input(shape =(x, y, inChannel))Mogelijk gemaakt door
Zoals eerder besproken, is de auto-encoder opgedeeld in twee delen: een encoder en een decoder.
Encoder
De eerste laag heeft 32 filters van 3 x 3, gevolgd door een downsampling- (max-pooling-)laag,
De tweede laag heeft 64 filters van 3 x 3, gevolgd door nog een downsampling-laag,
De laatste laag van de encoder heeft 128 filters van 3 x 3.
Decoder
De eerste laag heeft 128 filters van 3 x 3, gevolgd door een upsampling-laag,/li>
De tweede laag heeft 64 filters van 3 x 3, gevolgd door nog een upsampling-laag,
De laatste laag van de encoder heeft 1 filter van 3 x 3.
De max-poolinglaag downsamplet de input telkens met een factor twee, terwijl de upsamplinglaag de input telkens met een factor twee upsamplet.
Let op: Het aantal filters, de filtergrootte, het aantal lagen, het aantal epochs waarop je je model traint: het zijn allemaal hyperparameters en moeten worden bepaald op basis van je eigen intuïtie. Je kunt vrij experimenteren door met deze hyperparameters te spelen en de prestaties van je model te meten. Zo leer je stap voor stap de kunst van deep learning!
defautoencoder(input_img):#encoder#input = 28 x 28 x 1 (wide and thin)
conv1 = Conv2D(32,(3,3), activation='relu', padding='same')(input_img)#28 x 28 x 32
pool1 = MaxPooling2D(pool_size=(2,2))(conv1)#14 x 14 x 32
conv2 = Conv2D(64,(3,3), activation='relu', padding='same')(pool1)#14 x 14 x 64
pool2 = MaxPooling2D(pool_size=(2,2))(conv2)#7 x 7 x 64
conv3 = Conv2D(128,(3,3), activation='relu', padding='same')(pool2)#7 x 7 x 128 (small and thick)#decoder
conv4 = Conv2D(128,(3,3), activation='relu', padding='same')(conv3)#7 x 7 x 128
up1 = UpSampling2D((2,2))(conv4)# 14 x 14 x 128
conv5 = Conv2D(64,(3,3), activation='relu', padding='same')(up1)# 14 x 14 x 64
up2 = UpSampling2D((2,2))(conv5)# 28 x 28 x 64
decoded = Conv2D(1,(3,3), activation='sigmoid', padding='same')(up2)# 28 x 28 x 1return decoded
Mogelijk gemaakt door
Nadat het model is gemaakt, moet je het compileren met de optimizer RMSProp.
Tip: bekijk deze tutorial van Andrew Ng over RMSProp als je er meer over wilt weten.
Let op dat je ook het type verlies moet specificeren via het argument loss. In dit geval is dat de mean squared error, omdat het verlies na elke batch wordt berekend tussen de batch met voorspelde output en de ground truth met behulp van mean squared error, pixel voor pixel:
autoencoder = Model(input_img, autoencoder(input_img))
autoencoder.compile(loss='mean_squared_error', optimizer = RMSprop())Mogelijk gemaakt door
Laten we de lagen die je in de bovenstaande stap hebt gemaakt visualiseren met de samenvattingsfunctie; deze toont het aantal parameters (gewichten en biases) in elke laag en ook het totaal aantal parameters in je model.
_________________________________________________________________
Layer(type) Output Shape Param #
=================================================================input_6(InputLayer)(None,28,28,1)0
_________________________________________________________________
conv2d_25(Conv2D)(None,28,28,32)320
_________________________________________________________________
max_pooling2d_9(MaxPooling2(None,14,14,32)0
_________________________________________________________________
conv2d_26(Conv2D)(None,14,14,64)18496
_________________________________________________________________
max_pooling2d_10(MaxPooling(None,7,7,64)0
_________________________________________________________________
conv2d_27(Conv2D)(None,7,7,128)73856
_________________________________________________________________
conv2d_28(Conv2D)(None,7,7,128)147584
_________________________________________________________________
up_sampling2d_9(UpSampling2(None,14,14,128)0
_________________________________________________________________
conv2d_29(Conv2D)(None,14,14,64)73792
_________________________________________________________________
up_sampling2d_10(UpSampling(None,28,28,64)0
_________________________________________________________________
conv2d_30(Conv2D)(None,28,28,1)577=================================================================
Total params:314,625
Trainable params:314,625
Non-trainable params:0
_________________________________________________________________
Mogelijk gemaakt door
Het is eindelijk tijd om het model te trainen met de fit()-functie van Keras! Het model traint 50 epochs. De fit()-functie retourneert een history-object; Door het resultaat hiervan op te slaan in fashion_train, kun je het later gebruiken om de verliesfunctie te plotten tussen training en validatie, wat je helpt om de prestaties van je model visueel te analyseren.
Train het model
autoencoder_train = autoencoder.fit(train_X, train_ground, batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(valid_X, valid_ground))Mogelijk gemaakt door
Eindelijk! Je hebt het model 50 epochs getraind op Not-MNIST. Laten we nu de verliesgrafiek tussen training en validatie plotten om de modelprestatie te visualiseren.
Training versus validatie-verliesdiagram
loss = autoencoder_train.history['loss']
val_loss = autoencoder_train.history['val_loss']
epochs =range(epochs)
plt.figure()
plt.plot(epochs, loss,'bo', label='Training loss')
plt.plot(epochs, val_loss,'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()Mogelijk gemaakt door
Je ziet dat de validatie- en trainingsverlies in de pas lopen. Dit toont aan dat je model niet overfit: de validatieverlies daalt en stijgt niet, en er is zelden een grote kloof tussen trainings- en validatieverlies.
Daarom kun je zeggen dat de generalisatiecapaciteit van je model goed is.
Tot slot is het tijd om de testafbeeldingen te reconstrueren met de functie predict() van Keras en te zien hoe goed je model in staat is om te reconstrueren op de testdata.
Voorspellen op testdata
Je laat het getrainde model voorspellen op alle 10.000 testafbeeldingen en plot een paar van de gereconstrueerde afbeeldingen om te visualiseren hoe goed je model de testafbeeldingen kan reconstrueren.
plt.figure(figsize=(20,4))print("Test Images")for i inrange(10):
plt.subplot(2,10, i+1)
plt.imshow(test_data[i,...,0], cmap='gray')
curr_lbl = test_labels[i]
plt.title("(Label: "+str(label_dict[curr_lbl])+")")
plt.show()
plt.figure(figsize=(20,4))print("Reconstruction of Test Images")for i inrange(10):
plt.subplot(2,10, i+1)
plt.imshow(pred[i,...,0], cmap='gray')
plt.show()Mogelijk gemaakt door
Uit de bovenstaande figuren kun je afleiden dat je model fantastisch werk heeft geleverd bij het reconstrueren van de testafbeeldingen die je met het model hebt voorspeld. Althans visueel gezien lijken de test- en gereconstrueerde afbeeldingen bijna exact op elkaar.
Denoising auto-encoder
Een denoising auto-encoder probeert een representatie (latente ruimte of bottleneck) te leren die robuust is tegen ruis. Je voegt ruis toe aan een afbeelding en voert vervolgens de ruisachtige afbeelding als input aan het encooder-gedeelte van je netwerk. Het encoder-gedeelte van de auto-encoder transformeert de afbeelding naar een andere ruimte die de letters probeert te behouden maar de ruis verwijdert.
Maar hoe verwijdert het de ruis precies?
Tijdens het trainen definieer je een verliesfunctie, vergelijkbaar met de root mean squared error die je eerder in de convolutionele auto-encoder had gedefinieerd. Bij elke iteratie van de training berekent het netwerk een verlies tussen de ruisachtige afbeelding die door de decoder wordt teruggegeven en de ground truth (denoisy-afbeelding) en probeert het dat verlies of verschil tussen de gereconstrueerde afbeelding en de originele ruisvrije afbeelding te minimaliseren. Met andere woorden: het netwerk leert een 7 x 7 x 128-ruimte die ruisvrije encodings van de data bevat waarop je het netwerk traint!
Implementatie van denoising auto-encoder
Om te zien hoe dit in Python werkt, gebruik je dezelfde NotMNIST-dataset als in het eerste deel van deze tutorial. Dat betekent dat je geen extra datapreprocessing hoeft te doen, want dat is al gedaan! Eén belangrijke preprocessingstap in dit deel is echter het toevoegen van ruis aan de train-, validatie- en testafbeeldingen. Laten we dat eerst snel doen!
Ruis toevoegen aan afbeeldingen
Laten we eerst een noise factor definiëren, een hyperparameter. De noise factor wordt vermenigvuldigd met een willekeurige matrix met een gemiddelde van 0,0 en standaarddeviatie van 1,0. Deze matrix trekt monsters uit een normale (Gaussische) verdeling. De vorm van de willekeurige normale array zal gelijk zijn aan de vorm van de data waaraan je de ruis toevoegt.
Ter vereenvoudiging: de variabele train_X heeft de vorm 48000 x 28 x 28 x 1. De willekeurige normale array zal dus ook een vorm hebben die lijkt op train_X; alleen dan kun je twee arrays optellen, omdat ze dan dezelfde dimensies hebben.
np.clip() zal alle negatieve waarden op nul afkappen en alle waarden groter dan één op één. Je wilt immers dat je pixelwaarden tussen nul en één liggen. En er is een kans dat na het introduceren van ruis in de data het bereik van pixelwaarden iets verandert, dus om veilig te zijn is het een goede gewoonte om de pixelwaarden te clippen.
De ruisachtige afbeeldingen visualiseren
plt.figure(figsize=[5,5])# Display the first image in training data
plt.subplot(121)
curr_img = np.reshape(x_train_noisy[1],(28,28))
plt.imshow(curr_img, cmap='gray')# Display the first image in testing data
plt.subplot(122)
curr_img = np.reshape(x_test_noisy[1],(28,28))
plt.imshow(curr_img, cmap='gray')Mogelijk gemaakt door
Nu je de ruisachtige data hebt, kun je die in het netwerk voeren en zien hoe de ruis "magisch" uit de afbeeldingen wordt verwijderd!
Denoising auto-encoder-netwerk
Zoals eerder besproken, is de auto-encoder verdeeld in twee delen: de encoder en de decoder. De architectuur die je gaat bouwen, ziet er als volgt uit:
Encoder
De eerste laag heeft 32-3 x 3-filters, gevolgd door een downsampling- (max-pooling-)laag,
De tweede laag heeft 64-3 x 3-filters, gevolgd door nog een downsampling-laag,
De laatste laag van de encoder heeft 128-3 x 3-filters.
Decoder
De eerste laag heeft 128-3 x 3-filters, gevolgd door een upsampling-laag,
De tweede laag heeft 64-3 x 3-filters, gevolgd door nog een upsampling-laag,
De laatste laag van de encoder heeft 1-3 x 3-filter.
batch_size =128
epochs =20
inChannel =1
x, y =28,28
input_img = Input(shape =(x, y, inChannel))Mogelijk gemaakt door
autoencoder = Model(input_img, autoencoder(input_img))
autoencoder.compile(loss='mean_squared_error', optimizer = RMSprop())Mogelijk gemaakt door
Trainen
Als je je herinnert: bij het trainen van de convolutionele auto-encoder voerde je de trainingsafbeeldingen twee keer in, omdat de input en de ground truth hetzelfde waren. Bij de denoising auto-encoder voer je echter de ruisachtige afbeeldingen als input, terwijl je ground truth de denoisy-afbeeldingen blijven waarop je de ruis had toegepast. Alleen dan kan het netwerk een verlies berekenen tussen de ruisachtige en de echte denoisy-afbeeldingen.
autoencoder_train = autoencoder.fit(x_train_noisy, train_X, batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(x_valid_noisy, valid_X))Mogelijk gemaakt door
loss = autoencoder_train.history['loss']
val_loss = autoencoder_train.history['val_loss']
epochs =range(epochs)
plt.figure()
plt.plot(epochs, loss,'bo', label='Training loss')
plt.plot(epochs, val_loss,'b', label='Validation loss')
plt.title('Training and validation loss')
plt.legend()
plt.show()Mogelijk gemaakt door
Uit de bovenstaande grafiek kun je afleiden dat het model bij sommige epochs overfit, terwijl het het grootste deel van de tijd in de pas loopt. Je kunt de prestaties van het model zeker proberen te verbeteren door er wat complexiteit aan toe te voegen zodat het verlies verder kan dalen; train het langer en beslis dan.
plt.figure(figsize=(20,4))print("Test Images")for i inrange(10,20,1):
plt.subplot(2,10, i+1)
plt.imshow(test_data[i,...,0], cmap='gray')
curr_lbl = test_labels[i]
plt.title("(Label: "+str(label_dict[curr_lbl])+")")
plt.show()
plt.figure(figsize=(20,4))print("Test Images with Noise")for i inrange(10,20,1):
plt.subplot(2,10, i+1)
plt.imshow(x_test_noisy[i,...,0], cmap='gray')
plt.show()
plt.figure(figsize=(20,4))print("Reconstruction of Noisy Test Images")for i inrange(10,20,1):
plt.subplot(2,10, i+1)
plt.imshow(pred[i,...,0], cmap='gray')
plt.show()Mogelijk gemaakt door
Het lijkt erop dat een vrij eenvoudige netwerkarchitectuur in slechts 20 epochs behoorlijk goed werk heeft geleverd bij het verwijderen van ruis uit de testafbeeldingen, of niet?
In de volgende tutorial leer je hoe je afbeeldingen from scratch inleest, analyseert, preprocesset en ze invoert in het model met behulp van een vingerafdrukdataset. Je leert ook hoe je medische beelden van T-1-modus inleest en reconstrueert met een auto-encoder!
Er is nog veel te behandelen, dus waarom zou je DataCamp's Deep Learning in Python-cursus niet volgen, als je dat nog niet hebt gedaan? Je leert vanaf de basis en groeit langzaam naar het beheersen van het deep learning-domein. Het zal ongetwijfeld een onmisbare bron zijn wanneer je leert werken met convolutionele neurale netwerken in Python, hoe je gezichten, objecten enz. detecteert.
In het algemeen kun je auto-encoders beschouwen als een unsupervised leertechniek, omdat je geen expliciete labels nodig hebt om het model te trainen. Alles wat je nodig hebt om een auto-encoder te trainen, is ruwe inputdata.
In deze tutorial leer je over auto-encoders in deep learning en implementeer je een convolutionele en denoising auto-encoder in Python met Keras. Je werkt met de NotMNIST-alfabetdataset als voorbeeld.
Kort samengevat behandel je vandaag de volgende onderwerpen:
Auto-encoder
Zoals je in de introductie las, is een auto-encoder een unsupervised machine learning-algoritme dat een afbeelding als input neemt en probeert deze te reconstrueren met minder bits vanuit de bottleneck, ook wel de latente ruimte genoemd. De afbeelding wordt bij de bottleneck grotendeels gecomprimeerd. De compressie in auto-encoders wordt bereikt door het netwerk een tijd te trainen; naarmate het leert, probeert het de inputafbeelding zo goed mogelijk te representeren in de bottleneck. Algemene beeldcompressie-algoritmen zoals JPEG en JPEG lossless comprimeren afbeeldingen zonder enige vorm van training en doen dat behoorlijk goed.
Auto-encoders lijken op technieken voor dimensiereductie zoals Principal Component Analysis (PCA). Ze projecteren data van een hogere dimensie naar een lagere dimensie met lineaire transformaties en proberen de belangrijke kenmerken van de data te behouden terwijl ze de niet-essentiële delen verwijderen.
Het belangrijkste verschil tussen auto-encoders en PCA zit echter in de transformatie: zoals je al las, gebruikt PCA lineaire transformaties, terwijl auto-encoders niet-lineaire transformaties gebruiken.
Nu je een beetje begrip hebt van auto-encoders, laten we de term opsplitsen en er wat intuïtie bij krijgen!
De bovenstaande afbeelding is een vanilla auto-encoder met twee lagen en één verborgen laag. In deep learning-terminologie zul je vaak merken dat de inputlaag niet wordt meegeteld bij het bepalen van het totale aantal lagen in een architectuur. Het totaal aantal lagen in een architectuur bestaat alleen uit het aantal verborgen lagen en de outputlaag.
Zoals in de afbeelding te zien is, hebben de input- en outputlagen hetzelfde aantal neuronen.
Neem een voorbeeld. Je voert een afbeelding met slechts vijf pixelwaarden in de auto-encoder, die door de encoder wordt gecomprimeerd naar drie pixelwaarden bij de bottleneck (middelste laag) of latente ruimte. Met deze drie waarden probeert de decoder de vijf pixelwaarden of eigenlijk de inputafbeelding te reconstrueren die je als input aan het netwerk hebt gegeven.
In de praktijk zitten er meer verborgen lagen tussen de input en de output.
Een auto-encoder kun je in drie delen opdelen
Er zijn verschillende soorten auto-encoders, zoals de convolutionele auto-encoder, denoising auto-encoder, variational auto-encoder en sparse auto-encoder. Zoals je in de introductie las, focus je in deze tutorial alleen op de convolutionele en denoising varianten.Convolutionele auto-encoders in Python met Keras
Omdat je inputdata uit afbeeldingen bestaat, is het een goed idee om een convolutionele auto-encoder te gebruiken. Het is geen auto-encoder-variant, maar eerder een traditionele auto-encoder met convolutionele lagen erbovenop: je vervangt in feite volledig verbonden lagen door convolutionele lagen. Convolutionele lagen, samen met max-pooling-lagen, zetten de input om van breed (een 28 x 28-afbeelding) en dun (één kanaal of grijswaarden) naar klein (7 x 7-afbeelding in de latente ruimte) en dik (128 kanalen).
Maak je geen zorgen als je het bovenstaande idee nog niet helemaal begrijpt! Het tweede deel van deze tutorial, waarin je focust op de implementatie hiervan, zal hopelijk al je twijfels wegnemen (als je die hebt!).
Tip: als je meer wilt weten over convolutionele neurale netwerken, bekijk dan deze tutorial.
Dit helpt het netwerk om visuele kenmerken uit de afbeeldingen te halen en zo een nauwkeurigere representatie in de latente ruimte te krijgen. Het reconstructieproces gebruikt upsampling en convoluties, die bekendstaan als een decoder. Het downsamplen is het proces waarin de afbeelding wordt gecomprimeerd naar een lage dimensie, ook wel een encoder genoemd.
Het is belangrijk om op te merken dat de encoder vooral de inputafbeelding comprimeert; bijvoorbeeld: als je inputafbeelding de afmeting 176 x 176 x 1 (~30976) heeft, dan kan het maximale compressiepunt een dimensie van 22 x 22 x 512 (~247808) hebben. In dit geval begon je met een grijswaardenafbeelding van 176 x 176 en door die door een paar convolutionele lagen en precies drie max-pooling-lagen te sturen, is je afbeelding uiteindelijk gedownsampeld naar een dimensie van 22 x 22, maar het aantal kanalen is toegenomen van 1 naar 512. Zoals hierboven vermeld, werd je input van breed (176 x 176) en dun (1) klein (22x22) en dik (512).
De data laden
De notMNIST-dataset is een beeldherkenningsdataset van lettertypeglyphs voor de letters A tot en met J. Ze lijkt sterk op de klassieke MNIST-dataset, die afbeeldingen bevat van handgeschreven cijfers 0 tot en met 9: in dit geval vind je dat de NotMNIST-dataset bestaat uit 28x28 grijswaardenafbeeldingen van 70.000 letters van A - J in totaal 10 categorieën, en 6.000 afbeeldingen per categorie.
Tip: als je wilt leren hoe je een Multi-Layer Perceptron (MLP) voor classificatietaken met de MNIST-dataset implementeert, bekijk dan deze tutorial.
De NotMNIST-dataset is niet vooraf gedefinieerd in het Keras- of TensorFlow-framework, dus je zult de data moeten downloaden van deze bron. De data wordt gedownload in
ubyte.gzip-formaat, maar maak je daar nog geen zorgen over! Je leert zo hoe je bytestream-formaten leest en ze omzet naar een NumPy-array. Laten we beginnen!Het netwerk wordt getraind op een Nvidia Tesla K40, dus als je op een GPU traint en Jupyter Notebook gebruikt, moet je drie extra regels code toevoegen waarin je de CUDA device order en CUDA visible devices specificeert met een module genaamd
os.In de onderstaande code stel je in feite omgevingsvariabelen in in de notebook met
os.environ. Het is goed om het volgende te doen vóór je Keras initialiseert, om de Keras-backend TensorFlow te beperken tot de eerste GPU. Als de machine waarop je traint een GPU op0heeft, gebruik dan0in plaats van1. Je kunt dat controleren door een eenvoudig commando in je terminal uit te voeren: bijvoorbeeldnvidia-smiVervolgens importeer je alle vereiste modules zoals
numpy,matplotliben vooralkeras, aangezien je dat framework in deze tutorial gebruikt!Hier definieer je een functie die het
gzip-bestand opent en het bestand leest metbytestream.read(). Je geeft de afbeeldingsdimensie en het totale aantal afbeeldingen door aan deze functie. Vervolgens zet je metnp.frombuffer()de string die is opgeslagen in variabelebufom naar een NumPy-array van typefloat32.Daarna vorm je de array om naar een driedimensionale array of tensor, waarbij de eerste dimensie het aantal afbeeldingen is en de tweede en derde dimensie de dimensies van de afbeelding zijn. Tot slot retourneer je de NumPy-array
data.Je roept nu de functie
extract_data()aan door de trainings- en testbestanden door te geven, samen met hun bijbehorende aantal afbeeldingen:Evenzo definieer je een functie om labels te extraheren die het
gzip-bestand opent en het bestand leest metbytestream.read(), waaraan je de labeldimensie (1) en het totale aantal afbeeldingen doorgeeft. Vervolgens zet je metnp.frombuffer()de string die is opgeslagen in variabelebufom naar een NumPy-array van typeint64.Dit keer hoef je de array niet te reshapen, omdat de variabele
labelseen kolomvector van dimensie 60.000 x 1 zal teruggeven. Tot slot retourneer je de NumPy-arraylabels.Je roept nu de functie voor het extraheren van labels aan door de trainings- en testlabelfiles door te geven, samen met hun bijbehorende aantal afbeeldingen:
Als je de trainings- en testdata eenmaal hebt geladen, ben je klaar om de data te analyseren om wat intuïtie te krijgen over de dataset waarmee je in deze tutorial gaat werken!
Data verkennen
Laten we nu analyseren hoe afbeeldingen in de dataset eruitzien en ook de dimensies van de afbeeldingen bekijken met behulp van het NumPy-arrayattribuut
.shape:Uit de bovenstaande output zie je dat de trainingsdata een vorm heeft van 60000 x 28 x 28, omdat er 60.000 trainingsvoorbeelden zijn, elk een matrix van 28 x 28. Evenzo heeft de testdata een vorm van 10000 x 28 x 28, omdat er 10.000 testvoorbeelden zijn.
Let op dat je in deze taak de trainings- en testlabels niet zult gebruiken. De taak gaat alleen over de trainings- en testafbeeldingen. Maar voor verkenningsdoeleinden, wat je een betere intuïtie over de data kan geven, maak je wel gebruik van de labels.
Laten we een woordenboek maken dat klassennamen met hun bijbehorende categorische klasselabels bevat:
Bekijk nu een paar afbeeldingen in je dataset:
De output van bovenstaande twee plots zijn een van de voorbeeldafbeeldingen uit zowel de trainings- als testdata, en deze afbeeldingen hebben respectievelijk een klasselabel
5ofFen3ofD. Op dezelfde manier hebben andere letters verschillende labels, maar vergelijkbare letters hebben hetzelfde label. Dit betekent dat alle 6.000 afbeeldingen van klasseFeen klasselabel5hebben.Data preprocessing
De afbeeldingen in de dataset zijn inderdaad grijswaardenafbeeldingen met pixelwaarden van 0 tot 255 en een dimensie van 28 x 28. Voordat je de data in het model voert, is het heel belangrijk om te preprocessen. Je zet eerst elke 28 x 28-afbeelding van de train- en testset om naar een matrix van 28 x 28 x 1, die je in het netwerk kunt voeren:
Controleer vervolgens het datatype van de trainings- en test-NumPy-arrays; dit moet float32 zijn. Zo niet, dan moet je het omzetten naar dit formaat, maar omdat je dat al hebt gedaan tijdens het inlezen van de data, hoeft dat nu niet meer. Je moet de pixelwaarden ook herschalen naar het bereik 0 - 1 inclusief. Laten we dat doen!
Vergeet niet de datatypes van de trainings- en testdata te verifiëren:
Herschalen van de trainings- en testdata met de maximale pixelwaarde van de trainings- en testdata:
Laten we verifiëren dat de maximale waarde van de train- en testdata 1,0 is na het herschalen!
Na dit alles is het belangrijk om de data op te splitsen. Om je model goed te laten generaliseren, splits je de trainingsdata in twee delen: een train- en een validatieset. Je traint je model op 80% van de data en valideert op 20% van de overgebleven trainingsdata.
Dit helpt ook om de kans op overfitting te verkleinen, omdat je je model valideert op data die het niet heeft gezien tijdens de trainingsfase.
Je kunt de module
train_test_splitvan scikit-learn gebruiken om de data goed te verdelen:Let op dat je voor deze taak geen trainings- en testlabels nodig hebt. Daarom geef je de trainingsafbeeldingen twee keer door. Je trainingsafbeeldingen fungeren zowel als input als als ground truth, vergelijkbaar met de labels die je hebt bij een classificatietaak.
Nu ben je klaar om het netwerk te definiëren en de data erin te voeren. Dus zonder verder oponthoud: door naar de volgende stap!
De convolutionele auto-encoder
De afbeeldingen hebben formaat 28 x 28 x 1 ofwel een 784-dimensionale vector. Je zet de afbeeldingsmatrix om naar een array, schaalt die tussen 0 en 1, vormt hem om naar 28 x 28 x 1 en voert dit als input aan het netwerk.
Ook gebruik je een batchgrootte van 128; een hogere batchgrootte van 256 of 512 is ook prima, het hangt af van het systeem waarop je je model traint. Dit draagt sterk bij aan het bepalen van de leerparameters en beïnvloedt de voorspellingsnauwkeurigheid. Je traint je netwerk 50 epochs.
Zoals eerder besproken, is de auto-encoder opgedeeld in twee delen: een encoder en een decoder.
Encoder
Decoder
De max-poolinglaag downsamplet de input telkens met een factor twee, terwijl de upsamplinglaag de input telkens met een factor twee upsamplet.
Let op: Het aantal filters, de filtergrootte, het aantal lagen, het aantal epochs waarop je je model traint: het zijn allemaal hyperparameters en moeten worden bepaald op basis van je eigen intuïtie. Je kunt vrij experimenteren door met deze hyperparameters te spelen en de prestaties van je model te meten. Zo leer je stap voor stap de kunst van deep learning!
Nadat het model is gemaakt, moet je het compileren met de optimizer RMSProp.
Tip: bekijk deze tutorial van Andrew Ng over RMSProp als je er meer over wilt weten.
Let op dat je ook het type verlies moet specificeren via het argument
loss. In dit geval is dat de mean squared error, omdat het verlies na elke batch wordt berekend tussen de batch met voorspelde output en de ground truth met behulp van mean squared error, pixel voor pixel:Laten we de lagen die je in de bovenstaande stap hebt gemaakt visualiseren met de samenvattingsfunctie; deze toont het aantal parameters (gewichten en biases) in elke laag en ook het totaal aantal parameters in je model.
Het is eindelijk tijd om het model te trainen met de
fit()-functie van Keras! Het model traint 50 epochs. Defit()-functie retourneert een history-object; Door het resultaat hiervan op te slaan in fashion_train, kun je het later gebruiken om de verliesfunctie te plotten tussen training en validatie, wat je helpt om de prestaties van je model visueel te analyseren.Train het model
Eindelijk! Je hebt het model 50 epochs getraind op Not-MNIST. Laten we nu de verliesgrafiek tussen training en validatie plotten om de modelprestatie te visualiseren.
Training versus validatie-verliesdiagram
Je ziet dat de validatie- en trainingsverlies in de pas lopen. Dit toont aan dat je model niet overfit: de validatieverlies daalt en stijgt niet, en er is zelden een grote kloof tussen trainings- en validatieverlies.
Daarom kun je zeggen dat de generalisatiecapaciteit van je model goed is.
Tot slot is het tijd om de testafbeeldingen te reconstrueren met de functie
predict()van Keras en te zien hoe goed je model in staat is om te reconstrueren op de testdata.Voorspellen op testdata
Je laat het getrainde model voorspellen op alle 10.000 testafbeeldingen en plot een paar van de gereconstrueerde afbeeldingen om te visualiseren hoe goed je model de testafbeeldingen kan reconstrueren.
Uit de bovenstaande figuren kun je afleiden dat je model fantastisch werk heeft geleverd bij het reconstrueren van de testafbeeldingen die je met het model hebt voorspeld. Althans visueel gezien lijken de test- en gereconstrueerde afbeeldingen bijna exact op elkaar.
Denoising auto-encoder
Een denoising auto-encoder probeert een representatie (latente ruimte of bottleneck) te leren die robuust is tegen ruis. Je voegt ruis toe aan een afbeelding en voert vervolgens de ruisachtige afbeelding als input aan het encooder-gedeelte van je netwerk. Het encoder-gedeelte van de auto-encoder transformeert de afbeelding naar een andere ruimte die de letters probeert te behouden maar de ruis verwijdert.
Maar hoe verwijdert het de ruis precies?
Tijdens het trainen definieer je een verliesfunctie, vergelijkbaar met de root mean squared error die je eerder in de convolutionele auto-encoder had gedefinieerd. Bij elke iteratie van de training berekent het netwerk een verlies tussen de ruisachtige afbeelding die door de decoder wordt teruggegeven en de ground truth (denoisy-afbeelding) en probeert het dat verlies of verschil tussen de gereconstrueerde afbeelding en de originele ruisvrije afbeelding te minimaliseren. Met andere woorden: het netwerk leert een 7 x 7 x 128-ruimte die ruisvrije encodings van de data bevat waarop je het netwerk traint!
Implementatie van denoising auto-encoder
Om te zien hoe dit in Python werkt, gebruik je dezelfde NotMNIST-dataset als in het eerste deel van deze tutorial. Dat betekent dat je geen extra datapreprocessing hoeft te doen, want dat is al gedaan! Eén belangrijke preprocessingstap in dit deel is echter het toevoegen van ruis aan de train-, validatie- en testafbeeldingen. Laten we dat eerst snel doen!
Ruis toevoegen aan afbeeldingen
Laten we eerst een noise factor definiëren, een hyperparameter. De noise factor wordt vermenigvuldigd met een willekeurige matrix met een gemiddelde van 0,0 en standaarddeviatie van 1,0. Deze matrix trekt monsters uit een normale (Gaussische) verdeling. De vorm van de willekeurige normale array zal gelijk zijn aan de vorm van de data waaraan je de ruis toevoegt.
Ter vereenvoudiging: de variabele
train_Xheeft de vorm 48000 x 28 x 28 x 1. De willekeurige normale array zal dus ook een vorm hebben die lijkt optrain_X; alleen dan kun je twee arrays optellen, omdat ze dan dezelfde dimensies hebben.np.clip()zal alle negatieve waarden op nul afkappen en alle waarden groter dan één op één. Je wilt immers dat je pixelwaarden tussen nul en één liggen. En er is een kans dat na het introduceren van ruis in de data het bereik van pixelwaarden iets verandert, dus om veilig te zijn is het een goede gewoonte om de pixelwaarden te clippen.De ruisachtige afbeeldingen visualiseren
Nu je de ruisachtige data hebt, kun je die in het netwerk voeren en zien hoe de ruis "magisch" uit de afbeeldingen wordt verwijderd!
Denoising auto-encoder-netwerk
Zoals eerder besproken, is de auto-encoder verdeeld in twee delen: de encoder en de decoder. De architectuur die je gaat bouwen, ziet er als volgt uit:
Encoder
Decoder
Trainen
Als je je herinnert: bij het trainen van de convolutionele auto-encoder voerde je de trainingsafbeeldingen twee keer in, omdat de input en de ground truth hetzelfde waren. Bij de denoising auto-encoder voer je echter de ruisachtige afbeeldingen als input, terwijl je ground truth de denoisy-afbeeldingen blijven waarop je de ruis had toegepast. Alleen dan kan het netwerk een verlies berekenen tussen de ruisachtige en de echte denoisy-afbeeldingen.
Train versus validatie-verliesdiagram
Uit de bovenstaande grafiek kun je afleiden dat het model bij sommige epochs overfit, terwijl het het grootste deel van de tijd in de pas loopt. Je kunt de prestaties van het model zeker proberen te verbeteren door er wat complexiteit aan toe te voegen zodat het verlies verder kan dalen; train het langer en beslis dan.
Voorspellen op de testdataset
Het lijkt erop dat een vrij eenvoudige netwerkarchitectuur in slechts 20 epochs behoorlijk goed werk heeft geleverd bij het verwijderen van ruis uit de testafbeeldingen, of niet?
Ga verder!
Deze tutorial was een goede start om auto-encoders zowel theoretisch als praktisch te begrijpen. Als je het makkelijk kon volgen of zelfs met een beetje extra moeite: goed gedaan! Bekijk DataCamp's Keras Tutorial: Deep Learning in Python-tutorial en Introduction to Deep Learning in Python-cursus.
In de volgende tutorial leer je hoe je afbeeldingen from scratch inleest, analyseert, preprocesset en ze invoert in het model met behulp van een vingerafdrukdataset. Je leert ook hoe je medische beelden van T-1-modus inleest en reconstrueert met een auto-encoder!
Er is nog veel te behandelen, dus waarom zou je DataCamp's Deep Learning in Python-cursus niet volgen, als je dat nog niet hebt gedaan? Je leert vanaf de basis en groeit langzaam naar het beheersen van het deep learning-domein. Het zal ongetwijfeld een onmisbare bron zijn wanneer je leert werken met convolutionele neurale netwerken in Python, hoe je gezichten, objecten enz. detecteert.