{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"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\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\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","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Part 0 Unpacking the data"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"import os\nimport zipfile\n\ndef unzip(file, destination):\n    print('Unzipping to', destination)\n    with zipfile.ZipFile(file, 'r') as zip_ref:\n        zip_ref.extractall(destination)\n\nbase_dir = \"/kaggle/tmp/\"\ntrain_images_path = os.path.join(base_dir, \"images_training_rev1\")\ntest_images_path = os.path.join(base_dir, \"images_test_rev1\")\n\nif not os.path.exists(base_dir):\n    unzip('/kaggle/input/galaxy-zoo-the-galaxy-challenge/images_training_rev1.zip', base_dir)\n    unzip('/kaggle/input/galaxy-zoo-the-galaxy-challenge/images_test_rev1.zip', base_dir)\n    unzip('/kaggle/input/galaxy-zoo-the-galaxy-challenge/training_solutions_rev1.zip', base_dir)\n\nfor dirname, _, filenames in os.walk(base_dir):\n    for filename in filenames[:5]:\n        print(os.path.join(dirname, filename))\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import pandas as pd\n\ndef append_ext(filename):\n    \"\"\" Appends `.jpg` file extension to a filename \"\"\"\n    return f\"{filename}.jpg\"\n\ntrain_sol = pd.read_csv(\"/kaggle/tmp/training_solutions_rev1.csv\")\ntrain_sol[\"GalaxyID\"] = train_sol[\"GalaxyID\"].apply(append_ext)\ntrain_sol.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Part 1 Preparing the Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\ndatagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)\n\ntrain_generator = datagen.flow_from_dataframe(\n    dataframe=train_sol,\n    directory=train_images_path,\n    x_col=\"GalaxyID\",\n    y_col=[\"Class1.1\", \"Class1.2\", \"Class1.3\"],\n    clases=['Early type', 'Spiral', 'Artifact'],\n    subset=\"training\",\n    batch_size=32,\n    shuffle=False,\n    class_mode=\"raw\",\n    target_size=(224,224)\n)\n\nvalid_generator = datagen.flow_from_dataframe(\n    dataframe=train_sol,\n    directory=train_images_path,\n    x_col=\"GalaxyID\",\n    y_col=[\"Class1.1\", \"Class1.2\", \"Class1.3\"],\n    subset=\"validation\",\n    batch_size=32,\n    shuffle=False,\n    class_mode=\"raw\",\n    target_size=(224,224)\n)\n\ntrain_steps = np.ceil(train_generator.samples / train_generator.batch_size)\nval_steps = np.ceil(valid_generator.samples / valid_generator.batch_size)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Part 2: The Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras import layers, Model\nfrom tensorflow.keras.applications.vgg19 import VGG19\nfrom tensorflow.keras.applications.resnet50 import ResNet50\n\ndef build_model(num_classes):\n\n    pre_trained_model = VGG19(input_shape=(224,224,3),\n                            weights='imagenet',\n                            include_top=False)\n#     pre_trained_model = ResNet50(input_shape=(150,150,3),\n#                             weights='imagenet',\n#                             include_top=False)\n    \n\n    ### START YOUR CODE HERE ### (TODO 1)\n\n    # Flatten the output layer to 1 dimension\n    x = layers.Flatten()(pre_trained_model.output)\n\n\n    # Add a fully connected layer with 1024 hidden units and ReLU activation (x2)\n    x = layers.Dense(1024, activation='relu')(x)\n    x = layers.Dense(1024, activation='relu')(x)\n\n\n    # Add a dropout rate of 0.2\n    x = layers.Dropout(0.2)(x)\n\n\n    # Add a final softmax layer for classification\n    output = layers.Dense(num_classes, activation='softmax')(x)\n\n    # Define the model\n    model = Model( pre_trained_model.input, output )\n\n    ### END YOUR CODE HERE ###\n\n    return model, pre_trained_model\n\nmodel, pre_trained_model = build_model(3)\n# print(model.summary())\n\nfor layer in pre_trained_model.layers:\n    layer.trainable = False\n\n# print(model.summary())","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Part 3 Compiling the Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"from tensorflow.keras.optimizers import Adam\nfrom keras import backend as K\n\ndef root_mean_squared_error(y_true, y_pred):\n        return K.sqrt(K.mean(K.square(y_pred - y_true)))\n\n\n### START YOUR CODE HERE ### (TODO 2)\n\nmodel.compile(loss='categorical_crossentropy',\n              optimizer=Adam(lr=1e-3),\n              metrics=['accuracy'])\n#               metrics=[root_mean_squared_error])\n\n### END YOUR CODE HERE ###","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#@title Definition: plot_history()\nfrom matplotlib import pyplot as plt\n\ndef plot_history(history):\n    # Retrieve a list of accuracy results on training and test data sets for each training epoch\n\n    acc = history.history['accuracy']\n    val_acc = history.history['val_accuracy']\n#     acc = history.history['root_mean_squared_error']\n#     val_acc = history.history['val_root_mean_squared_error']\n\n    # Retrieve a list of list results on training and test data\n    # sets for each training epoch\n    loss = history.history['loss']\n    val_loss = history.history['val_loss']\n\n    # Get number of epochs\n    epochs = range(len(acc))\n\n    # Plot training and validation accuracy per epoch\n    plt.figure(dpi=150)\n    plt.plot(epochs, acc)\n    plt.plot(epochs, val_acc)\n    plt.ylabel('Accuracy')\n    plt.ylim([0,1])\n    #plt.title('Training and validation accuracy')\n    plt.legend( ('training', 'validation') )\n    plt.figure()\n\n    # Plot training and validation loss per epoch\n    plt.figure(dpi=150)\n    plt.plot(epochs, loss)\n    plt.plot(epochs, val_loss)\n    plt.ylabel('Loss')\n    #plt.yscale('log')\n    #plt.title('Training and validation loss')\n   \n#plot_history(history)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Part 4 Model Training"},{"metadata":{"trusted":true},"cell_type":"code","source":"tf_history = model.fit_generator(train_generator,\n#                                  steps_per_epoch=256,\n                                 steps_per_epoch=train_steps,\n                                 epochs=2,\n                                 validation_data=valid_generator,\n#                                  validation_steps=256,\n                                 validation_steps=val_steps,\n                                 verbose=2)\n\nplot_history( tf_history )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for layer in pre_trained_model.layers[-5:]:\n    layer.trainable = True\n    \nmodel.compile(loss='categorical_crossentropy',\n              optimizer=Adam(lr=1e-4),\n              metrics=['accuracy'])\n\n# print(model.summary())\n    \ntf_history = model.fit_generator(train_generator,\n#                                  steps_per_epoch=256,\n                                 steps_per_epoch=train_steps,\n                                 epochs=3,\n                                 validation_data=valid_generator,\n#                                  validation_steps=256,\n                                 validation_steps=val_steps,\n                                 verbose=2)\n\nplot_history( tf_history )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# for layer in pre_trained_model.layers:\n#     layer.trainable = True\n    \n# model.compile(loss='categorical_crossentropy',\n#               optimizer=Adam(lr=1e-3),\n#               metrics=['accuracy'])\n\n# # print(model.summary())\n    \n# tf_history = model.fit_generator(train_generator,\n# #                                  steps_per_epoch=256,\n#                                  steps_per_epoch=train_steps,\n#                                  epochs=3,\n#                                  validation_data=valid_generator,\n# #                                  validation_steps=256,\n#                                  validation_steps=val_steps,\n#                                  verbose=2)\n\n# plot_history( tf_history )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for layer_idx, layer in enumerate(model.layers):\n  # check if convolutional layer\n  if not 'convolutional' in str(layer.__class__):\n    continue\n  print(layer_idx, layer.name, layer.output.shape)\n\nvisualization_model = Model(model.input, model.layers[1].output)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"visualization_model = Model(model.input, model.layers[1].output)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def show(img):\n  '''display image'''\n  plt.figure(figsize=(8,8))\n  plt.grid(False)\n  plt.axis('Off')\n  plt.imshow(img)\n  plt.show()\n\nnext_data = valid_generator.next()\nimg = next_data[0][0]\nshow(img)\n\n# expand dimensions so that it fakes a batch containing a single sample\nimg = np.expand_dims(img, axis=0)\n\nprint(f\"Ground truth:\\t   {next_data[1][0]}\")\nprint(f\"Model prediction: {model.predict(img)}\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"feature_maps = visualization_model.predict(img)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"square = 8\nfig = plt.gcf()\nfig.set_size_inches(square*2,square*2)\nidx = 1\nfor _ in range(square):\n  for _ in range(square):\n    sp = plt.subplot(square, square, idx)\n    sp.axis('Off')\n    sp.title.set_text(str(idx-1))\n    plt.imshow(feature_maps[0, :, :, idx-1])\n    idx += 1\n\n# plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"layer_indices = [1, 2, 4, 5, 7, 8, 9, 10, 12, 13, 14, 15, 17, 18, 19, 20]\nvisualization_model = Model( model.input, [model.layers[idx].output for idx in layer_indices] )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#@title Plot feature maps\nplt.imshow(img[0])\nplt.axis('Off')\nplt.title('Input Image')\nplt.show()\n\nsquare = 8\nfeature_maps = visualization_model.predict(img)\nfor layer_idx, fmap in enumerate(feature_maps):\n    fig = plt.gcf()\n    fig.set_size_inches(square*2, square*2)\n    fig.suptitle(model.layers[layer_indices[layer_idx]].name)\n    idx = 0\n    \n    for _ in range(square):\n        for _ in range(2):\n            fm = fmap[0, :, :, idx]\n            sp = plt.subplot(square, square, idx+1)\n            sp.axis('Off')\n            sp.title.set_text(str(idx))\n            plt.imshow(fm)\n            idx += 1\n\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#@title Plot average feature maps\nplt.imshow(img[0])\nplt.axis('Off')\nplt.title('Input Image')\nplt.show()\n\nfig=plt.figure(figsize=(150, 150))\nfor layer_idx, fmap in enumerate(feature_maps[:5]):\n    sp = fig.add_subplot(1, len(feature_maps), layer_idx+1)\n    sp.axis('Off')\n    sp.title.set_text(model.layers[ layer_indices[layer_idx] ].name)\n    plt.imshow(np.squeeze(fmap.mean(axis=-1)))\n    \nfig=plt.figure(figsize=(150, 150))\nfor layer_idx, fmap in enumerate(feature_maps[5:10]):\n    sp = fig.add_subplot(1, len(feature_maps), layer_idx+1)\n    sp.axis('Off')\n    sp.title.set_text(model.layers[ layer_indices[layer_idx] ].name)\n    plt.imshow(np.squeeze(fmap.mean(axis=-1)))\n    \nfig=plt.figure(figsize=(150, 150))\nfor layer_idx, fmap in enumerate(feature_maps[10:15]):\n    sp = fig.add_subplot(1, len(feature_maps), layer_idx+1)\n    sp.axis('Off')\n    sp.title.set_text(model.layers[ layer_indices[layer_idx] ].name)\n    plt.imshow(np.squeeze(fmap.mean(axis=-1)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.metrics import classification_report, confusion_matrix\n\nY_pred = model.predict_generator(valid_generator, val_steps)\ny_pred = np.argmax(Y_pred, axis=1)\ny_true = np.argmax(valid_generator.labels, axis=1)\n\nprint('Confusion Matrix')\nprint(confusion_matrix(y_true, y_pred))\n\nprint('Classification Report')\ntarget_names = ['Early type', 'Spiral', 'Artifact']\nprint(classification_report(y_true, y_pred, target_names=target_names))","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}