{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\n\n# standard imports\nimport numpy as np \nimport pandas as pd\nimport matplotlib.pyplot as plte\n%matplotlib inline\nimport tensorflow as tf\nimport tensorflow_hub as hub\n\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-06-11T15:44:19.204515Z","iopub.execute_input":"2021-06-11T15:44:19.205082Z","iopub.status.idle":"2021-06-11T15:44:21.967521Z","shell.execute_reply.started":"2021-06-11T15:44:19.205048Z","shell.execute_reply":"2021-06-11T15:44:21.966386Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Je télécharge ma donnée et la regarde en détail","metadata":{}},{"cell_type":"code","source":"labels_csv = pd.read_csv('/kaggle/input/dog-breed-identification/labels.csv')\nprint(labels_csv.describe())\nprint(labels_csv.head())","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:21.969058Z","iopub.execute_input":"2021-06-11T15:44:21.969390Z","iopub.status.idle":"2021-06-11T15:44:22.014083Z","shell.execute_reply.started":"2021-06-11T15:44:21.969356Z","shell.execute_reply":"2021-06-11T15:44:22.012999Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Je peux voir que j'ai 120 races de chien pour 10 222 photos. ","metadata":{}},{"cell_type":"code","source":"labels_csv[\"breed\"].value_counts().plot.bar(figsize=(20, 5));","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:22.017245Z","iopub.execute_input":"2021-06-11T15:44:22.017597Z","iopub.status.idle":"2021-06-11T15:44:24.030753Z","shell.execute_reply.started":"2021-06-11T15:44:22.017563Z","shell.execute_reply":"2021-06-11T15:44:24.029718Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Dans le schéma ci-dessus, on peut observer qu'il y a plus de 60 images pour chaque race de chien. C'est une bonne quantité, car pour certains de leurs produits de vision, Google recommande un minimum de 10 images par classe pour commencer. ","metadata":{}},{"cell_type":"markdown","source":"Il est temps de récupérer les images et leurs étiquettes\n\nPuisque nous avons les ID des images et leurs étiquettes dans un DataFrame (labels_csv), nous allons l'utiliser pour créer :\n\n* 1) Une liste de chemins d'accès aux images d'entraînement\n* 2) Un tableau de toutes les étiquettes\n* 3) Un tableau de toutes les étiquettes uniques\n\nNous allons seulement créer une liste de chemins d'accès aux images plutôt que de les importer toutes pour commencer. En effet, il est beaucoup plus efficace de travailler avec des chemins de fichiers (chaînes de caractères) qu'avec des images.\n\nComme nous l'utiliserons à plusieurs reprises, nous enregistrerons le chemin d'accès à nos fichiers d'entraînement dans une variable train_path.","metadata":{}},{"cell_type":"code","source":"# Define our training file path \ntrain_path = \"../input/dog-breed-identification/train/\"","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.032316Z","iopub.execute_input":"2021-06-11T15:44:24.032645Z","iopub.status.idle":"2021-06-11T15:44:24.036633Z","shell.execute_reply.started":"2021-06-11T15:44:24.032611Z","shell.execute_reply":"2021-06-11T15:44:24.035601Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create pathnames from image ID's\nfilenames = [train_path + fname + \".jpg\" for fname in labels_csv[\"id\"]]\n\n# Check the first 10 filenames\nfilenames[:10]","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.038313Z","iopub.execute_input":"2021-06-11T15:44:24.038756Z","iopub.status.idle":"2021-06-11T15:44:24.058481Z","shell.execute_reply.started":"2021-06-11T15:44:24.038712Z","shell.execute_reply":"2021-06-11T15:44:24.057462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Maintenant que nous avons une liste de tous les noms de fichiers de la colonne ID de labels_csv, nous pouvons la comparer au nombre de fichiers dans notre répertoire de données d'entraînement pour voir s'ils correspondent.","metadata":{"execution":{"iopub.status.busy":"2021-06-09T08:44:34.703357Z","iopub.execute_input":"2021-06-09T08:44:34.703941Z","iopub.status.idle":"2021-06-09T08:44:34.710065Z","shell.execute_reply.started":"2021-06-09T08:44:34.703893Z","shell.execute_reply":"2021-06-09T08:44:34.708592Z"}}},{"cell_type":"code","source":"if len(os.listdir('/kaggle/input/dog-breed-identification/train/')) == len(filenames):\n    print('Number of file matches number of actual images!')\nelse:\n    print('Number of file doesnot matches number of actual images!!')","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.059984Z","iopub.execute_input":"2021-06-11T15:44:24.060378Z","iopub.status.idle":"2021-06-11T15:44:24.075206Z","shell.execute_reply.started":"2021-06-11T15:44:24.060331Z","shell.execute_reply":"2021-06-11T15:44:24.074000Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Je retrouve une image par son id\nlabels_csv['breed'][900]","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.076781Z","iopub.execute_input":"2021-06-11T15:44:24.077091Z","iopub.status.idle":"2021-06-11T15:44:24.083451Z","shell.execute_reply.started":"2021-06-11T15:44:24.077060Z","shell.execute_reply":"2021-06-11T15:44:24.082201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Je regarde l'image directement\nfrom IPython.display import display, Image\nImage(filenames[900])","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.086705Z","iopub.execute_input":"2021-06-11T15:44:24.087123Z","iopub.status.idle":"2021-06-11T15:44:24.098344Z","shell.execute_reply.started":"2021-06-11T15:44:24.087087Z","shell.execute_reply":"2021-06-11T15:44:24.097384Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Maintenant que nous avons rassemblé les chemins de fichiers des images, récupérons les étiquettes.\nNous allons les prendre dans labels_csv et les transformer en tableau NumPy.","metadata":{"execution":{"iopub.status.busy":"2021-06-09T08:34:03.103338Z","iopub.status.idle":"2021-06-09T08:34:03.103734Z"}}},{"cell_type":"code","source":"import numpy as np\nlabels = labels_csv[\"breed\"].to_numpy() # convert labels column to NumPy array\nlabels[:10]","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.100253Z","iopub.execute_input":"2021-06-11T15:44:24.100598Z","iopub.status.idle":"2021-06-11T15:44:24.106107Z","shell.execute_reply.started":"2021-06-11T15:44:24.100566Z","shell.execute_reply":"2021-06-11T15:44:24.105458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Comparons le nombre d'étiquettes au nombre de noms de fichiers.","metadata":{}},{"cell_type":"code","source":"if len(labels) == len(filenames):\n    print('Number of labels matches the number of filenames.')\nelse:\n    print('Number of labels doesnot matches the number of filenames')","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.106983Z","iopub.execute_input":"2021-06-11T15:44:24.107248Z","iopub.status.idle":"2021-06-11T15:44:24.119636Z","shell.execute_reply.started":"2021-06-11T15:44:24.107222Z","shell.execute_reply":"2021-06-11T15:44:24.118496Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Si tout a fonctionné, nous devrions avoir la même quantité d'images et d'étiquettes.\n\nEnfin, comme un modèle d'apprentissage automatique ne peut pas prendre de chaînes de caractères en entrée (ce que sont les étiquettes actuellement), nous devons **convertir nos étiquettes en chiffres.**\n\nPour commencer, nous allons trouver tous les **noms uniques de races de chiens.**\n\nEnsuite, nous allons **parcourir la liste des étiquettes, les comparer aux races uniques** et **créer une liste de booléens** indiquant laquelle est l'étiquette réelle (Vrai) et lesquelles ne le sont pas (Faux).","metadata":{}},{"cell_type":"code","source":"unique_breed = np.unique(labels) \nlen(unique_breed)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.120942Z","iopub.execute_input":"2021-06-11T15:44:24.121220Z","iopub.status.idle":"2021-06-11T15:44:24.142833Z","shell.execute_reply.started":"2021-06-11T15:44:24.121192Z","shell.execute_reply":"2021-06-11T15:44:24.141914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"La longueur de unique_breeds doit être de 120, ce qui signifie que nous travaillons avec des images de 120 races de chiens différentes.\n\nUtilisez maintenant unique_breeds pour transformer notre tableau de labels en un tableau de booléens.","metadata":{}},{"cell_type":"code","source":"#exemple d'une étiquette transformée en tableau de boléens\nprint(labels[0])\nlabels[0] == unique_breed","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.144346Z","iopub.execute_input":"2021-06-11T15:44:24.144791Z","iopub.status.idle":"2021-06-11T15:44:24.155496Z","shell.execute_reply.started":"2021-06-11T15:44:24.144745Z","shell.execute_reply":"2021-06-11T15:44:24.154734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn every label into a boolean array\nboolean_labels = [label == np.array(unique_breed) for label in labels]\nboolean_labels[:2]","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.156363Z","iopub.execute_input":"2021-06-11T15:44:24.156681Z","iopub.status.idle":"2021-06-11T15:44:24.275600Z","shell.execute_reply.started":"2021-06-11T15:44:24.156652Z","shell.execute_reply":"2021-06-11T15:44:24.274824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"un concept important de l'apprentissage automatique consiste à convertir vos données en chiffres avant de les transmettre à un modèle d'apprentissage automatique.\n\nDans ce cas, nous avons transformé un seul nom de race de chien, tel que boston_bull, en un tableau de chiffres sur le principe du One Hot Encoder.","metadata":{}},{"cell_type":"code","source":"# Turining boolean arrays into integers.\nprint(labels[0])   #orginal index\nprint(np.where(unique_breed==labels[0]))    #index where labels occurs.\nprint(boolean_labels[0].argmax())     #index where label occurs in boolean array\nprint(boolean_labels[0].astype(int))   #there will be a 1 where sample label occurs","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.276614Z","iopub.execute_input":"2021-06-11T15:44:24.277006Z","iopub.status.idle":"2021-06-11T15:44:24.284600Z","shell.execute_reply.started":"2021-06-11T15:44:24.276976Z","shell.execute_reply":"2021-06-11T15:44:24.283708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Maintenant que nous avons nos étiquettes au format numérique et que les chemins de fichier de nos images sont facilement accessibles (ils ne sont pas encore numériques), nous allons diviser nos données.","metadata":{}},{"cell_type":"markdown","source":"# Création de notre propre ensemble de validation","metadata":{}},{"cell_type":"markdown","source":"Puisque l'ensemble de données de Kaggle n'est pas fourni avec un ensemble de validation (une division des données sur laquelle nous pouvons tester notre modèle avant de faire des prédictions finales sur l'ensemble de test), nous allons en créer un.\n\nNous pouvons utiliser la fonction train_test_split de Scikit-Learn ou nous pouvons simplement faire des divisions manuelles des données.\n\nPour des raisons d'accessibilité ultérieure, sauvegardons nos noms de fichiers en X (données) et nos étiquettes en y.","metadata":{}},{"cell_type":"code","source":"# Setup X & y variables\nX = filenames\ny = boolean_labels\n\nprint(f\"Number of training images: {len(X)}\")\nprint(f\"Number of labels: {len(y)}\")","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.285906Z","iopub.execute_input":"2021-06-11T15:44:24.286183Z","iopub.status.idle":"2021-06-11T15:44:24.304204Z","shell.execute_reply.started":"2021-06-11T15:44:24.286156Z","shell.execute_reply":"2021-06-11T15:44:24.303239Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Étant donné que nous travaillons avec plus de 10 000 images, il est préférable de travailler avec une partie d'entre elles pour s'assurer que tout fonctionne bien avant de s'entraîner sur toutes les images.\n\nEn effet, le calcul de plus de 10 000 images peut prendre beaucoup de temps. Et notre objectif, lorsque nous travaillons sur des projets d'apprentissage automatique, est de réduire le temps entre les expériences.\n\nCommençons à expérimenter avec 1000 et augmentons ce nombre selon nos besoins.","metadata":{}},{"cell_type":"code","source":"#set number of images to set for the experiment.\nnum_img = 1000 #@param {type:\"slider\",min:1000,max:10000}","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.305592Z","iopub.execute_input":"2021-06-11T15:44:24.306074Z","iopub.status.idle":"2021-06-11T15:44:24.314517Z","shell.execute_reply.started":"2021-06-11T15:44:24.306035Z","shell.execute_reply":"2021-06-11T15:44:24.313668Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Divisons maintenant nos données en ensembles de formation et de validation. Nous utiliserons une répartition 80/20 (80% de données de formation, 20% de données de validation).","metadata":{}},{"cell_type":"code","source":"#let's split our data into train and validation.\nfrom sklearn.model_selection import train_test_split\n\n#spliting into training and validation of total size NUM_IMAGES.\n\nX_train,X_val,y_train,y_val = train_test_split(X[:num_img],\n                                                y[:num_img],\n                                                test_size=0.2,\n                                                random_state=42)\nlen(X_train),len(X_val),len(y_train),len(y_val)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.315726Z","iopub.execute_input":"2021-06-11T15:44:24.316166Z","iopub.status.idle":"2021-06-11T15:44:24.332079Z","shell.execute_reply.started":"2021-06-11T15:44:24.316128Z","shell.execute_reply":"2021-06-11T15:44:24.331008Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out the training data (image file paths and labels)\nX_train[:1], y_train[:1]","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.333499Z","iopub.execute_input":"2021-06-11T15:44:24.334218Z","iopub.status.idle":"2021-06-11T15:44:24.345973Z","shell.execute_reply.started":"2021-06-11T15:44:24.334174Z","shell.execute_reply":"2021-06-11T15:44:24.344938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prétraitement des images (transformation des images en tenseurs)","metadata":{}},{"cell_type":"markdown","source":"\nNos étiquettes sont au format numérique mais nos images ne sont encore que des chemins de fichiers.\n\nComme nous utilisons TensorFlow, **nos données doivent être sous la forme de tenseurs.**\n\nUn tenseur est un moyen de **représenter des informations sous forme de nombres.** .Un tenseur peut être considéré comme une combinaison de tableaux NumPy, mais avec la capacité spéciale d'être utilisé sur un GPU.\n\nEn raison de la façon dont TensorFlow stocke les informations (dans les tenseurs), il permet aux modèles d'apprentissage automatique et d'apprentissage profond d'être **exécutés sur des GPU (généralement plus rapides pour le calcul numérique).**\n\nPour **prétraiter nos images en Tensors**, nous allons écrire une fonction qui fait plusieurs choses :\n\n* Prend un nom de fichier d'image en entrée.\n* Utilise TensorFlow pour lire le fichier et l'enregistrer dans une variable, image.\n* Transformer notre image (un fichier jpeg) en tenseurs.\n* Redimensionne l'image pour qu'elle soit de forme (224, 224).\n* Retourner l'image modifiée.\n\nUn bon endroit pour lire sur ce type de fonction est la documentation TensorFlow sur le **chargement des images.**\n\nVous vous demandez peut-être pourquoi **(224, 224)**, qui correspond à **(hauteur, largeur)**. C'est parce que c'est la taille de l'entrée que notre modèle (nous le verrons bientôt) prend, une image qui est (224, 224, 3).\n\n**Le 3, c'est le nombre de canaux de couleur par pixel, rouge, vert et bleu (RVB).**\n\nRendons cela un peu plus concret.","metadata":{}},{"cell_type":"code","source":"# Convert image to NumPy array\nfrom matplotlib.pyplot import imread\nimage = imread(filenames[42]) # read in an image\nimage.shape","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.347433Z","iopub.execute_input":"2021-06-11T15:44:24.347740Z","iopub.status.idle":"2021-06-11T15:44:24.364307Z","shell.execute_reply.started":"2021-06-11T15:44:24.347709Z","shell.execute_reply":"2021-06-11T15:44:24.363189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Remarquez la forme de l'image. C'est (257, 350, 3). C'est la hauteur, la largeur, la valeur du canal de couleur.\n\nEt vous pouvez facilement le convertir en un tenseur en utilisant tf.constant().","metadata":{}},{"cell_type":"code","source":"tf.constant(image)[:2]","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.365498Z","iopub.execute_input":"2021-06-11T15:44:24.365776Z","iopub.status.idle":"2021-06-11T15:44:24.374019Z","shell.execute_reply.started":"2021-06-11T15:44:24.365749Z","shell.execute_reply":"2021-06-11T15:44:24.373143Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Define image size\nIMG_SIZE = 224\n\ndef process_image(image_path):\n  \"\"\"\n  Takes an image file path and turns it into a Tensor.\n  \"\"\"\n  # Read in image file\n  image = tf.io.read_file(image_path)\n  # Turn the jpeg image into numerical Tensor with 3 colour channels (Red, Green, Blue)\n  image = tf.image.decode_jpeg(image, channels=3)\n  # Convert the colour channel values from 0-225 values to 0-1 values\n  image = tf.image.convert_image_dtype(image, tf.float32)\n  # Resize the image to our desired size (224, 244)\n  image = tf.image.resize(image, size=[IMG_SIZE, IMG_SIZE])\n  return image","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.375367Z","iopub.execute_input":"2021-06-11T15:44:24.376000Z","iopub.status.idle":"2021-06-11T15:44:24.385564Z","shell.execute_reply.started":"2021-06-11T15:44:24.375952Z","shell.execute_reply":"2021-06-11T15:44:24.384455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a simple function to return a tuple (image, label)\ndef get_image_label(image_path, label):\n  \"\"\"\n  Takes an image file path name and the associated label,\n  processes the image and returns a tuple of (image, label).\n  \"\"\"\n  image = process_image(image_path)\n  return image, label","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.386838Z","iopub.execute_input":"2021-06-11T15:44:24.387432Z","iopub.status.idle":"2021-06-11T15:44:24.398265Z","shell.execute_reply.started":"2021-06-11T15:44:24.387373Z","shell.execute_reply":"2021-06-11T15:44:24.397191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Création de lots de données\nMaintenant que nous avons une fonction pour convertir nos images en tenseurs, nous allons en construire une fonction pour **transformer nos données en lots** (un TensorFlow BatchDataset).\n\nQu'est-ce qu'un batch ?\n\nUn lot (également appelé mini-batch) est une petite portion de vos données, disons 32 (32 est généralement la taille de lot par défaut) images et leurs étiquettes. En apprentissage profond, au lieu de trouver des modèles dans un ensemble de données entier en même temps, vous les trouvez souvent un lot à la fois.\n\nDisons que vous avez affaire à plus de 10 000 images (ce qui est le cas). Ensemble, ces fichiers peuvent occuper plus de mémoire que votre GPU. Essayer de les calculer tous entraînerait une erreur.\n\nIl est donc plus efficace de  **créer des lots plus petits de vos données et de les calculer un par un.**\n\nTensorFlow est très efficace lorsque vos données sont des lots de tenseurs (image, étiquette). Nous allons donc construire une fonction pour les créer en premier. Nous allons profiter de la fonction process_image en même temps.","metadata":{}},{"cell_type":"code","source":"# Create a simple function to return a tuple (image, label)\ndef get_image_label(image_path, label):\n  \"\"\"\n  Takes an image file path name and the associated label,\n  processes the image and returns a tuple of (image, label).\n  \"\"\"\n  image = process_image(image_path)\n  return image, label","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.403850Z","iopub.execute_input":"2021-06-11T15:44:24.404482Z","iopub.status.idle":"2021-06-11T15:44:24.410123Z","shell.execute_reply.started":"2021-06-11T15:44:24.404432Z","shell.execute_reply":"2021-06-11T15:44:24.409442Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Maintenant que nous disposons d'une fonction simple pour transformer les noms des chemins d'accès aux fichiers d'images et les étiquettes associées en tuples (nous les transformerons ensuite en tenseurs), nous allons créer une fonction pour créer des lots de données.\n\nPuisque nous aurons affaire à trois ensembles de données différents (formation, validation et test), nous nous assurerons que la fonction peut s'adapter à chaque ensemble.\n\nNous définirons une taille de lot par défaut de 32.","metadata":{}},{"cell_type":"code","source":"# Define the batch size, 32 is a good default\nBATCH_SIZE = 32\n\n# Create a function to turn data into batches\ndef create_data_batches(x, y=None, batch_size=BATCH_SIZE, valid_data=False, test_data=False):\n  \"\"\"\n  Creates batches of data out of image (x) and label (y) pairs.\n  Shuffles the data if it's training data but doesn't shuffle it if it's validation data.\n  Also accepts test data as input (no labels).\n  \"\"\"\n  # If the data is a test dataset, we probably don't have labels\n  if test_data:\n    print(\"Creating test data batches...\")\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(x))) # only filepaths\n    data_batch = data.map(process_image).batch(BATCH_SIZE)\n    return data_batch\n  \n  # If the data if a valid dataset, we don't need to shuffle it\n  elif valid_data:\n    print(\"Creating validation data batches...\")\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(x), # filepaths\n                                               tf.constant(y))) # labels\n    data_batch = data.map(get_image_label).batch(BATCH_SIZE)\n    return data_batch\n\n  else:\n    # If the data is a training dataset, we shuffle it\n    print(\"Creating training data batches...\")\n    # Turn filepaths and labels into Tensors\n    data = tf.data.Dataset.from_tensor_slices((tf.constant(x), # filepaths\n                                              tf.constant(y))) # labels\n    \n    # Shuffling pathnames and labels before mapping image processor function is faster than shuffling images\n    data = data.shuffle(buffer_size=len(x))\n\n    # Create (image, label) tuples (this also turns the image path into a preprocessed image)\n    data = data.map(get_image_label)\n\n    # Turn the data into batches\n    data_batch = data.batch(BATCH_SIZE)\n  return data_batch","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.412041Z","iopub.execute_input":"2021-06-11T15:44:24.412633Z","iopub.status.idle":"2021-06-11T15:44:24.423582Z","shell.execute_reply.started":"2021-06-11T15:44:24.412595Z","shell.execute_reply":"2021-06-11T15:44:24.422506Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create training and validation data batches\ntrain_data = create_data_batches(X_train, y_train)\nval_data = create_data_batches(X_val, y_val, valid_data=True)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.424844Z","iopub.execute_input":"2021-06-11T15:44:24.425282Z","iopub.status.idle":"2021-06-11T15:44:24.553263Z","shell.execute_reply.started":"2021-06-11T15:44:24.425250Z","shell.execute_reply":"2021-06-11T15:44:24.552066Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check out the different attributes of our data batches\ntrain_data.element_spec, val_data.element_spec","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.555755Z","iopub.execute_input":"2021-06-11T15:44:24.556206Z","iopub.status.idle":"2021-06-11T15:44:24.563570Z","shell.execute_reply.started":"2021-06-11T15:44:24.556161Z","shell.execute_reply":"2021-06-11T15:44:24.562305Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Nous avons nos données en lots, plus précisément, elles sont dans des paires Tensor de (images, étiquettes) prêtes à être utilisées sur un GPU.","metadata":{"execution":{"iopub.status.busy":"2021-06-09T11:46:43.227094Z","iopub.execute_input":"2021-06-09T11:46:43.227481Z","iopub.status.idle":"2021-06-09T11:46:43.235008Z","shell.execute_reply.started":"2021-06-09T11:46:43.22745Z","shell.execute_reply":"2021-06-09T11:46:43.233241Z"}}},{"cell_type":"markdown","source":"# Visualisation des lots de données","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Create a function for viewing images in a data batch\ndef show_25_images(images, labels):\n  \"\"\"\n  Displays 25 images from a data batch.\n  \"\"\"\n  # Setup the figure\n  plt.figure(figsize=(10, 10))\n  # Loop through 25 (for displaying 25 images)\n  for i in range(25):\n    # Create subplots (5 rows, 5 columns)\n    ax = plt.subplot(5, 5, i+1)\n    # Display an image\n    plt.imshow(images[i])\n    # Add the image label as the title\n    plt.title(unique_breed[labels[i].argmax()])\n    # Turn gird lines off\n    plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.565010Z","iopub.execute_input":"2021-06-11T15:44:24.565401Z","iopub.status.idle":"2021-06-11T15:44:24.573637Z","shell.execute_reply.started":"2021-06-11T15:44:24.565369Z","shell.execute_reply":"2021-06-11T15:44:24.572695Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Pour rendre le calcul efficace, un lot est une collection de tenseurs fortement enroulée.\nAinsi, pour visualiser les données d'un lot, nous devons le dérouler. Nous pouvons le faire en appelant la méthode as_numpy_iterator() sur un lot de données. Cela transformera notre lot de données en quelque chose qui peut être itéré. Le passage d'un itérable à next() renverra l'élément suivant dans l'itérateur. Dans notre cas, next renverra un lot de 32 images et paires d'étiquettes.","metadata":{}},{"cell_type":"code","source":"# Visualize training images from the training data batch\ntrain_images, train_labels = next(train_data.as_numpy_iterator())\nshow_25_images(train_images, train_labels)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:24.574919Z","iopub.execute_input":"2021-06-11T15:44:24.575206Z","iopub.status.idle":"2021-06-11T15:44:26.798060Z","shell.execute_reply.started":"2021-06-11T15:44:24.575177Z","shell.execute_reply":"2021-06-11T15:44:26.796785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visualize validation images from the validation data batch\nval_images, val_labels = next(val_data.as_numpy_iterator())\nshow_25_images(val_images, val_labels)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:26.799648Z","iopub.execute_input":"2021-06-11T15:44:26.800031Z","iopub.status.idle":"2021-06-11T15:44:28.390045Z","shell.execute_reply.started":"2021-06-11T15:44:26.799993Z","shell.execute_reply":"2021-06-11T15:44:28.389201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Création et formation d'un modèle\n\nMaintenant que nos données sont prêtes, préparons leur modélisation. \n\n# Comment choisir un modèle ?\n\nEmpilements de couches Conv2D et MaxPool2D:\nMaxPool2D réduit la taille des cartes de caractéristiques\n-  Le maximum pooling est appliqué après l'activation ReLU et a pour effet d'\"intensifier\" les caractéristiques. L'étape de mise en commun augmente la proportion de pixels actifs par rapport aux pixels nuls.\n- filters= On  indique à la couche convolutionnelle le nombre de cartes de caractéristiques que vous souhaitez qu'elle crée en sortie.\n- padding='same'. remplissage pour obtenir des map feature de même taille que l’image.\n- kernel_size = Dimensions du noyau.\n- L'activation ReLU dit que les valeurs négatives ne sont pas importantes et les met donc à 0. \n- Dropout Corrige l’overfitting. Réduit le bruit en éliminant aléatoirement une fraction des unités d’entrées de couches. \n- Early stopping - Arrêt précoce si la perte de validation (validation loss) ne descend plus. Bcp de bruit peu de signal. \n- Softmax = problème de classification multiclasse\n\n\n# Construction d'un modèle\n\nAvant de construire un modèle, nous devons définir quelques éléments :\n\nLa forme d'entrée (images, sous la forme de tenseurs) de notre modèle.\nLa forme de sortie (étiquettes d'images, sous forme de tenseurs) de notre modèle.\nL'URL du modèle que nous voulons utiliser.\nCes éléments constituent une pratique standard, quel que soit le modèle d'apprentissage automatique que vous utilisez.","metadata":{}},{"cell_type":"code","source":"# Setup input shape to the model\nINPUT_SHAPE = [None, IMG_SIZE, IMG_SIZE, 3] # batch, height, width, colour channels\n\n# Setup output shape of the model\nOUTPUT_SHAPE = len(unique_breed) # number of unique labels","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.391110Z","iopub.execute_input":"2021-06-11T15:44:28.391542Z","iopub.status.idle":"2021-06-11T15:44:28.395734Z","shell.execute_reply.started":"2021-06-11T15:44:28.391508Z","shell.execute_reply":"2021-06-11T15:44:28.394829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data augmentation","metadata":{}},{"cell_type":"markdown","source":"ImageDataGenerator est la classe de référence de Keras pour le pipelining des données d'image pour l'apprentissage en profondeur. Il permet un accès facile à votre système de fichiers local et à plusieurs méthodes différentes pour charger des données à partir de différentes structures. Il possède également des capacités de prétraitement et d'augmentation des données assez puissantes.","metadata":{}},{"cell_type":"markdown","source":"https://ichi.pro/fr/methodes-de-flux-de-keras-imagedatagenerator-et-quand-les-utiliser-203621254419857","metadata":{}},{"cell_type":"code","source":"# Create early stopping (once our model stops improving, stop training)\nearly_stopping = tf.keras.callbacks.EarlyStopping(monitor=\"val_accuracy\",\n                                                  patience=3) # stops after 3 rounds of no improvements\nNUM_EPOCHS = 100","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.396872Z","iopub.execute_input":"2021-06-11T15:44:28.397299Z","iopub.status.idle":"2021-06-11T15:44:28.409377Z","shell.execute_reply.started":"2021-06-11T15:44:28.397269Z","shell.execute_reply":"2021-06-11T15:44:28.408384Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import keras\nimport tensorflow as tf\nfrom keras.layers.convolutional import Conv2D, MaxPooling2D\nfrom keras.models import Sequential\nfrom keras.layers import Dense, Activation, Flatten\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom keras.optimizers import Adam\n\n\nmodel = Sequential()\n\nmodel.add(Conv2D(32, (3, 3), padding='same', input_shape = INPUT_SHAPE[1:]))\nmodel.add(Activation('relu'))\n\nmodel.add(Conv2D(32, (3, 3)))\nmodel.add(Activation('relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(64, (3, 3), padding='same'))\nmodel.add(Activation('relu'))\n\nmodel.add(Conv2D(64, (3, 3)))\nmodel.add(Activation('relu'))\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\nmodel.add(Flatten())\n\nmodel.add(Dense(512))\nmodel.add(Activation('relu'))\nmodel.add(Dropout(0.5))\n\nmodel.add(Dense(OUTPUT_SHAPE, activation='softmax'))","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2021-06-11T16:02:18.254701Z","iopub.execute_input":"2021-06-11T16:02:18.255299Z","iopub.status.idle":"2021-06-11T16:02:18.917587Z","shell.execute_reply.started":"2021-06-11T16:02:18.255254Z","shell.execute_reply":"2021-06-11T16:02:18.916548Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"  # Compile the model\nmodel.compile(\n      loss=tf.keras.losses.CategoricalCrossentropy(), # Our model wants to reduce this (how wrong its guesses are)\n      optimizer=tf.keras.optimizers.Adam(), # A friend telling our model how to improve its guesses\n      metrics=[\"accuracy\"] # We'd like this to go up\n  )\n\n# Build the model\nmodel.build(INPUT_SHAPE) # Let the model know what kind of inputs it'll be getting","metadata":{"execution":{"iopub.status.busy":"2021-06-11T16:02:22.510733Z","iopub.execute_input":"2021-06-11T16:02:22.511131Z","iopub.status.idle":"2021-06-11T16:02:22.528672Z","shell.execute_reply.started":"2021-06-11T16:02:22.511095Z","shell.execute_reply":"2021-06-11T16:02:22.527677Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Maintenant que nous avons accès à nos données, nous pouvons mettre en place un ImageDataGenerator et connectez -vous à notre source de données à l' aide de notre première méthode, .flow.  \n\nImageDataGenerator:\n\n- **rescale**(facultatif, mais recommandé) - L'un des nombreux paramètres d'augmentation ajuste les valeurs de pixels de notre image. Le réglage rescale=1./255ajustera nos valeurs de pixels entre 0 et 1.\n\n- **validation_split**(facultatif, mais recommandé) - Attribue un train-test-split aux données passées en fonction du flottant fourni. L'utilisation de cette méthode signifie que vous devez attribuer un sous-ensemble de formation et de validation dans votre .flowméthode. Le réglage validation_split=0.2nous donne une répartition des essais de train de 80/20.\n\n- **x_train, y_train(obligatoire)** - Les deux premiers arguments passés à votre méthode de flux seront toujours vos données X et y sous la forme de tableaux NumPy.\n\n- **batch_size(obligatoire)** - Nombre d'images à inclure dans chaque lot de données d'entraînement. N'oubliez pas que les réseaux de neurones s'entraînent sur une série d' époques , au cours desquelles des groupes d'images appelés lots sont transmis à votre modèle.\n\n- **shuffle**(facultatif, mais recommandé pour le générateur de formation) - indique à votre générateur s'il doit ou non sélectionner au hasard les images à intégrer dans chaque lot. L'avantage de ceci est que notre modèle ne sera pas formé sur plusieurs images de la même catégorie dos à dos. Nous ne l'incluons pas dans notre générateur de validation car nous souhaitons pouvoir interpréter facilement nos prédictions.\n\n- **seed** (facultatif) - Définit un état aléatoire pour la reproductibilité.\n\n- **subset**(obligatoire quand validation_splitest défini) - Indique quel sous-ensemble de données est contenu dans le générateur, correspond directement à l' validation_splitargument passé au constructeur IDG.","metadata":{}},{"cell_type":"code","source":"for layer in model.layers[:20]:\n    layer.trainable=False\nfor layer in model.layers[20:]:\n    layer.trainable=True","metadata":{"execution":{"iopub.status.busy":"2021-06-11T16:02:27.209336Z","iopub.execute_input":"2021-06-11T16:02:27.209736Z","iopub.status.idle":"2021-06-11T16:02:27.215318Z","shell.execute_reply.started":"2021-06-11T16:02:27.209702Z","shell.execute_reply":"2021-06-11T16:02:27.214140Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.preprocessing.image import ImageDataGenerator\n\ndatagen = ImageDataGenerator(\n        featurewise_center=True,\n        featurewise_std_normalization=True,\n        rotation_range=20,\n        width_shift_range=0.2,\n        height_shift_range=0.2,\n        horizontal_flip=True,\n        validation_split=0.2)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T16:03:02.268233Z","iopub.execute_input":"2021-06-11T16:03:02.268673Z","iopub.status.idle":"2021-06-11T16:03:02.274902Z","shell.execute_reply.started":"2021-06-11T16:03:02.268634Z","shell.execute_reply":"2021-06-11T16:03:02.273836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from os.path import isfile, join, abspath, exists, isdir, expanduser\nfrom keras.preprocessing.image import ImageDataGenerator, load_img\nfrom keras.utils import to_categorical\n\n#Extracting different classes\ndog_breeds = sorted(labels_csv['breed'].unique())\nn_classes = len(dog_breeds)\n\n#Converting classes to numbers\nclass_to_num = dict(zip(dog_breeds,range(n_classes)))\n\nimage_size = (224,224,3)\ndata_dir = \"../input/dog-breed-identification/train\"\n\"\"\"Return arrays that represents the images and processed target given where the images are saved, the dataframe that contains the id and the breeds and the image size\"\"\"\nimage_names = labels_csv['id']\nimage_labels = labels_csv['breed']\ndata_size = len(image_names)\n\nX = np.zeros([data_size,image_size[0],image_size[1],image_size[2]],dtype = np.uint8)\ny = np.zeros([data_size,1],dtype = np.uint8)\n\nfor i in range(data_size):\n    img_name = image_names[i]\n    img_dir = join(data_dir,img_name+'.jpg')\n    img_pixels = load_img(img_dir,target_size=image_size)\n    X[i] = img_pixels\n    y[i] = class_to_num[image_labels[i]]\n\ny = to_categorical(y)\n\nind = np.random.permutation(data_size)\nX = X[ind]\ny = y[ind]\nprint('Ouptut Data Size: ', X.shape)\nprint('Ouptut Label Size: ', y.shape)\n ","metadata":{"execution":{"iopub.status.busy":"2021-06-11T16:05:17.808242Z","iopub.execute_input":"2021-06-11T16:05:17.808658Z","iopub.status.idle":"2021-06-11T16:05:59.447461Z","shell.execute_reply.started":"2021-06-11T16:05:17.808623Z","shell.execute_reply":"2021-06-11T16:05:59.446265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#spliting into training and validation of total size NUM_IMAGES.\n\nX_train,X_val,y_train,y_val = train_test_split(X[:num_img],\n                                                y[:num_img],\n                                                test_size=0.2,\n                                                random_state=42)\nlen(X_train),len(X_val),len(y_train),len(y_val)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T16:06:05.523639Z","iopub.execute_input":"2021-06-11T16:06:05.524025Z","iopub.status.idle":"2021-06-11T16:06:05.745866Z","shell.execute_reply.started":"2021-06-11T16:06:05.523992Z","shell.execute_reply":"2021-06-11T16:06:05.744682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"datagen = ImageDataGenerator(rescale=1./255.,validation_split=0.2)\n\n\ntrain_generator = datagen.flow(X_train,\n                               y_train,\n                               batch_size=32,\n                               shuffle=True,\n                               seed=42,\n                               subset='training')\n\nvalid_generator = datagen.flow(X_val,\n                               y_val,\n                               batch_size=32,\n                               seed=42,\n                               subset='validation')\n\n\nSTEP_SIZE_TRAIN=train_generator.n//train_generator.batch_size\nSTEP_SIZE_VALID=valid_generator.n//valid_generator.batch_size\n\nhistory = model.fit(train_generator,\n          steps_per_epoch=STEP_SIZE_TRAIN,\n          validation_data=valid_generator,\n          validation_steps=STEP_SIZE_VALID,\n           epochs=NUM_EPOCHS,\n            validation_freq=1,\n            callbacks=early_stopping)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T16:06:09.735439Z","iopub.execute_input":"2021-06-11T16:06:09.735892Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check again if GPU is available (otherwise computing will take a looooonnnnggggg time)\nprint(\"GPU\", \"available (OUUUUIIII!!!!)\" if tf.config.list_physical_devices(\"GPU\") else \"NONNNNNN!!!!!\")","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.459966Z","iopub.status.idle":"2021-06-11T15:44:28.460514Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on the validation data (not used to train on)\npredictions = model.predict(val_data, verbose=1) # verbose shows us how long there is to go\npredictions","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.461310Z","iopub.status.idle":"2021-06-11T15:44:28.461879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Check the shape of predictions\npredictions.shape","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.462677Z","iopub.status.idle":"2021-06-11T15:44:28.463192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"La réalisation de prédictions avec notre modèle renvoie un tableau avec une valeur différente pour chaque étiquette.\n\nDans ce cas, faire des prédictions sur les données de validation (200 images) renvoie un tableau (prédictions) de tableaux, chacun contenant 120 valeurs différentes (une pour chaque race de chien unique).\n\nCes différentes valeurs sont les probabilités ou la probabilité que le modèle ait prédit qu'une certaine image était une certaine race de chien. Plus la valeur est élevée, plus le modèle pense qu'une image donnée est une race de chien spécifique.\n\nVoyons comment convertir un tableau de probabilités en une étiquette réelle.","metadata":{}},{"cell_type":"code","source":"history_df = pd.DataFrame(history.history)\nhistory_df.loc[:, ['loss', 'val_loss']].plot();\nhistory_df.loc[:, ['accuracy', 'val_accuracy']].plot();","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.463987Z","iopub.status.idle":"2021-06-11T15:44:28.464529Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Turn prediction probabilities into their respective label (easier to understand)\ndef get_pred_label(prediction_probabilities):\n  \"\"\"\n  Turns an array of prediction probabilities into a label.\n  \"\"\"\n  return unique_breed[np.argmax(prediction_probabilities)]\n\n# Get a predicted label based on an array of prediction probabilities\npred_label = get_pred_label(predictions[0])\npred_label","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.465317Z","iopub.status.idle":"2021-06-11T15:44:28.465849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Rappelez-vous, le modèle n'a pas été entraîné sur les données de validation, pendant la fonction fit(), il a seulement utilisé les données de validation pour s'évaluer. Nous pouvons donc utiliser les images de validation pour comparer visuellement les prédictions de notre modèle avec les étiquettes de validation.\n\nPuisque nos données de validation (val_data) sont sous forme de lot, pour obtenir une liste d'images et d'étiquettes de validation, nous devrons les débloquer (en utilisant unbatch()) et ensuite les transformer en itérateur en utilisant as_numpy_iterator().\n","metadata":{}},{"cell_type":"code","source":"# Create a function to unbatch a batched dataset\ndef unbatchify(data):\n  \"\"\"\n  Takes a batched dataset of (image, label) Tensors and returns separate arrays\n  of images and labels.\n  \"\"\"\n  images = []\n  labels = []\n  # Loop through unbatched data\n  for image, label in data.unbatch().as_numpy_iterator():\n    images.append(image)\n    labels.append(unique_breed[np.argmax(label)])\n  return images, labels\n\n# Unbatchify the validation data\nval_images, val_labels = unbatchify(val_data)\nval_images[0], val_labels[0]","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.466635Z","iopub.status.idle":"2021-06-11T15:44:28.467141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Maintenant, nous avons des moyens d'obtenir :\n\n* Des étiquettes de prédiction\n* Étiquettes de validation (étiquettes de vérité)\n* Images de validation\n* Créons quelques fonctions pour rendre tout cela un peu plus visuel.\n\nPlus précisément, nous voulons être en mesure de visualiser une image, son étiquette prédite et son étiquette réelle (true label).\n\nLa première fonction que nous allons créer va :\n\n* Prendre un tableau de probabilités de prédiction, un tableau d'étiquettes réelles, un tableau d'images et un nombre entier.\n* Convertir les probabilités de prédiction en une étiquette prédite.\n* Tracer l'étiquette prédite, sa probabilité prédite, l'étiquette de vérité et l'image cible sur un seul graphique.","metadata":{}},{"cell_type":"code","source":"def plot_pred(prediction_probabilities, labels, images, n=1):\n  \"\"\"\n  View the prediction, ground truth label and image for sample n.\n  \"\"\"\n  pred_prob, true_label, image = prediction_probabilities[n], labels[n], images[n]\n  \n  # Get the pred label\n  pred_label = get_pred_label(pred_prob)\n  \n  # Plot image & remove ticks\n  plt.imshow(image)\n  plt.xticks([])\n  plt.yticks([])\n\n  # Change the color of the title depending on if the prediction is right or wrong\n  if pred_label == true_label:\n    color = \"green\"\n  else:\n    color = \"red\"\n\n  plt.title(\"{} {:2.0f}% ({})\".format(pred_label,\n                                      np.max(pred_prob)*100,\n                                      true_label),\n                                      color=color)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.467964Z","iopub.status.idle":"2021-06-11T15:44:28.468511Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# View an example prediction, original image and truth label\nplot_pred(prediction_probabilities=predictions,\n          labels=val_labels,\n          images=val_images)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.469292Z","iopub.status.idle":"2021-06-11T15:44:28.469848Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Comme nous travaillons sur un problème multi-classes (120 races de chiens différentes), il serait également intéressant de voir quelles autres prédictions notre modèle fait. Plus précisément, si notre modèle prédit une certaine étiquette avec une probabilité de 24 %, que prédit-il d'autre ?\n\nConstruisons une fonction pour le démontrer. Cette fonction va :\n**Prendre en entrée un tableau de probabilités de prédiction, un tableau d'étiquettes de vérité terrain et un nombre entier./\nTrouver l'étiquette prédite en utilisant get_pred_label()./\nTrouver les 10 premiers :\nIndices de probabilités de prédiction - \nValeurs des probabilités de prédiction - \nÉtiquettes de prédiction /. \nTracez les 10 premières valeurs de probabilité de prédiction et les étiquettes, en colorant la véritable étiquette en vert.**","metadata":{}},{"cell_type":"code","source":"def plot_pred_conf(prediction_probabilities, labels, n=1):\n  \"\"\"\n  Plots the top 10 highest prediction confidences along with\n  the truth label for sample n.\n  \"\"\"\n  pred_prob, true_label = prediction_probabilities[n], labels[n]\n\n  # Get the predicted label\n  pred_label = get_pred_label(pred_prob)\n\n  # Find the top 10 prediction confidence indexes\n  top_10_pred_indexes = pred_prob.argsort()[-10:][::-1]\n  # Find the top 10 prediction confidence values\n  top_10_pred_values = pred_prob[top_10_pred_indexes]\n  # Find the top 10 prediction labels\n  top_10_pred_labels = unique_breed[top_10_pred_indexes]\n\n  # Setup plot\n  top_plot = plt.bar(np.arange(len(top_10_pred_labels)), \n                     top_10_pred_values, \n                     color=\"grey\")\n  plt.xticks(np.arange(len(top_10_pred_labels)),\n             labels=top_10_pred_labels,\n             rotation=\"vertical\")\n\n  # Change color of true label\n  if np.isin(true_label, top_10_pred_labels):\n    top_plot[np.argmax(top_10_pred_labels == true_label)].set_color(\"green\")\n  else:\n    pass","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.470667Z","iopub.status.idle":"2021-06-11T15:44:28.471193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_pred_conf(prediction_probabilities=predictions,\n               labels=val_labels,\n               n=9)","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.471982Z","iopub.status.idle":"2021-06-11T15:44:28.472524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's check a few predictions and their different values\ni_multiplier = 0\nnum_rows = 3\nnum_cols = 2\nnum_images = num_rows*num_cols\nplt.figure(figsize=(5*2*num_cols, 5*num_rows))\nfor i in range(num_images):\n  plt.subplot(num_rows, 2*num_cols, 2*i+1)\n  plot_pred(prediction_probabilities=predictions,\n            labels=val_labels,\n            images=val_images,\n            n=i+i_multiplier)\n  plt.subplot(num_rows, 2*num_cols, 2*i+2)\n  plot_pred_conf(prediction_probabilities=predictions,\n                labels=val_labels,\n                n=i+i_multiplier)\nplt.tight_layout(h_pad=1.0)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2021-06-11T15:44:28.473332Z","iopub.status.idle":"2021-06-11T15:44:28.473855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"https://www.kaggle.com/mrdbourke/tensorflow-2-x-tensorflow-hub-end-to-end-example","metadata":{}}]}