{"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":"# Imports\n\nimport numpy as np\nimport pandas as pd\nimport tensorflow as tf\nfrom glob import glob # finds all the pathnames matching a specified pattern according to the rules used by the Unix shell\nimport cv2 # computer vision library for reading images\n\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom tensorflow.keras.layers.experimental import preprocessing\nfrom keras import applications\nfrom keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau\nfrom tensorflow.keras.applications.resnet50 import preprocess_input\nfrom tensorflow.keras.preprocessing import image\n\nfrom sklearn.model_selection import train_test_split\n\nimport os, warnings\nimport matplotlib.pyplot as plt\nfrom matplotlib import gridspec\n\n# Reproducability\ndef set_seed(seed=31415):\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    os.environ['TF_DETERMINISTIC_OPS'] = '1'\nset_seed()\n\n# Set Matplotlib defaults\nplt.rc('figure', autolayout=True)\nplt.rc('axes', labelweight='bold', labelsize='large',\n       titleweight='bold', titlesize=18, titlepad=10)\nplt.rc('image', cmap='magma')\nwarnings.filterwarnings(\"ignore\") # to clean up output cells","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-06-16T14:06:50.082878Z","iopub.execute_input":"2021-06-16T14:06:50.08326Z","iopub.status.idle":"2021-06-16T14:06:56.980426Z","shell.execute_reply.started":"2021-06-16T14:06:50.083174Z","shell.execute_reply":"2021-06-16T14:06:56.979185Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pretrained_base = applications.resnet50.ResNet50(\n    include_top=False,\n    weights='imagenet',\n    input_tensor=None,\n    input_shape=(224, 224, 3),\n    pooling=None)\n\npretrained_base.trainable = False\n","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:07:10.252723Z","iopub.execute_input":"2021-06-16T14:07:10.253104Z","iopub.status.idle":"2021-06-16T14:07:16.689162Z","shell.execute_reply.started":"2021-06-16T14:07:10.25307Z","shell.execute_reply":"2021-06-16T14:07:16.687598Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pretrained_base.summary()","metadata":{"execution":{"iopub.status.busy":"2021-06-11T07:56:46.502123Z","iopub.execute_input":"2021-06-11T07:56:46.50477Z","iopub.status.idle":"2021-06-11T07:56:46.638019Z","shell.execute_reply.started":"2021-06-11T07:56:46.504721Z","shell.execute_reply":"2021-06-11T07:56:46.636977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef build_model():\n    '''\n    Builds the neural network classifier model\n    '''\n    model = keras.Sequential([\n        pretrained_base,\n        layers.GlobalAveragePooling2D(),\n        layers.Dense(units=256, activation='relu'),\n        layers.Dense(units=120, activation='softmax')\n    ])\n    return model\n","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:07:27.531106Z","iopub.execute_input":"2021-06-16T14:07:27.531481Z","iopub.status.idle":"2021-06-16T14:07:27.537928Z","shell.execute_reply.started":"2021-06-16T14:07:27.531449Z","shell.execute_reply":"2021-06-16T14:07:27.536578Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def read_image(path):\n    '''\n    Read the image.\n    Resize the image.\n    Transform the image in an array.\n    Add 1 dimension.\n    Apply normalization.\n    '''\n    img = image.load_img(path, target_size=(224, 224))\n    img = image.img_to_array(img)\n    #img = np.expand_dims(img, axis=0)\n    img = preprocess_input(img)\n    return img\n\n\ndef parse_data(x, y):\n    x = x.decode()\n    num_class = NUM_CLASSES\n    image = read_image(x)\n    label = [0] * num_class\n    label[y] = 1\n    label = np.array(label)\n    label = label.astype(np.int32)\n    return image, label\n\ndef tf_parse(x, y):\n    \n    x, y = tf.numpy_function(parse_data, [x, y], [tf.float32, tf.int32])\n    y.set_shape((NUM_CLASSES))\n    return x, y\n\n\ndef tf_dataset(x, y, batch):\n    dataset = tf.data.Dataset.from_tensor_slices((x, y))\n    dataset = dataset.map(tf_parse)\n    dataset = dataset.batch(batch)\n    dataset = dataset.repeat()\n    return dataset\n\n","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:08:05.0987Z","iopub.execute_input":"2021-06-16T14:08:05.099102Z","iopub.status.idle":"2021-06-16T14:08:05.111772Z","shell.execute_reply.started":"2021-06-16T14:08:05.099073Z","shell.execute_reply":"2021-06-16T14:08:05.110286Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_array = read_image(\"../input/dog-breed-identification/train/000bec180eb18c7604dcecc8fe0dba07.jpg\")\nimg_array[0][0][0]","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:08:27.902437Z","iopub.execute_input":"2021-06-16T14:08:27.902911Z","iopub.status.idle":"2021-06-16T14:08:27.937411Z","shell.execute_reply.started":"2021-06-16T14:08:27.90288Z","shell.execute_reply":"2021-06-16T14:08:27.93598Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"img_array.shape","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:08:31.845Z","iopub.execute_input":"2021-06-16T14:08:31.845378Z","iopub.status.idle":"2021-06-16T14:08:31.852881Z","shell.execute_reply.started":"2021-06-16T14:08:31.845346Z","shell.execute_reply":"2021-06-16T14:08:31.851583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Path to the data\nPATH = \"../input/dog-breed-identification\"\nTRAIN_PATH = os.path.join(PATH, 'train/*')\nTEST_PATH = os.path.join(PATH, 'test/*')\nLABELS_PATH = os.path.join(PATH, 'labels.csv')\n\n# Set the parameters for the Keras model\nSIZE = 224\nNUM_CLASSES = 120\nLR = 1e-4\nBATCH_SIZE = 32\nEPOCHS = 10\nFILTERS = 16\nKERNEL_SIZE = 3\nDIM = (224, 224)","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:08:37.076348Z","iopub.execute_input":"2021-06-16T14:08:37.076777Z","iopub.status.idle":"2021-06-16T14:08:37.085024Z","shell.execute_reply.started":"2021-06-16T14:08:37.076746Z","shell.execute_reply":"2021-06-16T14:08:37.083611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get the number of breeds\nlabels_df = pd.read_csv(LABELS_PATH)\nbreed = labels_df['breed'].unique()\nprint('Number of breeds: ', len(breed))","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:08:43.101155Z","iopub.execute_input":"2021-06-16T14:08:43.101534Z","iopub.status.idle":"2021-06-16T14:08:43.159768Z","shell.execute_reply.started":"2021-06-16T14:08:43.101493Z","shell.execute_reply":"2021-06-16T14:08:43.158652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set a unique id for each breed\nbreed_to_id = {name: i for i, name in enumerate(breed)}\nid_to_breed = {i: name for i, name in enumerate(breed)}","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:08:48.51776Z","iopub.execute_input":"2021-06-16T14:08:48.518126Z","iopub.status.idle":"2021-06-16T14:08:48.525867Z","shell.execute_reply.started":"2021-06-16T14:08:48.518095Z","shell.execute_reply":"2021-06-16T14:08:48.524281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a list of labels ids from each image\nids = glob(TRAIN_PATH)\nlabels = []\n\nfor image_id in ids:\n    image_id = image_id.split('/')[-1].split('.')[0]\n    breed_name = list(labels_df[labels_df.id == image_id]['breed'])[0]\n    breed_idx = breed_to_id[breed_name]\n    labels.append(breed_idx)","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:08:51.833718Z","iopub.execute_input":"2021-06-16T14:08:51.834112Z","iopub.status.idle":"2021-06-16T14:09:11.75312Z","shell.execute_reply.started":"2021-06-16T14:08:51.834069Z","shell.execute_reply":"2021-06-16T14:09:11.75201Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Split the dataset\nx_train, x_valid, y_train, y_valid = train_test_split(ids, labels, test_size=0.2, random_state=42)","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:10:53.772864Z","iopub.execute_input":"2021-06-16T14:10:53.773257Z","iopub.status.idle":"2021-06-16T14:10:53.786744Z","shell.execute_reply.started":"2021-06-16T14:10:53.773225Z","shell.execute_reply":"2021-06-16T14:10:53.785468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_train[0]","metadata":{"execution":{"iopub.status.busy":"2021-06-11T08:07:44.189118Z","iopub.execute_input":"2021-06-11T08:07:44.189558Z","iopub.status.idle":"2021-06-11T08:07:44.198804Z","shell.execute_reply.started":"2021-06-11T08:07:44.189525Z","shell.execute_reply":"2021-06-11T08:07:44.197541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create the datasets\ntrain_dataset = tf_dataset(x_train, y_train,BATCH_SIZE)\nvalid_dataset = tf_dataset(x_valid, y_valid,BATCH_SIZE)","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:11:02.98139Z","iopub.execute_input":"2021-06-16T14:11:02.981806Z","iopub.status.idle":"2021-06-16T14:11:03.161199Z","shell.execute_reply.started":"2021-06-16T14:11:02.981775Z","shell.execute_reply":"2021-06-16T14:11:03.160065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset","metadata":{"execution":{"iopub.status.busy":"2021-06-11T07:57:07.71566Z","iopub.execute_input":"2021-06-11T07:57:07.716102Z","iopub.status.idle":"2021-06-11T07:57:07.724629Z","shell.execute_reply.started":"2021-06-11T07:57:07.716055Z","shell.execute_reply":"2021-06-11T07:57:07.723505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Instanciate the model\nmodel = build_model()\nmodel.compile(loss='categorical_crossentropy', optimizer='Adam', metrics=['acc'])\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:11:09.684503Z","iopub.execute_input":"2021-06-16T14:11:09.684946Z","iopub.status.idle":"2021-06-16T14:11:10.246753Z","shell.execute_reply.started":"2021-06-16T14:11:09.684916Z","shell.execute_reply":"2021-06-16T14:11:10.245607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset[0]","metadata":{"execution":{"iopub.status.busy":"2021-06-11T07:57:08.350219Z","iopub.execute_input":"2021-06-11T07:57:08.353256Z","iopub.status.idle":"2021-06-11T07:57:08.889291Z","shell.execute_reply.started":"2021-06-11T07:57:08.352419Z","shell.execute_reply":"2021-06-11T07:57:08.887056Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set callbacks\ncallbacks = [\n    EarlyStopping(\n    patience=5,\n    min_delta=0.001,\n    restore_best_weights=True,\n    ),\n    #ModelCheckpoint('model.h5', verbose=1, save_best_only=True),\n    ReduceLROnPlateau(factor=0.1, patience=5, min_lr=1e-6)\n]\ntrain_steps = (len(x_train)//BATCH_SIZE) + 1\nvalid_steps = (len(x_valid)//BATCH_SIZE) + 1\n\n# Training\nhistory = model.fit(train_dataset,\n          steps_per_epoch=train_steps,\n          validation_steps=valid_steps,\n          validation_data=(valid_dataset),\n          epochs=EPOCHS,\n          callbacks=callbacks\n         )","metadata":{"execution":{"iopub.status.busy":"2021-06-16T14:15:37.156856Z","iopub.execute_input":"2021-06-16T14:15:37.157259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history_frame = pd.DataFrame(history.history)\nhistory_frame.loc[:, ['loss', 'val_loss']].plot()\nhistory_frame.loc[:, ['acc', 'val_acc']].plot();","metadata":{"execution":{"iopub.status.busy":"2021-06-11T07:57:08.892469Z","iopub.status.idle":"2021-06-11T07:57:08.893328Z"},"trusted":true},"execution_count":null,"outputs":[]}]}