{"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":"import tensorflow as tf\nimport pandas as pd\nimport numpy as np\nfrom tensorflow.keras.applications.resnet import ResNet50, preprocess_input\nfrom tensorflow.keras.models import Sequential, load_model\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten\nfrom tensorflow.keras.callbacks import ModelCheckpoint\nimport matplotlib.pyplot as plt\nfrom PIL import Image\nimport os\nimport math\nimport shutil\nfrom sklearn.preprocessing import OneHotEncoder\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix\n\n# Importando as bibliotecas necessárias\n\n# Importando TensorFlow para computação numérica e treinamento de redes neurais\nimport tensorflow as tf\n\n# Importando Pandas para manipulação de dados\nimport pandas as pd\n\n# Importando NumPy para cálculos numéricos\nimport numpy as np\n\n# Importando ResNet50 e preprocess_input para usar a arquitetura ResNet50 pré-treinada\nfrom tensorflow.keras.applications.resnet import ResNet50, preprocess_input\n\n# Importando Sequential, load_model, Dense, Dropout, Flatten e ModelCheckpoint do Keras para construção e treinamento de redes neurais\nfrom tensorflow.keras.models import Sequential, load_model\nfrom tensorflow.keras.layers import Dense, Dropout, Flatten\nfrom tensorflow.keras.callbacks import ModelCheckpoint\n\n# Importando Matplotlib para visualização de gráficos\nimport matplotlib.pyplot as plt\n\n# Importando PIL para processamento de imagens\nfrom PIL import Image\n\n# Importando módulos para operações de sistema de arquivos, cálculos matemáticos e manipulação de arquivos\nimport os\nimport math\nimport shutil\n\n# Importando classes para pré-processamento de dados e avaliação de modelos de aprendizado de máquina\nfrom sklearn.preprocessing import OneHotEncoder\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix\n\n# Fim da importação das bibliotecas necessárias\n","metadata":{"execution":{"iopub.status.busy":"2023-06-20T01:19:56.907597Z","iopub.execute_input":"2023-06-20T01:19:56.907962Z","iopub.status.idle":"2023-06-20T01:19:56.918358Z","shell.execute_reply.started":"2023-06-20T01:19:56.907933Z","shell.execute_reply":"2023-06-20T01:19:56.917241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Carregando os rótulos das raças dos cães a partir de um arquivo CSV usando o Pandas\ny_df = pd.read_csv('/kaggle/input/dog-breed-identification/labels.csv')\n\n# Convertendo os rótulos das raças em uma matriz NumPy e redimensionando para ter uma única coluna\ny_breed = np.asarray(y_df['breed']).reshape(-1, 1)\n\n# Criando uma instância do codificador OneHotEncoder e aplicando-o aos rótulos das raças\nohe = OneHotEncoder(sparse_output=False)\ny = ohe.fit_transform(y_breed)\n\n# Mapeando os rótulos das raças para os índices correspondentes no vetor codificado one-hot\nlabels_mapping = {np.argmax(y[i]): y_df.loc[i, 'breed'] for i in range(len(y))}\n\n# Definindo a altura e a largura desejadas para as imagens\nimage_height = 50\nimage_width = 50\n\n# Carregando as imagens dos cães e redimensionando-as para a altura e a largura especificadas\nx = []\nfor i in y_df['id']:\n  image = Image.open('/kaggle/input/dog-breed-identification/train/' + i + '.jpg')\n  x.append(np.array(image.resize((image_height, image_width))))\nx = np.asarray(x)","metadata":{"execution":{"iopub.status.busy":"2023-06-20T01:04:25.179906Z","iopub.execute_input":"2023-06-20T01:04:25.180264Z","iopub.status.idle":"2023-06-20T01:05:48.108094Z","shell.execute_reply.started":"2023-06-20T01:04:25.180235Z","shell.execute_reply":"2023-06-20T01:05:48.107072Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Dividindo os dados em conjuntos de treinamento e teste usando a função train_test_split do scikit-learn\nx_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=7, shuffle=True, stratify=y)\n    ","metadata":{"execution":{"iopub.status.busy":"2023-06-20T01:05:59.799975Z","iopub.execute_input":"2023-06-20T01:05:59.800347Z","iopub.status.idle":"2023-06-20T01:06:01.291084Z","shell.execute_reply.started":"2023-06-20T01:05:59.800298Z","shell.execute_reply":"2023-06-20T01:06:01.290112Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Cria uma instância do modelo ResNet50 pré-treinado com os pesos da ImageNet\nRN50 = ResNet50(include_top=False, weights='imagenet', input_shape=(image_height, image_width, 3))\n\n# Obtém os recursos extraídos das imagens de treinamento usando o modelo ResNet50\nx_train_features = RN50.predict(preprocess_input(x_train))\n\n# Obtém os recursos extraídos das imagens de teste usando o modelo ResNet50\nx_test_features = RN50.predict(preprocess_input(x_test))\n","metadata":{"execution":{"iopub.status.busy":"2023-06-20T01:06:22.705502Z","iopub.execute_input":"2023-06-20T01:06:22.705849Z","iopub.status.idle":"2023-06-20T01:06:54.889128Z","shell.execute_reply.started":"2023-06-20T01:06:22.705822Z","shell.execute_reply":"2023-06-20T01:06:54.888102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Cria um modelo sequencial para classificação de raças de cães\nmodel = Sequential()\n\n# Adiciona uma camada de achatamento (flatten) para converter os recursos extraídos em um vetor unidimensional\nmodel.add(Flatten(input_shape=x_train_features.shape[1:]))\n\n# Aplica regularização Dropout para evitar overfitting, descartando aleatoriamente 50% dos neurônios\nmodel.add(Dropout(0.5))\n\n# Adiciona uma camada densamente conectada com 240 unidades e função de ativação ReLU\nmodel.add(Dense(units=240, activation='relu'))\n\n# Aplica regularização Dropout, descartando aleatoriamente 30% dos neurônios\nmodel.add(Dropout(0.3))\n\n# Adiciona a camada de saída com 120 unidades (correspondendo às 120 raças de cães) e função de ativação softmax\nmodel.add(Dense(units=120, activation='softmax'))\n\n# Imprime um resumo do modelo, mostrando a arquitetura, número de parâmetros e tamanhos das camadas\nprint(model.summary())\n","metadata":{"execution":{"iopub.status.busy":"2023-06-20T01:07:01.126807Z","iopub.execute_input":"2023-06-20T01:07:01.127162Z","iopub.status.idle":"2023-06-20T01:07:01.455501Z","shell.execute_reply.started":"2023-06-20T01:07:01.127132Z","shell.execute_reply":"2023-06-20T01:07:01.454765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Compila o modelo, especificando o otimizador, a função de perda e as métricas a serem usadas\nmodel.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy'])\n\n# Define um callback para salvar o melhor modelo com base na precisão de validação\nmc = ModelCheckpoint('best_model.h5', monitor='val_accuracy', mode='max', verbose=1, save_best_only=True)\n\n# Define o tamanho do lote e o número de épocas de treinamento\nbatch_size = 256\nnb_epochs = 20\n\n# Treina o modelo usando os recursos extraídos das imagens de treinamento\n# e as classes de treinamento, com validação usando os recursos extraídos das imagens de teste e as classes de teste\nhistory = model.fit(x_train_features, y_train, batch_size=batch_size, epochs=nb_epochs,\n                    validation_data=[x_test_features, y_test], callbacks=[mc])\n\n# Carrega o melhor modelo salvo durante o treinamento\nsaved_model = load_model('best_model.h5')\n\n# Plota as curvas de perda (loss) do treinamento e da validação ao longo das épocas\nplt.plot(history.history['loss'], label='train')\nplt.plot(history.history['val_loss'], label='test')\nplt.legend()\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2023-06-20T01:07:23.895540Z","iopub.execute_input":"2023-06-20T01:07:23.895955Z","iopub.status.idle":"2023-06-20T01:07:35.733325Z","shell.execute_reply.started":"2023-06-20T01:07:23.895923Z","shell.execute_reply":"2023-06-20T01:07:35.732422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Faz a previsão das classes das imagens de teste usando o modelo salvo\ny_test_pred = saved_model.predict(x_test_features)\n\n# Obtém o índice da classe com maior probabilidade de cada previsão\ny_test_pred_id = np.argmax(y_test_pred, axis=1).reshape(-1, 1)\n\n# Obtém o índice da classe real de cada imagem de teste\ny_test_id = np.argmax(y_test, axis=1).reshape(-1, 1)\n\n# Cria um DataFrame de matriz de confusão usando as previsões e as classes reais\ndf_cm = pd.DataFrame(confusion_matrix(y_test_id, y_test_pred_id),\n                     index=[labels_mapping[i] for i in range(len(labels_mapping))],\n                     columns=[labels_mapping[i] for i in range(len(labels_mapping))])\n\n# Calcula as classes mais confusas, ou seja, as classes que têm maior confusão com outras classes\nmost_confused = []\nfor i in range(len(labels_mapping)):\n    most_confused.append((df_cm.index[i], df_cm.iloc[i, df_cm.columns != df_cm.index[i]].idxmax(),\n                          df_cm.iloc[i, df_cm.columns != df_cm.index[i]].max(axis=0),\n                          df_cm.iloc[i].sum(axis=0)))\nmost_confused.sort(key=lambda x: x[2], reverse=True)\n\n# Imprime as classes mais confusas\nprint(most_confused)\n","metadata":{"execution":{"iopub.status.busy":"2023-06-20T01:08:14.967343Z","iopub.execute_input":"2023-06-20T01:08:14.967839Z","iopub.status.idle":"2023-06-20T01:08:15.682789Z","shell.execute_reply.started":"2023-06-20T01:08:14.967808Z","shell.execute_reply":"2023-06-20T01:08:15.681702Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Inicializa listas para armazenar os dados de teste e as imagens de submissão\ntest = []\nsubmission_images = []\n\n# Itera sobre os arquivos no diretório de teste\nfor filename in os.listdir('/kaggle/input/dog-breed-identification/test/'):\n    # Abre a imagem e a adiciona à lista de imagens de submissão\n    image = Image.open('/kaggle/input/dog-breed-identification/test/' + str(filename))\n    submission_images.append(filename.split('.')[0])\n    \n    # Redimensiona a imagem e a adiciona à lista de dados de teste\n    test.append(np.array(image.resize((image_height, image_width))))\ntest = np.asarray(test)\n\n# Imprime a forma dos dados de teste\nprint(test.shape)\n\n# Obtém os recursos extraídos das imagens de teste usando o modelo ResNet50\ntest_features = RN50.predict(preprocess_input(test))\n\n# Faz a previsão das probabilidades das classes para as imagens de teste usando o modelo salvo\nsubmission_ohe = saved_model.predict(test_features)\n\n# Cria um DataFrame para a submissão, com as probabilidades das classes e os IDs das imagens\nsubmission = pd.DataFrame(submission_ohe, columns=[labels_mapping[i] for i in range(len(labels_mapping))])\nsubmission.insert(0, 'id', submission_images)\n\n# Salva o DataFrame como um arquivo CSV para submissão\nsubmission.to_csv('/kaggle/working/submission.csv', index=False)\n","metadata":{"execution":{"iopub.status.busy":"2023-06-20T01:08:21.870710Z","iopub.execute_input":"2023-06-20T01:08:21.871071Z","iopub.status.idle":"2023-06-20T01:10:33.250538Z","shell.execute_reply.started":"2023-06-20T01:08:21.871044Z","shell.execute_reply":"2023-06-20T01:10:33.249576Z"},"trusted":true},"execution_count":null,"outputs":[]}]}