{"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":"# Introdução","metadata":{}},{"cell_type":"markdown","source":"Este notebook tem como finalidade de resolver o Desafio Digit Recognizer para a disciplina de Tópicos Especiais II: Deep Learning e Aplicações.\n\nAlterações realizadas tendo como referência o notebook https://www.kaggle.com/mauriciofigueiredo/cnn-simples-com-keras-para-iniciantes:\n* Alteração no kernel_size da primeira camada CONV2D: (3,3) -> (5,5);\n* Adicionei mais uma camada CONV2D; \n* Diminui o numero de neuronios para 40 na camada dense;\n* Alteração do otimizador para Adam;","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"# Bibliotecas e Dados","metadata":{}},{"cell_type":"code","source":"# Bibliotecas necessárias\nimport pandas as pd # Manipulação de dados\n\n# Redes Neurais\nfrom tensorflow import keras\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Dropout, Conv2D, MaxPooling2D, Flatten \n\n# Plot\nimport matplotlib.pyplot as plt\n%matplotlib inline\n\n# Avaliação\nfrom sklearn.metrics import classification_report, confusion_matrix","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:23.179798Z","iopub.execute_input":"2022-03-12T00:10:23.180312Z","iopub.status.idle":"2022-03-12T00:10:25.139157Z","shell.execute_reply.started":"2022-03-12T00:10:23.180243Z","shell.execute_reply":"2022-03-12T00:10:25.138439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Lendo o dataset\ntrain = pd.read_csv('../input/digit-recognizer/train.csv')\n\ntrain.head()","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:25.144414Z","iopub.execute_input":"2022-03-12T00:10:25.144632Z","iopub.status.idle":"2022-03-12T00:10:28.235252Z","shell.execute_reply.started":"2022-03-12T00:10:25.144599Z","shell.execute_reply":"2022-03-12T00:10:28.234519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Verificando o tamanho do dataset para treino\nprint(\"Quantidade de elementos de treino: {}\". format(len(train)))","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:28.236562Z","iopub.execute_input":"2022-03-12T00:10:28.236819Z","iopub.status.idle":"2022-03-12T00:10:28.243261Z","shell.execute_reply.started":"2022-03-12T00:10:28.236785Z","shell.execute_reply":"2022-03-12T00:10:28.242567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# separando o x_train e y_train\nY = train[\"label\"]\nX = train.drop(labels = ['label'], axis = 1)\n\nprint(X.head())","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:28.245617Z","iopub.execute_input":"2022-03-12T00:10:28.246268Z","iopub.status.idle":"2022-03-12T00:10:28.334534Z","shell.execute_reply.started":"2022-03-12T00:10:28.246234Z","shell.execute_reply":"2022-03-12T00:10:28.333794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(Y.head())","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:28.335932Z","iopub.execute_input":"2022-03-12T00:10:28.336386Z","iopub.status.idle":"2022-03-12T00:10:28.341735Z","shell.execute_reply.started":"2022-03-12T00:10:28.336347Z","shell.execute_reply":"2022-03-12T00:10:28.341027Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(X.shape)\nprint(Y.shape)","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:28.343015Z","iopub.execute_input":"2022-03-12T00:10:28.343435Z","iopub.status.idle":"2022-03-12T00:10:28.351533Z","shell.execute_reply.started":"2022-03-12T00:10:28.343399Z","shell.execute_reply":"2022-03-12T00:10:28.350669Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Verificar com matplotlib\nplt.imshow(X.values[100].reshape(28,28), cmap=plt.cm.binary)\nplt.show()\nprint('Label: {}'.format(Y[100]))","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:28.353042Z","iopub.execute_input":"2022-03-12T00:10:28.353299Z","iopub.status.idle":"2022-03-12T00:10:28.523543Z","shell.execute_reply.started":"2022-03-12T00:10:28.353265Z","shell.execute_reply":"2022-03-12T00:10:28.522825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Transformando um numpy array em imagem 2d (28*28)\nx = X.values.reshape(42000, 28, 28, 1)\n\n#Normalizando para valores entre 0 e 1\nx = x.astype('float32')\nx /= 255","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:28.524809Z","iopub.execute_input":"2022-03-12T00:10:28.525529Z","iopub.status.idle":"2022-03-12T00:10:28.599468Z","shell.execute_reply.started":"2022-03-12T00:10:28.525488Z","shell.execute_reply":"2022-03-12T00:10:28.598605Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Vamos ajustar o formato da saida\nnum_classes = 10\n\n# Convertendo para um vetor de saida com 10 dimensoes\n# ex. 8 => [0,0,0,0,0,0,0,0,1,0]\ny = keras.utils.to_categorical(Y, num_classes)\nprint(y[0])","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:28.600891Z","iopub.execute_input":"2022-03-12T00:10:28.601166Z","iopub.status.idle":"2022-03-12T00:10:28.607869Z","shell.execute_reply.started":"2022-03-12T00:10:28.601129Z","shell.execute_reply":"2022-03-12T00:10:28.607032Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Separando uma parte para treino (90%) e outra para validação (10%)\nfrom sklearn.model_selection import train_test_split\n\nx_train, x_val, y_train, y_val = train_test_split(x, y, test_size = 0.1, random_state=5)\n\nprint('Qtde de treino: {}'.format(len(x_train)))\nprint('Qtde de validação: {}'.format(len(x_val)))","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:10:28.609378Z","iopub.execute_input":"2022-03-12T00:10:28.609837Z","iopub.status.idle":"2022-03-12T00:10:28.931874Z","shell.execute_reply.started":"2022-03-12T00:10:28.609801Z","shell.execute_reply":"2022-03-12T00:10:28.931054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Criando e Treinando o Modelo","metadata":{}},{"cell_type":"markdown","source":"* Criando o modelo Sequential\n* Sequential: Modelo Keras de ir adicionando camadas (como um lego)\n* Conv2D: Camada com kernels (filtros) que percorrem a imagem extraindo caracterísitcas (mapas de caracteísticas)\n* MaxPooling2D: Camada que reduz a dimensionalidade dos mapas de características 2D\n* Flatten: Camada que transforma um mapa de características 2D num vetor para classficador final\n* Dense: Camada onde todas as entradas estão conectadas em cada neurônio (totalmente conectada)\n* Dropout: Camada usa durante treino que descarta aleatoriamente um percentual de conexões (reduz overfitting)","metadata":{}},{"cell_type":"code","source":"model = Sequential()\n\n\nmodel.add(Conv2D(20, kernel_size=(5, 5),\n                 activation='relu',\n                 input_shape=(28,28,1))) # alteração no tamanho do kernel_size\n\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Conv2D(40, kernel_size=(3,3), activation='relu'))\n\n# camada adicionada com relação ao notebook de referencia\nmodel.add(Conv2D(40, kernel_size=(3,3), activation='relu')) \n\nmodel.add(Flatten())\nmodel.add(Dense(40, activation = 'relu')) # Diminui o numero de neuronios dessa camada\nmodel.add(Dropout(0.2))\n\nmodel.add(Dense(num_classes, activation='softmax'))\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:19:51.504226Z","iopub.execute_input":"2022-03-12T00:19:51.504508Z","iopub.status.idle":"2022-03-12T00:19:51.572634Z","shell.execute_reply.started":"2022-03-12T00:19:51.504478Z","shell.execute_reply":"2022-03-12T00:19:51.571852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Compila o modelo\n\n# Alteração no otimizador\nmodel.compile(loss = 'categorical_crossentropy',\n              optimizer = 'Adam',\n              metrics = ['accuracy']) ","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:19:54.102760Z","iopub.execute_input":"2022-03-12T00:19:54.103305Z","iopub.status.idle":"2022-03-12T00:19:54.112041Z","shell.execute_reply.started":"2022-03-12T00:19:54.103265Z","shell.execute_reply":"2022-03-12T00:19:54.111121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Treina com os parte dos dados\nbatch_size = 32\nepochs = 100\n\n#Salvar o melhor modelo\ncallbacks_list = [\n    keras.callbacks.ModelCheckpoint(\n        filepath='model.h5',\n        monitor='val_loss', save_best_only=True, verbose=1),\n    keras.callbacks.EarlyStopping(monitor='val_loss', patience=10,verbose=1)\n]\n\nhistory = model.fit(x_train, y_train,\n                    batch_size=batch_size,\n                    epochs=epochs,\n                    callbacks = callbacks_list,\n                    verbose=1,\n                    validation_data=(x_val, y_val))","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:19:54.554926Z","iopub.execute_input":"2022-03-12T00:19:54.555348Z","iopub.status.idle":"2022-03-12T00:21:08.731893Z","shell.execute_reply.started":"2022-03-12T00:19:54.555312Z","shell.execute_reply":"2022-03-12T00:21:08.731202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Vamos ver como foi o treino?\n\nfig, ax = plt.subplots(1,2, figsize=(16,8))\nax[0].plot(history.history['loss'], color='b', label=\"Training loss\")\nax[0].plot(history.history['val_loss'], color='r', label=\"validation loss\",axes =ax[0])\nlegend = ax[0].legend(loc='best', shadow=True)\n\nax[1].plot(history.history['accuracy'], color='b', label=\"Training accuracy\")\nax[1].plot(history.history['val_accuracy'], color='r',label=\"Validation accuracy\")\nlegend = ax[1].legend(loc='best', shadow=True)","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:21:08.733568Z","iopub.execute_input":"2022-03-12T00:21:08.733908Z","iopub.status.idle":"2022-03-12T00:21:09.127232Z","shell.execute_reply.started":"2022-03-12T00:21:08.733868Z","shell.execute_reply":"2022-03-12T00:21:09.126492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.models import load_model\n\n# Load the best saved model\nmodel = load_model('model.h5')","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:14:33.720097Z","iopub.execute_input":"2022-03-12T00:14:33.720666Z","iopub.status.idle":"2022-03-12T00:14:33.818240Z","shell.execute_reply.started":"2022-03-12T00:14:33.720612Z","shell.execute_reply":"2022-03-12T00:14:33.817592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Testa\nscore = model.evaluate(x_val, y_val, verbose=0)\n\nprint('Test loss:', score[0])\nprint('Test accuracy:', score[1])","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:14:41.304561Z","iopub.execute_input":"2022-03-12T00:14:41.305455Z","iopub.status.idle":"2022-03-12T00:14:41.668842Z","shell.execute_reply.started":"2022-03-12T00:14:41.305408Z","shell.execute_reply":"2022-03-12T00:14:41.668028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Avaliando o Modelo","metadata":{"execution":{"iopub.status.busy":"2022-03-11T19:30:20.265209Z","iopub.execute_input":"2022-03-11T19:30:20.265857Z","iopub.status.idle":"2022-03-11T19:30:20.47753Z","shell.execute_reply.started":"2022-03-11T19:30:20.265809Z","shell.execute_reply":"2022-03-11T19:30:20.476023Z"}}},{"cell_type":"code","source":"import itertools\n\n#Plot the confusion matrix. Set Normalize = True/False\ndef plot_confusion_matrix(cm, classes, normalize=True, title='Confusion matrix', cmap=plt.cm.Blues):\n    \"\"\"\n    This function prints and plots the confusion matrix.\n    Normalization can be applied by setting `normalize=True`.\n    \"\"\"\n    plt.figure(figsize=(10,10))\n    plt.imshow(cm, interpolation='nearest', cmap=cmap)\n    plt.title(title)\n    plt.colorbar()\n    tick_marks = np.arange(len(classes))\n    plt.xticks(tick_marks, classes, rotation=45)\n    plt.yticks(tick_marks, classes)\n    \n    if normalize:\n        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n        cm = np.around(cm, decimals=2)\n        cm[np.isnan(cm)] = 0.0\n        \n    thresh = cm.max() / 2.\n    \n    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n        plt.text(j, i, cm[i, j],\n                 horizontalalignment=\"center\",\n                 color=\"white\" if cm[i, j] > thresh else \"black\")\n        \n    plt.tight_layout()\n    plt.ylabel('True label')\n    plt.xlabel('Predicted label')","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:14:45.806875Z","iopub.execute_input":"2022-03-12T00:14:45.807126Z","iopub.status.idle":"2022-03-12T00:14:45.818415Z","shell.execute_reply.started":"2022-03-12T00:14:45.807098Z","shell.execute_reply":"2022-03-12T00:14:45.817684Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Vendo alguns reports# Vendo alguns reports\n# Usando sklearn\nimport numpy as np\n\n# Classificando toda base de teste\ny_pred = np.argmax(model.predict(x_val), axis=1)\n# voltando pro formato de classes\ny_test_c = np.argmax(y_val, axis=1)\ntarget_names = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']\n\n#Confution Matrix\ncm = confusion_matrix(y_test_c, y_pred)\nplot_confusion_matrix(cm, target_names, normalize=False, title='Confusion Matrix')\n\nprint('Classification Report')\nprint(classification_report(y_test_c, y_pred, target_names=target_names))","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:11:32.087562Z","iopub.execute_input":"2022-03-12T00:11:32.088015Z","iopub.status.idle":"2022-03-12T00:11:33.416140Z","shell.execute_reply.started":"2022-03-12T00:11:32.087978Z","shell.execute_reply":"2022-03-12T00:11:33.415458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Gerando Saida","metadata":{}},{"cell_type":"code","source":"# Gerando saída para dataset de teste\n\n#Carrega dataset de teste\ntest = pd.read_csv(\"../input/digit-recognizer/test.csv\")\nprint(\"Qtde de testes: {}\".format(len(test)))\nprint(test.shape)\n# Bota no formato numpy e normaliza\nx_test = test.values.reshape(len(test),28,28,1)\nx_test = x_test.astype('float32')\nx_test /= 255\n\n# Faz classificação para dataset de teste\ny_pred = np.argmax(model.predict(x_test), axis=1)\n\n# Verficando algum exemplo\ni = 0\nplt.imshow(test.values[i].reshape(28,28), cmap=plt.cm.binary)\nplt.show()\nprint('Previsto: {}'.format(y_pred[i]))\n\n# Botando no formato de saída (competição Kaggle)\nresults = pd.Series(y_pred,name=\"Label\")\nsubmission = pd.concat([pd.Series(range(1,len(y_pred)+1),name = \"ImageId\"),results],axis = 1)\nprint(submission.head(10))\n#Salvando Arquivo\nsubmission.to_csv(\"cnn_mnist.csv\",index=False)","metadata":{"execution":{"iopub.status.busy":"2022-03-12T00:11:33.417431Z","iopub.execute_input":"2022-03-12T00:11:33.418104Z","iopub.status.idle":"2022-03-12T00:11:36.660722Z","shell.execute_reply.started":"2022-03-12T00:11:33.418064Z","shell.execute_reply":"2022-03-12T00:11:36.659981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}