.. _chap-tpDeepLearning5: ############################################################################## Travaux pratiques - Deep Learning : transfert et fine-tuning ############################################################################## Pour illustrer le principe du transfert avec les réseaux profonds, on va s'intéresser à une tâche de visualisation. Comme vu dans le TP 4 avec la t-SNE, il va s'agir de projeter les représentations internes apprises par les réseaux de neurones dans un espace 2D. Exercice 1 : Transfert *********************************************** On va commencer par charger un Perceptron qui a été entraîné sur la base MNIST au TP 4 : vous pouvez récupérer l'architecture ici ``_ et les poids ici ``_. Commencer par charger ce modèle : .. code-block:: python model = loadModel("MLP_100") Vous pouvez vérifier l'architecture du réseau avec la méthode ``summary()`` et vérifier les performances du modèle après l'avoir compilé (on doit obtenir des performances en test légèrement inférieures à 98%). On va maintenant chercher à apprendre, à partir des représentations interne de la couche caché du Perceptron, un réseau de neurone capable de projeter les données en 2D. On va pour cela : - Supprimer la couche de sortie vers les classes du réseau : .. code-block:: python model.pop() - On va ensuite ajouter deux couches complètement connectées suivies d'une fonction d'activation de type sigmoïde. On choisira des couches de taille décroissante pour arriver à 2, par exemple : .. code-block:: python model.add(Dense(nbHidden, activation='sigmoid')) model.add(Dense(2, activation='sigmoid')) - Enfin on ajoutera une couche complètement connectée vers les classes de sorties (taille 10), avec une fonction d'activation de type ``softmax``. On veut maintenant entraîner les couches nouvellement ajoutées au réseau, en conservant les poids sur la première couche. On peut avec ``Keras`` indiquer pour chaque couche si elle est "entraînable" de la manière suivante : .. code-block:: python model.layers[i].trainable = False Vous pouvez à nouveau utiliser la fonction ``summary()`` pour vérifier la nouvelle architecture définie et le nombre de paramètres à apprendre du réseau. **On va maintenant apprendre le nouveau modèle et le sauvegarder** - Compiler le modèle en lui passant les paramètres habituels pour une tâche de classification : .. code-block:: python model.compile(loss='categorical_crossentropy',optimizer=sgd,metrics=['accuracy']) - Utiliser la méthode ``fit`` sur la base d'apprentissage pour optimiser le modèle - Utiliser la méthode ``saveModel`` pour sauver le modèle Maintenant, on va dans un script ``visuNN.py`` charger le modèle précédemment appris et visualiser le résultat de l'application de ce réseau **sur la base de test de MNIST** : - Charger le modèle avec ``loadModel`` - Supprimer la couche des classes de sortie avec ``pop()`` - Extraire les features de la dernière couche pour les images de la base de test avec la méthode ``predict()`` - Calculer les métriques de séparation des classes du TP 4 : .. code-block:: python # Computing convex hulls convex_hulls= convexHulls(h3, y_test) # Computing best fitting ellipses ellipses = best_ellipses(h3, y_test) # Computing Neighborhood Hit nh = neighboring_hit(h3, y_test) - Visualisation des données : utiliser la méthode ``visualization(h3, y_test, convex_hulls, ellipses , laodName , nh)`` Voici le type de visualisation que vous devez obtenir : .. image:: img/MLP_100_10_2.png :width: 300px :align: center .. admonition:: Question : Que pensez-vous de la séparabilité des classes, *e.g.* métrique NH, obtenue avec cette méthode et la t-SNE du TP 4 ? Quelles sont les différences importantes en terme d'apprentissage entre les deux méthodes ? Exercice 2 : Fine-tuning *********************************************** On va maintenant renouveler l'exercice 1, mais en cherchant à raffiner la première couche complètement connectée du réseau pour coller à la tâche cible. .. image:: img/MLP_100_10_2_FT.png :width: 300px :align: center Exercice 3 : Transfert et Fine-tuning sur notMNIST **************************************************** On va maintenant s'intéresser à utliser un modèle appris sur la base MNIST pour la tester sur la base notMNIST : ``_. On peut télécharger la base ici : ``_, et l'ouvrir avec le code suivant : .. code-block:: python from scipy import io # load data data = io.loadmat("notMNIST_small.mat") # transform data X = data['images'] y = data['labels'] # Change init tensor size of (28, 28, 18724) => (18724, 28, 28) X = np.transpose(X, (2, 0, 1)) y = y.astype('int32') X = X.astype('float32') / 255. On peut visualiser les 20 premières images de chaque classe ainsi : .. code-block:: python Yc = [0 for i in range(10)] for k in range(10): Yc[k] = np.where(y==k)[0] for i in range(10): for j in range(20): plt.subplot(10,20,i*20+j+1) plt.imshow(X[Yc[i][j],:], cmap='gray') plt.axis('off') plt.show() On va maintenant charger un réseau convolutif entraîné sur la base MNIST, que vous pouvez télécharger ici : ``_ et les poids ici ``_. Vous pouvez observer l'architecture du réseau avec la méthode ``summary()``. On demande maintenant d'appeler trois fois la méthode ``pop()`` et d'ajouter les couches suivantes au réseau : .. code-block:: python nb_classes=10 model.add(Dense(100, activation='relu', name='belastfc')) model.add(Dense(100, activation='relu', name='lastfc')) model.add(Dense(nb_classes, activation='softmax', name='finalfc')) for i in range(freeze_limit): model.layers[i].trainable = False .. admonition:: Question : Pourquoi choisir d'extraire les feature de MNIST à ce niveau ? On demande maintenant d'entraîner le mondèle sur la base notMNIST (après permutation aléatoire des exemples) : .. code-block:: python from sklearn.model_selection import train_test_split # Reshape to (18724, 28, 28,1) X = X.reshape(X.shape[0], 28, 28, 1) ratio_test_train = 0.2 X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=ratio_test_train, random_state=42) model.compile(loss='categorical_crossentropy',optimizer='sgd',metrics=['accuracy']) model.fit(X_trainfinal, Y_trainfinal, epochs=50,batch_size=100) scores = model.evaluate(X_testfinal, Y_testfinal, verbose=0) print("%s: %.2f%%" % (model.metrics_names[1], scores[1]*100)) Quelles performanes obtenez vous sur la base de test ? Renouvelez l'expérience mais sans geler les couches précédentes (fine-tuning complet du réseau). Conclure. .. L'objectif de ce TME est d’illustrer les réseaux de neurones convolutifs appris sur des bases large échelle, *e.g.* ImageNet, afin de fournir des descripteurs visuels (Deep Features, DF) permettant de représenter le .. contenu visuel d'images dans d'autres domaines ou contexte. .. On étudiera également la possibilité de pouvoir raffiner ces Deep Features à la tache cible considérée, *i.e.* problème de fine-tuning. .. Exercice 1 : Extraction de Deep Features .. *********************************************** .. Exercice 2 : Evaluation des Deep Features en transfert .. ******************************************************* .. Exercice 3 : Fine-tuning .. ***********************************************