{"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":"<a href=\"https://colab.research.google.com/github/soaresbru/bootcamp-Unimed-Data-science/blob/main/cachorro_ou_gato.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>","metadata":{"id":"view-in-github"}},{"cell_type":"markdown","source":"## Redes Neurais: Saber se é cachorro ou gato","metadata":{"id":"l-ZlbtJtaeF9"}},{"cell_type":"markdown","source":"Neste notebook serão realizadas as principais etapas para aplicar redes neurais para saber se uma imagem é de cachorro ou gato, o ideia é ver qual será um quantidade pequena de dados que dá para ver que a rede está aprendendo e não apenas um chute.","metadata":{"id":"kcRuhH6oM4Ds"}},{"cell_type":"markdown","source":"Os dados para realizar esse notebook foram retirados do Kaggle: https://www.kaggle.com/competitions/dogs-vs-cats\n","metadata":{"id":"tcyolh2xbraH"}},{"cell_type":"markdown","source":"Como todas as imagens juntas era demais, levaria muito tempo para o processamento  \nEntão decidi fazer com cerca de 300 imagens de gatos e 300 imagens de cachorro, mas eram poucas imagens e o modelo não conseguiu aprender.   \nDepois com cerca de 700 imagens de gatos e 700 imagens de cachorro o modelo começou a aprender bem","metadata":{"id":"PU1Fjv5FiCw_"}},{"cell_type":"markdown","source":"## Conteúdo\n1. Importando as bibliotecas\n2. Leitura das bases consumidas\n3. Manipulando os dados de treino\n4. Construindo o modelo\n5. Criando Callback\n6. Dividindo em treino e validação\n7. Data Augmentation\n8. Treinando o modelo\n9. Avaliando mais o modelo\n10. Aplicando aos dados de treino\n11. Conclusão","metadata":{"id":"7ohJ3STj1d8W"}},{"cell_type":"markdown","source":"## 1. Importando as bibliotecas\n\nNesta etapa, todas as biliotecas usadas no notebook serão importadas\n\n","metadata":{"id":"Px3tQIVa2BCa"}},{"cell_type":"code","source":"# importando as bibliotecas\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\n# Importando a biblioteca para carregar arquivos do drive\nfrom google.colab import drive\n\n# Importando bibliotecas referentes as redes neurais\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras_preprocessing.image import load_img\nfrom keras.utils import to_categorical\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization\nfrom keras.callbacks import EarlyStopping, ReduceLROnPlateau\n\n# Importando outras bibliotecas uteis\nfrom sklearn.model_selection import train_test_split\nimport os\nimport random\n\n#importando bibliotecas de métricas\nfrom sklearn.metrics import confusion_matrix\nfrom sklearn.metrics import classification_report","metadata":{"id":"2hGCagzuEvpU"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 2. Leitura das bases consumidas\nNesta etapa, a base de dados será lida\n\n","metadata":{"id":"X9SCaEH-2GzT"}},{"cell_type":"code","source":"# Montando Google Drive\ndrive.mount('/content/drive')\n\n# Caminho para pegar os arquivos do drive\ncaminho = '/content/drive/MyDrive/Dataset - projetos dados/dogs-vs-cats/treino'  \n\n# Importando também o arquivo de teste\ntest_filenames = os.listdir(\"/content/drive/MyDrive/Dataset - projetos dados/dogs-vs-cats/teste\")","metadata":{"id":"5WXcLIFKqy0t","outputId":"0e03f592-f83d-4874-d3bb-869d1e657208"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 3. Manipulando os dados de treino\nNesta etapa, vamos convencionar 0 para gato e o número 1 para cachorro, e ainda contar quantos dados temos de cada\n\n","metadata":{"id":"ZItNoZad202-"}},{"cell_type":"code","source":"# Agora vamos separar as fotos que são referentes aos cachorros ou gatos\nnome_arquivos = os.listdir(caminho)\ntipos = []\nfor nome_arquivo in nome_arquivos:\n    tipo = nome_arquivo.split('.')[0]\n    if tipo == 'cat':\n        tipos.append(0)\n    else:\n        tipos.append(1)\n\ndf = pd.DataFrame({\n    'nome_arquivo': nome_arquivos,\n    'tipo': tipos\n})","metadata":{"id":"l1A8Bicpq1NC"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Olhando se a tabela está certinha\ndf.head()","metadata":{"id":"9un024tEFjIg","outputId":"de8d7dc9-aaab-4cb0-9ede-5bc03251fee6"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Contando os valores de cada tipo para ver se está certo\ndf['tipo'].value_counts()","metadata":{"id":"VD1foE-3FpKS","outputId":"3cd1cbfa-0f22-412c-afba-9f02293b8254"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Pegando uma imagem para ver se está correto\nexemplo = random.choice(nome_arquivos)\nimage = load_img(caminho+'/'+exemplo)\nplt.imshow(image)","metadata":{"id":"B_oqOvwAFwz_","outputId":"bb96aa2e-e249-44ec-bbdd-e8e491c4541c"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4. Construindo o modelo\nNesta etapa, vamos construir o modelo e explicar alguns termos\n\n","metadata":{"id":"0cRIBDHp3ZE0"}},{"cell_type":"markdown","source":"Aqui é muito importante entender o que está sendo feito, e os termos utilizados, portanto vou passar um resumo, caso queira saber um pouco mais eu indico o canal do sandeco:  \n https://www.youtube.com/c/canalsandeco  \n Em especial a playlist de redes convolucionais","metadata":{"id":"uaJJqear6rya"}},{"cell_type":"markdown","source":"\n**Dropout**- ajuda a regularizar(generalizar) a rede neural, \"escondendo neuronios\"   \n**Flatten** - Converte imagem em dado estruturado   \n**Activation** - São essenciais para dar capacidade representativa às redes neurais    \n**Pooling** - Serve para reduzir a imagem  \n**Padding** - Serve para o output da convolução ficar no tamanho original  \n**BatchNormalization** - A normalização em lote é um método usado para tornar o treinamento de redes neurais artificiais mais rápido e estável por meio da normalização das entradas das camadas","metadata":{"id":"lDW9pa8z8FDQ"}},{"cell_type":"code","source":"# O modelo pode não entender muito bem caso o tamanho das imagens seja diferente, então vamos deixar iguais\nFAST_RUN = False\nIMAGE_WIDTH=256\nIMAGE_HEIGHT=256\nIMAGE_SIZE=(IMAGE_WIDTH, IMAGE_HEIGHT)\nIMAGE_CHANNELS=3","metadata":{"id":"C3rh9VHMHTNc"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nmodel = Sequential()\n\nmodel.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS)))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(128, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Flatten())\nmodel.add(Dense(512, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.25))\nmodel.add(Dense(2, activation='softmax')) # 2 pois temos dois tipos: cão e gato\n\nmodel.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])\n\nmodel.summary()","metadata":{"id":"5BsAFnZSHXvt","outputId":"2808f3d6-1b82-48f7-e2a5-2dd741db7b05"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Podemos criar um Callback, para o programa parar quando chega ao estado desejado.","metadata":{"id":"NEdlfNk-8PgM"}},{"cell_type":"markdown","source":"## 5. Criando Callback\nNesta etapa, vamos criar um Callback, para o programa parar quando chega ao estado desejado.\n\n","metadata":{"id":"WnkjINWD3_BL"}},{"cell_type":"code","source":"earlystop = EarlyStopping(patience=10)","metadata":{"id":"t8UX9XiCHoMa"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learning_rate_reduction = ReduceLROnPlateau(monitor='val_accuracy', \n                                            patience=2, \n                                            verbose=1, \n                                            factor=0.5, \n                                            min_lr=0.00001)","metadata":{"id":"LFkLJZBoH-ca"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks = [earlystop, learning_rate_reduction]","metadata":{"id":"GaYn3SnNIBH5"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[\"tipo\"] = df[\"tipo\"].replace({0: 'cat', 1: 'dog'}) ","metadata":{"id":"RksOlzQSIEmR"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 6. Dividindo em treino e validação.\n\n","metadata":{"id":"gyBLIxyd4SuW"}},{"cell_type":"code","source":"train_df, validate_df = train_test_split(df, test_size=0.20, random_state=0)\ntrain_df = train_df.reset_index(drop=True)\nvalidate_df = validate_df.reset_index(drop=True)","metadata":{"id":"OOQRciJlIH0v"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df['tipo'].value_counts()","metadata":{"id":"imedVpT3IUUw","outputId":"9d3cc5f7-984c-40fb-f4c1-fdf8bcdb639f"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validate_df['tipo'].value_counts()","metadata":{"id":"lYBsSkOSIaSg","outputId":"895ac5d6-6f95-4032-ee89-ef3e58c55433"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"total_train = train_df.shape[0]\ntotal_validate = validate_df.shape[0]\nbatch_size=16","metadata":{"id":"v6FQ9vSwIf1p"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 7. Data Augmentation\nNesta etapa, vamos \"aumentar\" a quantidade de dados modificando uma imagem, mudando por exemplo a rotação, o brilho, o zoom, espelhando, entre outros.\n\n","metadata":{"id":"cZ_9YIfr4j4V"}},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n    rotation_range=15,\n    rescale=1./255,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    width_shift_range=0.2,\n    height_shift_range=0.2\n)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df, \n    caminho, \n    x_col='nome_arquivo',\n    y_col='tipo',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical',\n    batch_size=batch_size\n)","metadata":{"id":"Hyc0XDgpIl8x","outputId":"d7fa447b-515b-4822-b84c-68b9ef542a44"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_datagen = ImageDataGenerator(rescale=1./255)\nvalidation_generator = validation_datagen.flow_from_dataframe(\n    validate_df, \n    caminho, \n    x_col='nome_arquivo',\n    y_col='tipo',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical',\n    batch_size=batch_size\n)","metadata":{"id":"7R3nXdo6I0Bo","outputId":"55aeaabc-c12a-49a3-cc86-16e4ee0e991e"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"example_df = train_df.sample(n=1).reset_index(drop=True)\nexample_generator = train_datagen.flow_from_dataframe(\n    example_df, \n    caminho, \n    x_col='nome_arquivo',\n    y_col='tipo',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical'\n)","metadata":{"id":"gZfPPE5bI7oV","outputId":"f063b6dd-edaa-4527-ef1e-62891e759c4e"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12, 12))\nfor i in range(0, 15):\n    plt.subplot(5, 3, i+1)\n    for X_batch, Y_batch in example_generator:\n        image = X_batch[0]\n        plt.imshow(image)\n        break\nplt.tight_layout()\nplt.show()","metadata":{"id":"YtMjhtKEJDxG","outputId":"098c1d05-97e1-4c71-aea7-626974862cdf"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 8. Treinando o modelo\nNesta etapa, vamos de fato fazer com que a rede neural aprenda e avaliar esse aprendizado\n\n","metadata":{"id":"5BKJHbJt43To"}},{"cell_type":"code","source":"epochs=3 if FAST_RUN else 50\nhistory = model.fit_generator(\n    train_generator, \n    epochs=epochs,\n    validation_data=validation_generator,\n    validation_steps=total_validate//batch_size,\n    steps_per_epoch=total_train//batch_size,\n    callbacks=callbacks\n)","metadata":{"id":"IDSm6sm2JhqG","outputId":"20b00e08-46af-4830-d3d8-100404797c30"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Salvando o modelo\nmodel.save_weights(\"model.h5\")","metadata":{"id":"B0OdRUByVr3c"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Avaliando o modelo por meio de gráficos\nfig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 12))\nax1.plot(history.history['loss'], color='b', label=\"Training loss\")\nax1.plot(history.history['val_loss'], color='r', label=\"validation loss\")\nax1.set_xticks(np.arange(1, epochs, 1))\n\nax2.plot(history.history['accuracy'], color='b', label=\"Training accuracy\")\nax2.plot(history.history['val_accuracy'], color='r',label=\"Validation accuracy\")\nax2.set_xticks(np.arange(1, epochs, 1))\n\nlegend = plt.legend(loc='best', shadow=True)\nplt.tight_layout()\nplt.show()","metadata":{"id":"Hp7zEjFMVwAj","outputId":"07aff15d-9ce5-4b67-b9e9-588bda22172e"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss, accuracy = model.evaluate_generator(validation_generator, total_validate//batch_size, workers=12)\nprint(\"Test: accuracy = %f  ;  loss = %f \" % (accuracy, loss))","metadata":{"id":"e0SeamERH6NX","outputId":"9fb29028-f9db-49e1-fe13-b1c78f3ae9e5"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 9. Avaliando mais o modelo\nNesta etapa, vamos avaliar ainda mais o modelo com matriz de confusão e classification report\n\n","metadata":{"id":"O8Yb2joz5x4y"}},{"cell_type":"code","source":"validate_df[\"tipo\"] = validate_df[\"tipo\"].replace({ 1: 'dog', 0: 'cat' })\nY_val = validate_df['tipo']\n\ny_pred =  model.predict(validation_generator, steps=np.ceil(total_validate/batch_size))","metadata":{"id":"dUOlQVa1Ij6W","outputId":"6e20f4cd-5eb0-4e04-b077-0fefb6789256"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validate_df['y_pred'] = np.argmax(y_pred, axis = -1)\nlabel_map = dict((v,k) for k,v in train_generator.class_indices.items())\n\nvalidate_df['y_pred'] = validate_df['y_pred'].replace(label_map)","metadata":{"id":"Wv9HmWSVtcyb"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Utilizando a matriz de confusão\nconfusion_mtx = confusion_matrix(validate_df[\"tipo\"], validate_df['y_pred']) \n# plotando a matriz\nf,ax = plt.subplots(figsize=(6, 6))\nsns.heatmap(confusion_mtx, annot=True, linewidths=0.01, fmt= '.1f',ax=ax)\nplt.xlabel(\"Predicted Label\")\nplt.ylabel(\"True Label\")\nplt.title(\"Matriz de Confusão\")\nplt.show()","metadata":{"id":"p5BcN4n4IwlX","outputId":"1989fbdf-021d-4a89-a179-babe691af4b0"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Mostrando o classification report\nreport = classification_report(validate_df[\"tipo\"], validate_df['y_pred'], target_names=['0','1'])\n\nprint(report)","metadata":{"id":"UvOuVaVoIzEt","outputId":"2955ee11-6bb4-43ec-d5ca-5381198646b6"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 10. Aplicando aos dados de treino\nNesta etapa, vamos fazer os passos que fizemos anteriormente nos dados de treino para os dados de teste\n\n","metadata":{"id":"2YfRs5Y463zx"}},{"cell_type":"code","source":"test_df = pd.DataFrame({\n    'nome_arquivo': test_filenames\n})\nnb_samples = test_df.shape[0]","metadata":{"id":"L1TeF2otWOU7"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_gen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    test_df, \n    \"/content/drive/MyDrive/Dataset - projetos dados/dogs-vs-cats/teste\", \n    x_col='nome_arquivo',\n    y_col=None,\n    class_mode=None,\n    target_size=IMAGE_SIZE,\n    batch_size=batch_size,\n    shuffle=False\n)","metadata":{"id":"XHZZUD4BWmk5","outputId":"923a44cf-ae81-4215-c346-efa41aa43518"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict = model.predict_generator(test_generator, steps=np.ceil(nb_samples/batch_size))","metadata":{"id":"-hOiewtIWomO","outputId":"3724f8f3-d6f7-4520-9885-01fcc654253e"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['tipo'] = np.argmax(predict, axis=-1)","metadata":{"id":"MKzU9uDzWuqf"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"label_map = dict((v,k) for k,v in train_generator.class_indices.items())\ntest_df['tipo'] = test_df['tipo'].replace(label_map)","metadata":{"id":"uTgn80HWXI67"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df['tipo'] = test_df['tipo'].replace({ 'dog': 1, 'cat': 0 })","metadata":{"id":"B_wleXo2XLYB"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 11. Conclusão\nNesta etapa, vamos fazer concluir, fazendo a avaliação do teste, falar dos próximos passos e agradecer\n\n","metadata":{"id":"lyzhezm97qRc"}},{"cell_type":"code","source":"sample_test = test_df.head(9)\nsample_test.head()\nplt.figure(figsize=(9, 11))\nfor index, row in sample_test.iterrows():\n    filename = row['nome_arquivo']\n    category = row['tipo']\n    img = load_img(\"/content/drive/MyDrive/Dataset - projetos dados/dogs-vs-cats/teste/\"+filename, target_size=IMAGE_SIZE)\n    plt.subplot(3, 3, index+1)\n    plt.imshow(img)\n    plt.xlabel(filename + '(' + \"{}\".format(category) + ')' , fontsize = 15)\nplt.tight_layout()\nplt.show()","metadata":{"id":"WFQXAPtmXMMF","outputId":"89f078ff-9132-48ff-f605-d6000fb50002"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Lembrando que gato é igual a 0, e cachorro é igual 1  \nNesse dados de teste nosso modelo acertou 6 de 9, ou seja, 66%  \nEntão condiz com os nossos dados treino e validação","metadata":{"id":"N4HN8klswc_Z"}},{"cell_type":"markdown","source":"Para os próximos passos o ideal seria treinar com mais dados","metadata":{"id":"IO_dqLUexP0h"}},{"cell_type":"markdown","source":"Gostaria de agradecer ao  https://www.kaggle.com/uysimty  \nEle fez um ótimo trabalho e me ajudou na conclusão desse, quem quiser olhar o trabalho dele, aqui está o link:\nhttps://www.kaggle.com/code/uysimty/keras-cnn-dog-or-cat-classification\n","metadata":{"id":"mfw0LJ_i8E9s"}}]}