{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"name":"Άσκηση 12 - Αυτοκωδικοποιητές (solution).ipynb","provenance":[],"authorship_tag":"ABX9TyPG4JdvwWlUcbJuSLbKoBpm"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["# Άσκηση 12 - Αυτοκωδικοποιητές"],"metadata":{"id":"XUYD9Eb-V4V4"}},{"cell_type":"markdown","source":["## 1. Εισαγωγή"],"metadata":{"id":"0o_C1YfsV7XF"}},{"cell_type":"markdown","source":["### 1.α. Βιβλιοθήκες"],"metadata":{"id":"GuX4wzlsWJc3"}},{"cell_type":"code","source":["from tensorflow.keras import regularizers\n","from tensorflow.keras.datasets import mnist\n","from tensorflow.keras.layers import Input, Dense\n","from tensorflow.keras.models import Sequential\n","from sklearn.preprocessing import MinMaxScaler\n","from sklearn.metrics.pairwise import cosine_similarity\n","\n","import matplotlib.pyplot as plt\n","import numpy as np\n","import pandas as pd\n","\n","# Θέτουμε σπορά (seed) στη γεννήτρια ψευδο-τυχαίων αριθμών για να λάβουμε\n","# ίδια αποτελέσματα\n","\n","np.random.seed(2022)"],"metadata":{"id":"eyWBldddWDOH"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### 1.β. Βοηθητικές συναρτήσεις"],"metadata":{"id":"pDjitfzyWaMK"}},{"cell_type":"code","source":["def compare_digits(test, decoded, n=10):\n"," plt.figure(figsize=(20, 4))\n"," for i in range(n):\n"," # display original\n"," ax = plt.subplot(2, n, i + 1)\n"," plt.imshow(test[i].reshape(28, 28))\n"," plt.gray()\n"," ax.get_xaxis().set_visible(False)\n"," ax.get_yaxis().set_visible(False)\n","\n"," # display reconstruction\n"," ax = plt.subplot(2, n, i + 1 + n)\n"," plt.imshow(decoded[i].reshape(28, 28))\n"," plt.gray()\n"," ax.get_xaxis().set_visible(False)\n"," ax.get_yaxis().set_visible(False)\n"," plt.show()\n"," \n"," \n","def display_digits(data, n=10):\n"," plt.figure(figsize=(20, 2))\n"," for i in range(n):\n"," ax = plt.subplot(1, n, i + 1)\n"," plt.imshow(data[i].reshape(28, 28))\n"," plt.gray()\n"," ax.get_xaxis().set_visible(False)\n"," ax.get_yaxis().set_visible(False)\n"," plt.show()"],"metadata":{"id":"K__51EpNWgfZ"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["### 1.γ. Δεδομένα"],"metadata":{"id":"QRMXTfHsWOs4"}},{"cell_type":"code","source":["(x_train, _), (x_test, _) = mnist.load_data()\n","\n","x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:])))\n","x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))\n","\n","scaler = MinMaxScaler()\n","x_train = scaler.fit_transform(x_train)\n","x_test = scaler.fit_transform(x_test)\n","\n","print(x_train.shape)\n","print(x_test.shape)"],"metadata":{"id":"gE-pw6QBWDV7"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["## 2. Υποπλήρης Αυτοκωδικοποιητής\n","\n","Βάση εργασίας αποτελεί ο υποπλήρης αυτοκωδικοποιητής που δείξαμε στο εργαστήριο"],"metadata":{"id":"VkI2cDP4WusC"}},{"cell_type":"markdown","source":["### 2.1. Αντιστρέψετε τις συναρτήσεις (απο)κωδικοποίησης. Τι παρατηρείτε;\n"],"metadata":{"id":"caHTDwzcXADX"}},{"cell_type":"code","source":["dim_x = 28*28\n","dim_h = 32\n","\n","autoencoder = Sequential([\n"," Dense(dim_h, activation='sigmoid', input_shape=(dim_x,)),\n"," Dense(dim_x, activation='relu')\n","])\n","\n","\n","autoencoder.compile(optimizer='adam', loss='binary_crossentropy')\n","\n","autoencoder.fit(x_train, x_train,\n"," epochs=20,\n"," batch_size=64,\n"," shuffle=True,\n"," validation_data=(x_test, x_test))"],"metadata":{"id":"jvhsjSIgW-_o"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Παρατηρούμε ότι αντιστρέφοντας τις συναρτήσεις ενεργοποίησης (χρησιμοποιώντας σιγμοειδή στον κωδικοποιητή αντί του αποκωδικοποιητή και relu στον αποκωδικοποιητή αντί του κωδικοποιητή) τα σφάλματα εκπαίδευσης και επαλήθευσης είναι αρκετά πιο μεγάλα σε σύγκριση με τα αντίστοιχα που είχαμε επιτύχει στο εργαστήριο (γύρω στο $0.40$ αντί του $0.09$).\n","\n","Ας εξετάσουμε τι επίδραση έχει στην ποιότητα των αναδημιουργημένων εικόνων."],"metadata":{"id":"zYtLr1twXLVN"}},{"cell_type":"code","source":["encoder = Sequential([\n"," autoencoder.layers[-2]\n","])\n","\n","decoder = Sequential([\n"," autoencoder.layers[-1]\n","])\n","\n","h = encoder.predict(x_test)\n","x_test_out = decoder.predict(h)\n","\n","compare_digits(x_test, x_test_out)"],"metadata":{"id":"1j2AkPeEbw7Q"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Παρατηρούμε ότι σε σύγκριση με τις αντίστοιχες εικόνες του υποπλήρη αυτοκωδικοποιητή του εργαστηρίου, εδώ η ποιότητα έχει σαφώς χειροτερεύσει (εισαγωγή artifacts κλπ). Συνεπώς οι παράμετροι και των δύο δικτύων παίζουν πολύ μεγάλο ρόλο στη συνολική απόδοση του αυτοκωδικοποιητή."],"metadata":{"id":"Uc83sXRLcYTc"}},{"cell_type":"markdown","source":["### 2.2. Χρησιμοποιείστε την ίδια συνάρτηση κωδικοποίησης και αποκωδικοποίησης (λχ τη relu). Τι παρατηρείτε;"],"metadata":{"id":"YOY6fFK1XLpu"}},{"cell_type":"code","source":["autoencoder = Sequential([\n"," Dense(dim_h, activation='relu', input_shape=(dim_x,)),\n"," Dense(dim_x, activation='relu')\n","])\n","\n","\n","autoencoder.compile(optimizer='adam', loss='binary_crossentropy')\n","\n","autoencoder.fit(x_train, x_train,\n"," epochs=20,\n"," batch_size=64,\n"," shuffle=True,\n"," validation_data=(x_test, x_test))"],"metadata":{"id":"f0hFjvT1XO8E"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Παρατηρούμε πως και σε αυτή την περίπτωση το σφάλμα εκπαίδευσης είναι μεγαλύτερο από τον υποπλήρη αυτοκωδικοποιητή που δείξαμε στο εργαστήριο (περίπου το διπλάσιο). Έτσι όπως είναι σχεδιασμένο το δίκτυο, δεν υπάρχει κάποιος μηχανισμός που να το αποτρέπει από το να αντιγράφει την είσοδό του στην έξοδό του, με αποτέλεσμα να μην αποτυπώνει τα χαρακτηριστικά της εισόδου του στον λανθάνοντα χώρο, σε ικανοποιητικό βαθμό.\n","\n","Όπως και στην προηγούμενη περίπτωση, ας εξετάσουμε την επίδραση του δικτύου στις αναδημιουργούμενες εικόνες."],"metadata":{"id":"7kBqcCHpXUtq"}},{"cell_type":"code","source":["encoder = Sequential([\n"," autoencoder.layers[-2]\n","])\n","\n","decoder = Sequential([\n"," autoencoder.layers[-1]\n","])\n","\n","h = encoder.predict(x_test)\n","x_test_out = decoder.predict(h)\n","\n","compare_digits(x_test, x_test_out)"],"metadata":{"id":"ojvffxaiiewW"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Και σε αυτή την περίπτωση, η ποιότητα έχει σαφώς χειροτερεύσει (θόλωμα, artifacts κλπ). Συνεπώς, είναι σημαντικό να σχεδιάζουμε δίκτυα αυτοκωδικοποίησης που μπορούν να μαθαίνουν τα χαρακτηριστικά της εισόδου τους."],"metadata":{"id":"IO67H3MJifDm"}},{"cell_type":"markdown","source":["## 3. Αραιός Αυτοκωδικοποιητής\n","\n","Βάση εργασίας αποτελεί ο αραιός αυτοκωδικοποιητής που δείξαμε στο εργαστήριο"],"metadata":{"id":"4E9T9I8YXyJW"}},{"cell_type":"markdown","source":["### 3.1. Δοκιμάστε να αυξήσετε το βάρος της ποινής αραιότητας. Τι παρατηρείτε;"],"metadata":{"id":"kGwWOwsIX-IO"}},{"cell_type":"markdown","source":["Ας αυξήσουμε το βάρος της ποινής αραιότητας κατά 100, δηλαδή επιλέγοντας $\\lambda=0.01$"],"metadata":{"id":"DeugySFNkGEZ"}},{"cell_type":"code","source":["sparse_autoencoder = Sequential([\n"," Dense(dim_h, activation='relu', \n"," activity_regularizer=regularizers.l1(0.01), \n"," input_shape=(dim_x,)),\n"," Dense(dim_x, activation='sigmoid')\n","])\n","\n","\n","sparse_autoencoder.compile(optimizer='adam', loss='binary_crossentropy')\n","\n","sparse_autoencoder.fit(x_train, x_train,\n"," epochs=30,\n"," batch_size=64,\n"," shuffle=True,\n"," validation_data=(x_test, x_test))"],"metadata":{"id":"OVtNaAaoYGYX"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Παρατηρούμε πως τα σφάλματα εκπαίδευσης και ελέγχου, ενώ αρχικά μειώνονται, πολύ γρήγορα σταθεροποιούνται σε μια σχετικά μεγάλη τιμή (τουλάχιστον διπλάσια από την αντίστοιχη που είχαμε πετύχει στο εργαστήριο), δείγμα του ότι η εκπαίδευση \"κολλάει\" σε κάποια τοπικά βέλτιστη λύση.\n","\n","Στη συνέχεια θα εξετάσουμε την επίδραση του δικτύου στις αναδημιουργούμενες εικόνες."],"metadata":{"id":"nQlsoAHvYHFZ"}},{"cell_type":"code","source":["sparse_encoder = Sequential([\n"," sparse_autoencoder.layers[-2]\n","])\n","\n","sparse_decoder = Sequential([\n"," sparse_autoencoder.layers[-1]\n","])\n","\n","h_sparse = sparse_encoder.predict(x_test)\n","x_test_out_sparse = sparse_decoder.predict(h_sparse)\n","\n","compare_digits(x_test, x_test_out_sparse)"],"metadata":{"id":"4rhBRqlwlBcG"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Παρατηρούμε ότι η ποιότητα των εικόνων είναι πάρα πολύ κακή (μια θολή μουντζούρα, ίδια για όλα τα ψηφία). Συνεπώς, αν δεν επιλεγεί ορθά το εύρος της ποινής αραιότητας, βλέπουμε πως όχι μόνο δεν βελτιώνεται η απόδοση του δικτύου, αλλά αντίθετα χειροτερεύει."],"metadata":{"id":"k0uDjMcXlLpw"}},{"cell_type":"markdown","source":["## 4. Αυτοκωδικοποιητής απαλοιφής θορύβου\n","\n","Βάση εργασίας αποτελεί ο αραιός αυτοκωδικοποιητής που δείξαμε στο εργαστήριο."],"metadata":{"id":"JDSzQ1ZFYJ60"}},{"cell_type":"markdown","source":["### 4.1. Δοκιμάστε να μεταβάλλετε (αυξήσετε/μειώσετε) το συντελεστή θορύβου. Τι παρατηρείτε;"],"metadata":{"id":"G62OTVTvYuAF"}},{"cell_type":"markdown","source":["Ας διπλασιάσουμε τον συντελεστή θορύβου στο $0.6$"],"metadata":{"id":"GywhqIMLln5o"}},{"cell_type":"code","source":["noise_factor = 0.6\n","x_train_noisy = x_train + noise_factor * np.random.normal(loc=0.0, scale=1.0, \n"," size=x_train.shape) \n","x_test_noisy = x_test + noise_factor * np.random.normal(loc=0.0, scale=1.0, \n"," size=x_test.shape) \n","\n","x_train_noisy = np.clip(x_train_noisy, 0., 1.)\n","x_test_noisy = np.clip(x_test_noisy, 0., 1.)\n","\n","noisy_autoencoder = Sequential([\n"," Dense(dim_h, activation='relu', input_shape=(dim_x,)),\n"," Dense(dim_x, activation='sigmoid')\n","])\n","\n","\n","noisy_autoencoder.compile(optimizer='adam', loss='binary_crossentropy')\n","\n","noisy_autoencoder.fit(x_train_noisy, x_train,\n"," epochs=30,\n"," batch_size=64,\n"," shuffle=True,\n"," validation_data=(x_test, x_test))"],"metadata":{"id":"lpFaMpNwYo6F"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Παρατηρούμε ότι τα σφάλματα εκπαίδευσης και επαλήθευσης είναι ελαφρώς χειρότερα σε σύγκριση με τις τιμές που παρατηρήθηκαν στο εργαστήριο, παρά τον διπλασιασμό του συντελεστή θορύβου.\n","\n","Για να δούμε και την επίδρασή του στις παραγόμενες εικόνες."],"metadata":{"id":"1bDYJAD5Y1Px"}},{"cell_type":"code","source":["noisy_encoder = Sequential([\n"," noisy_autoencoder.layers[-2]\n","])\n","\n","noisy_decoder = Sequential([\n"," noisy_autoencoder.layers[-1]\n","])\n","\n","h_noisy = noisy_encoder.predict(x_test_noisy)\n","x_test_out_noisy = noisy_decoder.predict(h_noisy)\n","compare_digits(x_test_noisy, x_test_out_noisy)"],"metadata":{"id":"-AboSf-hmOKc"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Παρότι ο θόρυβος που προστέθηκε ήταν πολύς σε ποσότητα, κάνοντας τα ψηφία σχεδόν μη-αναγνωρίσιμα στο ανθρώπινο μάτι, εντούτοις ο αποκωδικοποιητής απαλοιφής θορύβου κατόρθωσε να τα ανακτήσει σε πολύ ικανοποιητικό βαθμό (είναι μοναχά λίγο πιο θολά από τα αντίστοιχα του αυτοκωδικοποιητή απαλοιφής θορύβου που δείξαμε στο εργαστήριο)."],"metadata":{"id":"YtDUIvPon1Jd"}},{"cell_type":"markdown","source":["## 5. Βαθύς αυτοκωδικοποιητής\n","\n","Βάση εργασίας αποτελεί ο βαθύς αυτοκωδικοποιητής που δείξαμε στο εργαστήριο."],"metadata":{"id":"EHREpqKEY1zf"}},{"cell_type":"markdown","source":["### 5.1. Δοκιμάστε να χρησιμοποιήσετε διαφορετικές συναρτήσεις στο επίπεδο αποκωδικοποίησης. Τι παρατηρείτε;"],"metadata":{"id":"JXJvzjwZZGP5"}},{"cell_type":"markdown","source":["Θα αντικαταστήσουμε τις ημιγραμμικές συναρτήσεις ενεργοποίησης του επιπέδου αποκωδικοποίησης με σιγμοειδείς. "],"metadata":{"id":"FAYfzvQ3osHl"}},{"cell_type":"code","source":["layer1_dim = 128\n","layer2_dim = 64\n","\n","deep_autoencoder = Sequential([\n"," Dense(layer1_dim, activation='relu', input_shape=(dim_x,)),\n"," Dense(layer2_dim, activation='relu'),\n"," Dense(dim_h, activation='relu'),\n"," \n"," Dense(layer2_dim, activation='sigmoid'),\n"," Dense(layer1_dim, activation='sigmoid'),\n"," Dense(dim_x, activation='sigmoid')\n","])\n","\n","\n","deep_autoencoder.compile(optimizer='adam', loss='binary_crossentropy')\n","\n","deep_autoencoder.fit(x_train, x_train,\n"," epochs=30,\n"," batch_size=64,\n"," shuffle=True,\n"," validation_data=(x_test, x_test))"],"metadata":{"id":"J20qKJQmZAA_"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Τα σφάλματα εκπαίδευσης και ελέγχου είναι ελαφρώς χειρότερα σε αυτή την περίπτωση. Ας δούμε και τις παραγόμενες εικόνες"],"metadata":{"id":"RZlpMhpVZAkn"}},{"cell_type":"code","source":["deep_encoder = Sequential([\n"," deep_autoencoder.layers[0],\n"," deep_autoencoder.layers[1],\n"," deep_autoencoder.layers[2]\n","])\n","\n","deep_decoder = Sequential([\n"," deep_autoencoder.layers[-3],\n"," deep_autoencoder.layers[-2],\n"," deep_autoencoder.layers[-1]\n","])\n","\n","h_deep = deep_encoder.predict(x_test)\n","x_test_out_deep = deep_decoder.predict(h_deep)\n","compare_digits(x_test, x_test_out_deep)"],"metadata":{"id":"lphjR-_5p5n-"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Οι διαφορές είναι πολύ μικρές σε σύγκριση με το αντίστοιχο δίκτυο που δείξαμε στο εργαστήριο. Ωστόσο παρατηρούμε πως ορισμένα ψηφία είναι λίγο περισσότερο θολά."],"metadata":{"id":"JodW92l_qWPh"}}]}