{"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":"markdown","source":"#### Francisco Igor da Silva Lima - 507536\n\nPara executar o notebook é necessário ter uma conta no kaggle e fazer o fork do mesmo\n\nO desafio escolhido é Dog Breed Identification, que consiste em descobrir qual é raça de cachorro, ou seja é um problema de classificação multi-classe, são em torno de 120 classes","metadata":{"_uuid":"645c3c997d5f2883f49ac63bf73ad31e29ae06ab"}},{"cell_type":"code","source":"# import das bibliotecas\n\nimport numpy as np\nimport pandas as pd\n\nnp.random.seed(2018)\n\n%matplotlib inline\nimport matplotlib.pyplot as plt\n\nimport keras\nfrom keras import regularizers\nfrom keras.applications.resnet50 import ResNet50\nfrom keras.models import Model\nfrom keras.layers import Dense, Dropout, Flatten\n\nimport os\nfrom tqdm import tqdm\nfrom sklearn import preprocessing\nfrom sklearn.model_selection import train_test_split\nimport cv2\nfrom keras.preprocessing.image import ImageDataGenerator","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-08-06T00:09:49.063407Z","iopub.execute_input":"2021-08-06T00:09:49.063758Z","iopub.status.idle":"2021-08-06T00:09:50.034289Z","shell.execute_reply.started":"2021-08-06T00:09:49.063701Z","shell.execute_reply":"2021-08-06T00:09:50.033504Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv('../input/dog-breed-identification/labels.csv') # file with the names of the images and its breed for training\ndf_test = pd.read_csv('../input/dog-breed-identification/sample_submission.csv') ## file with with the name of the images for testing","metadata":{"_uuid":"9918f2c8d3556e75cc94cc41fc4f3323bea3c8b3","execution":{"iopub.status.busy":"2021-08-06T00:09:53.956075Z","iopub.execute_input":"2021-08-06T00:09:53.956388Z","iopub.status.idle":"2021-08-06T00:09:55.092909Z","shell.execute_reply.started":"2021-08-06T00:09:53.956323Z","shell.execute_reply":"2021-08-06T00:09:55.092071Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train.head()","metadata":{"_uuid":"26ca1f0a72c44ec28803b111778bfee69bc02998","execution":{"iopub.status.busy":"2021-08-06T00:09:57.119764Z","iopub.execute_input":"2021-08-06T00:09:57.120096Z","iopub.status.idle":"2021-08-06T00:09:57.145053Z","shell.execute_reply.started":"2021-08-06T00:09:57.120035Z","shell.execute_reply":"2021-08-06T00:09:57.144067Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test.head()","metadata":{"_uuid":"063c723146ad83b0f5b0ea8e376b89129c95ffc4","execution":{"iopub.status.busy":"2021-08-06T00:09:59.748224Z","iopub.execute_input":"2021-08-06T00:09:59.748581Z","iopub.status.idle":"2021-08-06T00:09:59.884078Z","shell.execute_reply.started":"2021-08-06T00:09:59.748517Z","shell.execute_reply":"2021-08-06T00:09:59.882913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"targets_series = pd.Series(df_train['breed'])\none_hot = pd.get_dummies(targets_series, sparse = True)","metadata":{"_uuid":"e0293ffd5ee7ca8717f134bfc654623ae940b1bc","execution":{"iopub.status.busy":"2021-08-06T00:10:02.496081Z","iopub.execute_input":"2021-08-06T00:10:02.496401Z","iopub.status.idle":"2021-08-06T00:10:02.559367Z","shell.execute_reply.started":"2021-08-06T00:10:02.496343Z","shell.execute_reply":"2021-08-06T00:10:02.558689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"one_hot_labels = np.asarray(one_hot)","metadata":{"_uuid":"a2621ce3a02d13f4e651222233648bd8a814059c","execution":{"iopub.status.busy":"2021-08-06T00:10:04.723892Z","iopub.execute_input":"2021-08-06T00:10:04.724219Z","iopub.status.idle":"2021-08-06T00:10:04.731473Z","shell.execute_reply.started":"2021-08-06T00:10:04.724164Z","shell.execute_reply":"2021-08-06T00:10:04.730386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"im_size = 197  # tamanho da entrada","metadata":{"_uuid":"fb65dd8cd12273701922e56f4d0e249cad650cfc","execution":{"iopub.status.busy":"2021-08-06T00:11:52.352590Z","iopub.execute_input":"2021-08-06T00:11:52.353071Z","iopub.status.idle":"2021-08-06T00:11:52.360012Z","shell.execute_reply.started":"2021-08-06T00:11:52.352834Z","shell.execute_reply":"2021-08-06T00:11:52.359122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_train = []\ny_train = []\nx_test = []","metadata":{"_uuid":"50c66c7abdeb4478ac52e1013b7b5867ba243fa3","execution":{"iopub.status.busy":"2021-08-06T00:10:17.101841Z","iopub.execute_input":"2021-08-06T00:10:17.102327Z","iopub.status.idle":"2021-08-06T00:10:17.106605Z","shell.execute_reply.started":"2021-08-06T00:10:17.102091Z","shell.execute_reply":"2021-08-06T00:10:17.105760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fazendo a leitura dos dados de treino\n\ni = 0 \nfor f, breed in tqdm(df_train.values):\n    img = cv2.imread('../input/dog-breed-identification/train/{}.jpg'.format(f))\n    x_train.append(cv2.resize(img, (im_size, im_size)))\n    label = one_hot_labels[i]\n    y_train.append(label)\n    i += 1","metadata":{"_uuid":"d09eef3914e7a307bd1a1f92ec604db4d54ead5d","execution":{"iopub.status.busy":"2021-08-06T00:10:18.643372Z","iopub.execute_input":"2021-08-06T00:10:18.643721Z","iopub.status.idle":"2021-08-06T00:11:52.342967Z","shell.execute_reply.started":"2021-08-06T00:10:18.643667Z","shell.execute_reply":"2021-08-06T00:11:52.341229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del df_train # deletando pra economizar espaço","metadata":{"_uuid":"0d0b4ac7910368aa1806e7544f235da733e85ebc","execution":{"iopub.status.busy":"2021-08-06T00:11:52.344685Z","iopub.execute_input":"2021-08-06T00:11:52.344958Z","iopub.status.idle":"2021-08-06T00:11:52.350375Z","shell.execute_reply.started":"2021-08-06T00:11:52.344913Z","shell.execute_reply":"2021-08-06T00:11:52.349232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fazendo a leitura dos dados de treino\n\nfor f in tqdm(df_test['id'].values):\n    img = cv2.imread('../input/dog-breed-identification/test/{}.jpg'.format(f))\n    x_test.append(cv2.resize(img, (im_size, im_size)))","metadata":{"_uuid":"8372e0ee527f043df2ec267845329cbf538d37ce","execution":{"iopub.status.busy":"2021-08-06T00:12:02.275638Z","iopub.execute_input":"2021-08-06T00:12:02.275935Z","iopub.status.idle":"2021-08-06T00:13:41.944118Z","shell.execute_reply.started":"2021-08-06T00:12:02.275880Z","shell.execute_reply":"2021-08-06T00:13:41.941522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Criando uma variável para saber a quantidade classes que temos no dataset\nnum_class = 120","metadata":{"_uuid":"f9f86326b40aa50c5d4d196e6fac15f8eb94c890","execution":{"iopub.status.busy":"2021-08-06T00:13:41.946455Z","iopub.execute_input":"2021-08-06T00:13:41.946770Z","iopub.status.idle":"2021-08-06T00:13:41.951587Z","shell.execute_reply.started":"2021-08-06T00:13:41.946718Z","shell.execute_reply":"2021-08-06T00:13:41.950276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train, X_valid, Y_train, Y_valid = train_test_split(x_train, y_train, shuffle=True,  test_size=0.2, random_state=1)","metadata":{"_uuid":"8e9078701b87ee09b7b3a235bc9262dc3ab167df","execution":{"iopub.status.busy":"2021-08-06T00:13:41.953977Z","iopub.execute_input":"2021-08-06T00:13:41.954448Z","iopub.status.idle":"2021-08-06T00:13:41.968226Z","shell.execute_reply.started":"2021-08-06T00:13:41.954235Z","shell.execute_reply":"2021-08-06T00:13:41.967642Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del x_train, y_train","metadata":{"_uuid":"6f1464f0497cbf34d7a756d3133d59e2d339af19","execution":{"iopub.status.busy":"2021-08-06T00:13:41.969704Z","iopub.execute_input":"2021-08-06T00:13:41.970179Z","iopub.status.idle":"2021-08-06T00:13:41.974403Z","shell.execute_reply.started":"2021-08-06T00:13:41.969962Z","shell.execute_reply":"2021-08-06T00:13:41.973627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Sobre a arquitetura\n\nA rede escolhida é a [ResNet50](https://arxiv.org/abs/1512.03385), ela foi escolhida por ser uma rede bastante conhecida pela comunidade academica, e por ser bem posicionada no desafio do [ImageNet](https://www.image-net.org/).\n\nFoi também utilizada Data augmentation, para aumentar a quantidade de imagens, além de comparar dois otimizadores, o [RMSProp](https://keras.io/api/optimizers/rmsprop/) e o [SGD](https://keras.io/api/optimizers/sgd/), e um dropout de 50% na última camada.\n\nOs resultados com RMSProp foram péssimos, a acurácia não chegou a apenas 0.05, e um loss de 7.1323, o que é altissimo. Enquanto com SGD obtivemos resultados mais satisfatórios, como uma acurácia de 0.9727 e um [loss](https://keras.io/api/losses/probabilistic_losses/#categoricalcrossentropy-class) de apenas 0.5652, o que é um valor alto para loss, mas bem melhor que usando RMSProp.","metadata":{"_uuid":"2b690d397223f8b553847f5a10d292ba3e3ca4c3"}},{"cell_type":"code","source":"datagen = ImageDataGenerator(width_shift_range=0.2,\n                            height_shift_range=0.2,\n                            zoom_range=0.2,\n                            rotation_range=30,\n                            vertical_flip=False,\n                            horizontal_flip=True)\n\n\ndatagen.fit(X_train)","metadata":{"_uuid":"c1045af204c54069db458aa163255659010882fb","execution":{"iopub.status.busy":"2021-08-06T00:14:35.328202Z","iopub.execute_input":"2021-08-06T00:14:35.328512Z","iopub.status.idle":"2021-08-06T00:14:40.405799Z","shell.execute_reply.started":"2021-08-06T00:14:35.328457Z","shell.execute_reply":"2021-08-06T00:14:40.404870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_my_model(optimizer):\n    base_model = ResNet50(weights=\"../input/keras-pretrained-models/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5\",include_top=False, input_shape=(im_size, im_size, 3))\n    dropout = base_model.output\n    dropout = Dropout(0.5)(dropout)\n    model_with_dropout = Model(inputs=base_model.input, outputs=dropout)\n    \n    x = base_model.output\n    x = Flatten()(x)\n    predictions = Dense(num_class, activation='softmax',\n                        kernel_regularizer=regularizers.l2(0.0015),\n                        activity_regularizer=regularizers.l1(0.0015))(x)\n    \n    \n    \n    my_model = Model(inputs=base_model.input, outputs=predictions)\n    \n#     for layer in my_model.layers:\n#         layer.treinable = False\n    \n    my_model.compile(optimizer=optimizer,\n              loss='categorical_crossentropy', \n              metrics=['accuracy'])\n    return my_model\n","metadata":{"_uuid":"41f5dfae4bbfd648400f89d878c5c37752f0136e","execution":{"iopub.status.busy":"2021-08-06T00:14:40.407398Z","iopub.execute_input":"2021-08-06T00:14:40.407704Z","iopub.status.idle":"2021-08-06T00:14:40.416313Z","shell.execute_reply.started":"2021-08-06T00:14:40.407659Z","shell.execute_reply":"2021-08-06T00:14:40.415330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def gerar_grafico(historia, titulo):\n    plt.plot(historia.history['acc'])\n    plt.plot(historia.history['val_acc'])\n    plt.title('Acurácia ' + titulo)\n    plt.ylabel('Acurácia')\n    plt.xlabel('Épocas')\n    plt.legend(['treino', 'validação'], loc='upper left')\n    plt.show()\n    plt.plot(historia.history['loss'])\n    plt.plot(historia.history['val_loss'])\n    plt.title('Loss ' + titulo)\n    plt.ylabel('Loss')\n    plt.xlabel('Épocas')\n    plt.legend(['treino', 'validação'], loc='upper left')\n    plt.show()","metadata":{"_uuid":"bff918d1418425c5a3f04e87d1406f3558883600","execution":{"iopub.status.busy":"2021-08-06T00:14:40.417940Z","iopub.execute_input":"2021-08-06T00:14:40.418361Z","iopub.status.idle":"2021-08-06T00:14:40.429042Z","shell.execute_reply.started":"2021-08-06T00:14:40.418191Z","shell.execute_reply":"2021-08-06T00:14:40.428373Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_generator = datagen.flow(np.array(X_train), np.array(Y_train), \n                               batch_size=32) ","metadata":{"_uuid":"0153f85d4e7d3a3e45925fddf963e6f9463d6f8a","execution":{"iopub.status.busy":"2021-08-06T00:14:41.431197Z","iopub.execute_input":"2021-08-06T00:14:41.431520Z","iopub.status.idle":"2021-08-06T00:14:44.007504Z","shell.execute_reply.started":"2021-08-06T00:14:41.431459Z","shell.execute_reply":"2021-08-06T00:14:44.006583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_rmsprop_com_regularizador = create_my_model(optimizer='rmsprop')\nmodel_sgd_com_regularizador = create_my_model(optimizer='sgd')","metadata":{"_uuid":"26a34b47e785eeb8478ac60910acb817b2ff6f7a","execution":{"iopub.status.busy":"2021-08-06T00:14:44.009007Z","iopub.execute_input":"2021-08-06T00:14:44.009460Z","iopub.status.idle":"2021-08-06T00:15:10.382534Z","shell.execute_reply.started":"2021-08-06T00:14:44.009251Z","shell.execute_reply":"2021-08-06T00:15:10.381733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history_rmsprop_com_regularizador = model_rmsprop_com_regularizador.fit_generator(\n    train_generator,\n    epochs=10, steps_per_epoch=len(X_train) / 18, #len(X_train) / 18,\n    validation_data=(np.array(X_train), np.array(Y_train)), validation_steps=len(X_valid) / 18)\n\npreds = model_rmsprop_com_regularizador.predict(np.array(x_test), verbose=1)\n\ngerar_grafico(history_rmsprop_com_regularizador, \n              \"ResNet50 with RMSprop\")\n\nsub = pd.DataFrame(preds)\ncol_names = one_hot.columns.values\nsub.columns = col_names\nsub.insert(0, 'id', df_test['id'])\nsub.head(5)\n\nsub.to_csv(\"predictions_resnet50_rmsprop.csv\")\n\nmodel_rmsprop_com_regularizador.save('resnet50_rmsprop.h5')","metadata":{"_uuid":"b814e1c53da62f7fca5bf9c62b056aee8a6c2677","execution":{"iopub.status.busy":"2021-08-06T00:15:10.384178Z","iopub.execute_input":"2021-08-06T00:15:10.384468Z","iopub.status.idle":"2021-08-06T00:43:39.366705Z","shell.execute_reply.started":"2021-08-06T00:15:10.384406Z","shell.execute_reply":"2021-08-06T00:43:39.365505Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history_sgd_com_regularizador = model_sgd_com_regularizador.fit_generator(\n    train_generator,\n    epochs=10, steps_per_epoch=len(X_train) / 18, #len(X_train) / 18,\n    validation_data=(np.array(X_train), np.array(Y_train)), validation_steps=len(X_valid) / 18)\n\npreds = model_sgd_com_regularizador.predict(np.array(x_test), verbose=1)\n\ngerar_grafico(history_sgd_com_regularizador, \n              \"ResNet50 com SGD, data augmentation e Regularizador\")\n\nsub = pd.DataFrame(preds)\ncol_names = one_hot.columns.values\nsub.columns = col_names\nsub.insert(0, 'id', df_test['id'])\nsub.head(5)\n\nsub.to_csv(\"output_sgd_v2_com_data_augmentation_e_regularizador.csv\")\n\nmodel_sgd_com_regularizador.save('sgd_v2_com_data_augmentation_e_regularizador.h5')","metadata":{"_uuid":"25b4e347b635cff385784a5ac585b26bf0d4369d","execution":{"iopub.status.busy":"2021-08-06T00:43:39.368609Z","iopub.execute_input":"2021-08-06T00:43:39.368911Z","iopub.status.idle":"2021-08-06T01:10:45.348959Z","shell.execute_reply.started":"2021-08-06T00:43:39.368864Z","shell.execute_reply":"2021-08-06T01:10:45.348151Z"},"trusted":true},"execution_count":null,"outputs":[]}]}