{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from IPython.display import Image\n", "from IPython.core.display import HTML " ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: theano in /home/joao/.local/lib/python2.7/site-packages (1.0.3)\n", "Requirement already satisfied: numpy>=1.9.1 in /usr/local/lib/python2.7/dist-packages (from theano) (1.14.2)\n", "Requirement already satisfied: scipy>=0.14 in /usr/local/lib/python2.7/dist-packages (from theano) (1.0.0)\n", "Requirement already satisfied: six>=1.9.0 in /home/joao/.local/lib/python2.7/site-packages (from theano) (1.11.0)\n", "Requirement already satisfied: keras in /usr/local/lib/python2.7/dist-packages (2.1.5)\n", "Requirement already satisfied: numpy>=1.9.1 in /usr/local/lib/python2.7/dist-packages (from keras) (1.14.2)\n", "Requirement already satisfied: scipy>=0.14 in /usr/local/lib/python2.7/dist-packages (from keras) (1.0.0)\n", "Requirement already satisfied: six>=1.9.0 in /home/joao/.local/lib/python2.7/site-packages (from keras) (1.11.0)\n", "Requirement already satisfied: pyyaml in /usr/local/lib/python2.7/dist-packages (from keras) (3.12)\n", "Requirement already satisfied: tensorflow in /usr/local/lib/python2.7/dist-packages (1.6.0)\n", "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (0.6.2)\n", "Requirement already satisfied: protobuf>=3.4.0 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (3.5.2.post1)\n", "Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (0.2.0)\n", "Requirement already satisfied: tensorboard<1.7.0,>=1.6.0 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (1.6.0)\n", "Requirement already satisfied: six>=1.10.0 in /home/joao/.local/lib/python2.7/site-packages (from tensorflow) (1.11.0)\n", "Requirement already satisfied: wheel in /usr/lib/python2.7/dist-packages (from tensorflow) (0.29.0)\n", "Requirement already satisfied: absl-py>=0.1.6 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (0.1.12)\n", "Requirement already satisfied: backports.weakref>=1.0rc1 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (1.0.post1)\n", "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (1.1.0)\n", "Requirement already satisfied: enum34>=1.1.6 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (1.1.6)\n", "Requirement already satisfied: numpy>=1.13.3 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (1.14.2)\n", "Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (1.10.0)\n", "Requirement already satisfied: mock>=2.0.0 in /usr/local/lib/python2.7/dist-packages (from tensorflow) (2.0.0)\n", "Requirement already satisfied: setuptools in /home/joao/.local/lib/python2.7/site-packages (from protobuf>=3.4.0->tensorflow) (40.4.3)\n", "Requirement already satisfied: werkzeug>=0.11.10 in /usr/local/lib/python2.7/dist-packages (from tensorboard<1.7.0,>=1.6.0->tensorflow) (0.14.1)\n", "Requirement already satisfied: futures>=3.1.1; python_version < \"3\" in /usr/local/lib/python2.7/dist-packages (from tensorboard<1.7.0,>=1.6.0->tensorflow) (3.2.0)\n", "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python2.7/dist-packages (from tensorboard<1.7.0,>=1.6.0->tensorflow) (2.6.11)\n", "Requirement already satisfied: html5lib==0.9999999 in /usr/local/lib/python2.7/dist-packages (from tensorboard<1.7.0,>=1.6.0->tensorflow) (0.9999999)\n", "Requirement already satisfied: bleach==1.5.0 in /usr/local/lib/python2.7/dist-packages (from tensorboard<1.7.0,>=1.6.0->tensorflow) (1.5.0)\n", "Requirement already satisfied: pbr>=0.11 in /usr/local/lib/python2.7/dist-packages (from mock>=2.0.0->tensorflow) (3.1.1)\n", "Requirement already satisfied: funcsigs>=1; python_version < \"3.3\" in /usr/local/lib/python2.7/dist-packages (from mock>=2.0.0->tensorflow) (1.0.2)\n" ] } ], "source": [ "# se vc ainda não tem as bibliotecas, execute essa linha:\n", "!pip install --user theano \n", "!pip install --user keras \n", "!pip install --user tensorflow" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Introdução ao aprendizado profundo, redes neurais convolucionais e Keras\n", "Fontes : \n", "\n", "1) https://machinelearningmastery.com/handwritten-digit-recognition-using-convolutional-neural-networks-python-keras/\n", "\n", "2) https://towardsdatascience.com/a-visual-introduction-to-neural-networks-68586b0b733b\n", "\n", "3) http://www.dspguide.com/graphics/F_26_5.gif\n", "\n", "4) https://cdn-images-1.medium.com/max/1600/1*iT3SEgwnbhLloLY_zk1PfA.gif\n", "\n", "5) https://cdn-images-1.medium.com/max/1600/0*Eyhhx33AK58cHDXZ.png\n", "\n", "6) http://colah.github.io/posts/2014-07-Understanding-Convolutions/\n", "\n", "7) https://docs.gimp.org/2.10/en/gimp-filter-convolution-matrix.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Por que profundo? " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Multilayered Perceptron" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Multilayer perceptron](http://www.dspguide.com/graphics/F_26_5.gif)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Esta arquitetura aparentemente aprende sem nenhum problema... então por que complicar?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![learning model](https://cdn-images-1.medium.com/max/1600/1*iT3SEgwnbhLloLY_zk1PfA.gif)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Deeper Network" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Deeper Network](https://cdn-images-1.medium.com/max/1600/0*Eyhhx33AK58cHDXZ.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nem todos os espaços de features são simples como o mostrado acima - às vezes ajuda você ter diversas camadas de interpretação dos dados." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Exemplo legal para entender melhor: http://scs.ryerson.ca/~aharley/vis/conv/flat.html" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### O que é convolução?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " Explicação bem visual e detalhada pode ser encontrada aqui: http://colah.github.io/posts/2014-07-Understanding-Convolutions/\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para o nosso caso, tenham isso em mente: " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![definição básica de convolução](http://colah.github.io/posts/2014-07-Understanding-Convolutions/img/RiverTrain-ImageConvDiagram.png)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Aplica-se o kernel de convolução a cada um dos quadrados disponíveis na imagem, obtendo-se a imagem ao lado:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A | B | C\n", "- | - | - |\n", "![original](https://docs.gimp.org/2.10/en/images/filters/examples/generic-taj-convmatrix-sharpen.jpg) | ![kernel](https://docs.gimp.org/2.10/en/images/filters/examples/convolution-edge-detect1.png) |![result](https://docs.gimp.org/2.10/en/images/filters/examples/generic-taj-convmatrix-edge-detect.jpg) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Exemplo notável de convolução de kernels feitos a mão -algoritmo de Viola-Jones para detecção de faces : https://cs.nyu.edu/courses/fall12/CSCI-GA.2560-001/FaceRecognitionBoosting.pdf" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Por quê convoluir?\n", "Mais fácil de entender com um exemplo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Conhecendo nosso dataset - O que é MNIST?" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "Using TensorFlow backend.\n" ] }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "# O keras tem o dataset já pre-carregado\n", "from keras.datasets import mnist\n", "import matplotlib.pyplot as plt\n", "# carregamos o dataset:\n", "(X_train, y_train), (X_test, y_test) = mnist.load_data()\n", "# plot 4 images as gray scale\n", "plt.subplot(221)\n", "plt.imshow(X_train[0], cmap=plt.get_cmap('gray'))\n", "plt.subplot(222)\n", "plt.imshow(X_train[1], cmap=plt.get_cmap('gray'))\n", "plt.subplot(223)\n", "plt.imshow(X_train[2], cmap=plt.get_cmap('gray'))\n", "plt.subplot(224)\n", "plt.imshow(X_train[3], cmap=plt.get_cmap('gray'))\n", "# show the plot\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Imagens em grayscale 28x28 de dígitos escritos a mão - O objetivo é identificar cada um deles. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# O que é o Tensorflow ? O que é o Keras ? " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Tensorflow é bem mais versátil, mas bem mais verboso - vide https://github.com/aymericdamien/TensorFlow-Examples/blob/master/notebooks/3_NeuralNetworks/neural_network_raw.ipynb" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Baseline model - Multilayer perceptron" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para efeitos de comparação, vamos construir uma rede neural rasa plenamente conectada, para se ter uma idéia de tamanho e de performance. " ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "#importamos as bibliotecas relevantes\n", "import numpy as np\n", "# o dataset do mnist\n", "from keras.datasets import mnistk\n", "# O Keras permite que nós construamos modelos de diversos tipos, LSTM, paralelos entre outros. Para o nosso caso, basta\n", "# o modelo sequencial feedforward i.e. a saida de uma camada serve de entrada para a outra e uma camada só vê o que sai\n", "# da que veio antes dela, daí, Sequential.\n", "from keras.models import Sequential\n", "# cada \"pedaço\" de uma rede neural é tratado no keras como sendo uma camada. A camada dense é uma camada fully connected\n", "# de uma rede neural.\n", "from keras.layers import Dense\n", "# dropout é uma técnica usada para garantir que a rede neural fique mais robusta a variações e que ela tenha redundâncias\n", "# na detecção. - Leia mais sobre isso aqui : https://medium.com/@amarbudhiraja/https-medium-com-amarbudhiraja-learning-less-to-learn-better-dropout-in-deep-machine-learning-74334da4bfc5\n", "from keras.layers import Dropout\n", "# Esta biblioteca ajuda a fazer o one-hot encoding dos alvos. \n", "from keras.utils import np_utils" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Mantendo uma seed constante no gerador aletório do numpy\n", "seed = 7\n", "np.random.seed(seed)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "# carrego os dados\n", "(X_train, y_train), (X_test, y_test) = mnist.load_data()" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# transformando as imagens 28x28 em um vetor com 784 componentes para poder servir de entrada para a primeira camada da rede\n", "num_pixels = X_train.shape[1] * X_train.shape[2]\n", "X_train = X_train.reshape(X_train.shape[0], num_pixels).astype('float32')\n", "X_test = X_test.reshape(X_test.shape[0], num_pixels).astype('float32')" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "# Normalizando os inputs - prática comum em NN - deixa o problema melhor comportado numericamente\n", "X_train = X_train / 255\n", "X_test = X_test / 255" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "# one-hot encoding dos outputs (maneira usada para se lidar comproblemas de classificação múltipla em redes neurais)\n", "# one-hot encoding é também usado para se lidar com variáveis categóricas como features!\n", "y_train = np_utils.to_categorical(y_train)\n", "y_test = np_utils.to_categorical(y_test)\n", "num_classes = y_test.shape[1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "![Multilayer perceptron](http://www.dspguide.com/graphics/F_26_5.gif)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "# definindo o modelo baseline\n", "def baseline_model():\n", " # criamos o modelo\n", " # começamos por instanciar o esqueleto do modelo, neste caso, o sequencial\n", " model = Sequential()\n", " # em seguida, adicionamos as camadas uma a uma. Adicionamos uma camada de entrada com ativação relu\n", " model.add(Dense(num_pixels, input_dim=num_pixels, kernel_initializer='normal', activation='relu'))\n", " # e a camada de saída, com ativação softmax para transformar as saídas numéricas em probabilidades\n", " model.add(Dense(num_classes, kernel_initializer='normal', activation='softmax'))\n", " # compilamos o modelo escolhendo a função objetiva, o otimizador (cuja escolha é empírica) e a métrica \n", " #de performance mais conveniente.\n", " model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n", " return model" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "_________________________________________________________________\n", "Layer (type) Output Shape Param # \n", "=================================================================\n", "dense_1 (Dense) (None, 784) 615440 \n", "_________________________________________________________________\n", "dense_2 (Dense) (None, 10) 7850 \n", "=================================================================\n", "Total params: 623,290\n", "Trainable params: 623,290\n", "Non-trainable params: 0\n", "_________________________________________________________________\n" ] } ], "source": [ "%matplotlib inline\n", "# construimos o modelo com nossa classe\n", "model = baseline_model()\n", "model.summary()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note que, para um modelo extremamente simples, nos já temos mais de 600k parâmetros para ajustar. " ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Train on 60000 samples, validate on 10000 samples\n", "Epoch 1/10\n", " - 4s - loss: 0.2788 - acc: 0.9211 - val_loss: 0.1408 - val_acc: 0.9576\n", "Epoch 2/10\n", " - 4s - loss: 0.1118 - acc: 0.9676 - val_loss: 0.0924 - val_acc: 0.9710\n", "Epoch 3/10\n", " - 4s - loss: 0.0721 - acc: 0.9793 - val_loss: 0.0782 - val_acc: 0.9767\n", "Epoch 4/10\n", " - 4s - loss: 0.0504 - acc: 0.9858 - val_loss: 0.0737 - val_acc: 0.9771\n", "Epoch 5/10\n", " - 4s - loss: 0.0374 - acc: 0.9893 - val_loss: 0.0678 - val_acc: 0.9788\n", "Epoch 6/10\n", " - 4s - loss: 0.0269 - acc: 0.9927 - val_loss: 0.0635 - val_acc: 0.9809\n", "Epoch 7/10\n", " - 5s - loss: 0.0208 - acc: 0.9948 - val_loss: 0.0615 - val_acc: 0.9803\n", "Epoch 8/10\n", " - 4s - loss: 0.0142 - acc: 0.9968 - val_loss: 0.0639 - val_acc: 0.9797\n", "Epoch 9/10\n", " - 4s - loss: 0.0110 - acc: 0.9976 - val_loss: 0.0593 - val_acc: 0.9813\n", "Epoch 10/10\n", " - 4s - loss: 0.0078 - acc: 0.9986 - val_loss: 0.0594 - val_acc: 0.9815\n", "Baseline Error: 1.85%\n" ] } ], "source": [ "# Treinamos o modelo, usando uma sintaxe parecida com a do scikit-learn, selecionando dois fatores cruciais para o \n", "# treinamento de redes neurais - o tamanho do batch e o número de rounds no treinamento.\n", "# O número de rounds no treinamento é simples - indica quantas vezes você vai aplicar o algoritmo de Backpropagation \n", "# no seu dataset de treino. Se você tem um modelo com muita variância e treina ele demais - acaba overfitando.\n", "# O outro parâmetro relevante é o tamanho do batch. O batch é a quantidade de samples que vc usa por cada step do algoritmo\n", "# de backpropagation que você faz. Um batch size pequeno garante que você fará muitos updates dos parâmetros do seu modelo\n", "# mesmo durante a primeira rodada, o que pode acelerar o aprendizado. Ao mesmo tempo, um batch size pequeno pode acabar\n", "# te prendendo em um máximo/mínimo local. Portanto, é interessante brincar com esse parâmetro e ver o que acontece com \n", "# a acurácia do seu modelo e com seu tempo de convergência.\n", "model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200, verbose=2)\n", "# Avaliação final do modelo.\n", "scores = model.evaluate(X_test, y_test, verbose=0)\n", "print(\"Baseline Error: %.2f%%\" % (100-scores[1]*100))\n", "\n", "# Boa estratégia ?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Rede Convolucional Simples\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from keras.datasets import mnist\n", "from keras.models import Sequential\n", "from keras.layers import Dense\n", "from keras.layers import Dropout\n", "from keras.layers import Flatten\n", "from keras.layers.convolutional import Conv2D\n", "from keras.layers.convolutional import MaxPooling2D\n", "from keras.utils import np_utils\n", "from keras import backend as K\n", "K.set_image_dim_ordering('th')" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "# Mantendo a seed constante para poder reproduzir os resultados\n", "seed = 7\n", "np.random.seed(seed)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# carregamos o dataset\n", "(X_train, y_train), (X_test, y_test) = mnist.load_data()\n", "# imagens podem ter várias camadas de cor - R,G,B, por exemplo. Assim sendo, modelos convolucionais geralmente esperam\n", "# em suas entradas, matrizes tetradimensionais, i.e., no formato [samples][canais][width][height] , onde canais é o número\n", "# de canais de cor de sua imagem. No caso do MNIST, é uma imagem em grayscale, então temos apenas um canal de cor. \n", "X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')\n", "X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32')" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "# Novamente normalizando as features\n", "X_train = X_train / 255\n", "X_test = X_test / 255\n", "# one hot encode outputs\n", "y_train = np_utils.to_categorical(y_train)\n", "y_test = np_utils.to_categorical(y_test)\n", "num_classes = y_test.shape[1]" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "def baseline_model():\n", " # criando o modelo\n", " model = Sequential()\n", " # de novo, simplesmente basta adicionar a camada de convolução. Vale notar que para esta camada temos que determinar\n", " #o número de kernels de convolução, (32,neste caso), o tamanho do kernel de convolução (5x5) e o formato de cada \n", " # entrada, neste caso, 1 canal e uma imagem 28x28\n", " model.add(Conv2D(32, (5, 5), input_shape=(1, 28, 28), activation='relu'))\n", " # em seguida, adicionamos uma camada de pooling, para reduzir a dimensionalidade do problema e acelearar o aprendizado\n", " # sobre o efeito do pooling, vc pode ler mais aqui: https://pt.coursera.org/lecture/convolutional-neural-networks/pooling-layers-hELHk\n", " model.add(MaxPooling2D(pool_size=(2, 2)))\n", " # incluimos uma camada de dropout para adicionar robustez ao aprendizado\n", " model.add(Dropout(0.2))\n", " # em seguida, para a camada de saída, temos que formatar as saídas da camada convolucional em um vetor que pode servir\n", " # de entrada para uma camada conectada tradicional\n", " model.add(Flatten())\n", " model.add(Dense(128, activation='relu'))\n", " # adicionamos, por fim, a camada de saída, com ativação softmax para transformar os valores em probabilidades.\n", " model.add(Dense(num_classes, activation='softmax'))\n", " # compilando o modelo\n", " model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n", " return model" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "_________________________________________________________________\n", "Layer (type) Output Shape Param # \n", "=================================================================\n", "conv2d_1 (Conv2D) (None, 32, 24, 24) 832 \n", "_________________________________________________________________\n", "max_pooling2d_1 (MaxPooling2 (None, 32, 12, 12) 0 \n", "_________________________________________________________________\n", "dropout_1 (Dropout) (None, 32, 12, 12) 0 \n", "_________________________________________________________________\n", "flatten_1 (Flatten) (None, 4608) 0 \n", "_________________________________________________________________\n", "dense_3 (Dense) (None, 128) 589952 \n", "_________________________________________________________________\n", "dense_4 (Dense) (None, 10) 1290 \n", "=================================================================\n", "Total params: 592,074\n", "Trainable params: 592,074\n", "Non-trainable params: 0\n", "_________________________________________________________________\n" ] } ], "source": [ "# build the model\n", "model = baseline_model()\n", "model.summary()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Observe que esta rede, apesar de ter mais camadas e ser evidentemente mais complexa em termos de arquitetura, tem menos componentes." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Train on 60000 samples, validate on 10000 samples\n", "Epoch 1/20\n", "60000/60000 [==============================] - 86s 1ms/step - loss: 0.2339 - acc: 0.9341 - val_loss: 0.0812 - val_acc: 0.9746\n", "Epoch 2/20\n", "60000/60000 [==============================] - 85s 1ms/step - loss: 0.0737 - acc: 0.9778 - val_loss: 0.0464 - val_acc: 0.9837\n", "Epoch 3/20\n", "60000/60000 [==============================] - 86s 1ms/step - loss: 0.0533 - acc: 0.9838 - val_loss: 0.0433 - val_acc: 0.9859\n", "Epoch 4/20\n", "60000/60000 [==============================] - 84s 1ms/step - loss: 0.0405 - acc: 0.9876 - val_loss: 0.0400 - val_acc: 0.9871\n", "Epoch 5/20\n", "60000/60000 [==============================] - 82s 1ms/step - loss: 0.0337 - acc: 0.9892 - val_loss: 0.0340 - val_acc: 0.9886\n", "Epoch 6/20\n", "60000/60000 [==============================] - 82s 1ms/step - loss: 0.0278 - acc: 0.9913 - val_loss: 0.0322 - val_acc: 0.9897\n", "Epoch 7/20\n", "60000/60000 [==============================] - 82s 1ms/step - loss: 0.0234 - acc: 0.9926 - val_loss: 0.0350 - val_acc: 0.9884\n", "Epoch 8/20\n", "60000/60000 [==============================] - 81s 1ms/step - loss: 0.0206 - acc: 0.9935 - val_loss: 0.0328 - val_acc: 0.9890\n", "Epoch 9/20\n", "60000/60000 [==============================] - 82s 1ms/step - loss: 0.0170 - acc: 0.9945 - val_loss: 0.0287 - val_acc: 0.9904\n", "Epoch 10/20\n", "60000/60000 [==============================] - 80s 1ms/step - loss: 0.0144 - acc: 0.9959 - val_loss: 0.0314 - val_acc: 0.9903\n", "Epoch 11/20\n", "60000/60000 [==============================] - 82s 1ms/step - loss: 0.0128 - acc: 0.9957 - val_loss: 0.0316 - val_acc: 0.9897\n", "Epoch 12/20\n", "60000/60000 [==============================] - 82s 1ms/step - loss: 0.0115 - acc: 0.9961 - val_loss: 0.0344 - val_acc: 0.9886\n", "Epoch 13/20\n", "60000/60000 [==============================] - 82s 1ms/step - loss: 0.0096 - acc: 0.9968 - val_loss: 0.0329 - val_acc: 0.9900\n", "Epoch 14/20\n", "60000/60000 [==============================] - 82s 1ms/step - loss: 0.0098 - acc: 0.9970 - val_loss: 0.0425 - val_acc: 0.9875\n", "Epoch 15/20\n", "60000/60000 [==============================] - 84s 1ms/step - loss: 0.0084 - acc: 0.9974 - val_loss: 0.0341 - val_acc: 0.9902\n", "Epoch 16/20\n", "60000/60000 [==============================] - 83s 1ms/step - loss: 0.0065 - acc: 0.9979 - val_loss: 0.0319 - val_acc: 0.9898\n", "Epoch 17/20\n", "60000/60000 [==============================] - 86s 1ms/step - loss: 0.0067 - acc: 0.9976 - val_loss: 0.0365 - val_acc: 0.9892\n", "Epoch 18/20\n", "60000/60000 [==============================] - 88s 1ms/step - loss: 0.0070 - acc: 0.9977 - val_loss: 0.0371 - val_acc: 0.9898\n", "Epoch 19/20\n", "60000/60000 [==============================] - 86s 1ms/step - loss: 0.0054 - acc: 0.9982 - val_loss: 0.0440 - val_acc: 0.9888\n", "Epoch 20/20\n", "60000/60000 [==============================] - 87s 1ms/step - loss: 0.0059 - acc: 0.9981 - val_loss: 0.0346 - val_acc: 0.9900\n", "CNN Error: 1.00%\n" ] } ], "source": [ "# Fitando o modelo\n", "model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=20, batch_size=200, verbose=1)\n", "# Avaliação final do modelo\n", "scores = model.evaluate(X_test, y_test, verbose=0)\n", "print(\"CNN Error: %.2f%%\" % (100-scores[1]*100))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Esta avaliação de erro faz sentido? Usamos a melhor versão do nosso modelo? \n", "### Não! Contaminamos a análise usando os dados de teste como validação. \n", "### Talvez! 10 não é um número mágico! Talvez treinar mais resultasse em uma acurácia maior! " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Para consertar isso, dividimos o set de treino em dois pedaços, um de treino e outro de validação:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "from sklearn.model_selection import train_test_split" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "X_real_train,X_validation,Y_real_train,Y_validation = train_test_split(X_train,y_train, test_size = 0.2)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "# estabelecemos então uma função de callback do keras chamada early stopping\n", "from keras.callbacks import EarlyStopping" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Com o early stopping, o modelo para de ser treinado a partir do momento que o erro de validação para de cair. Neste contexto, o parâmetro patience indica quantas etapas de treinamento consecutivas o erro de valicação deve ser não decrescente até que o modelo pare de treinar. Isso é importante para evitar que algum efeito de ruído aumente seu erro de validação em uma época de treinamento e você pare de treinar o seu modelo mais cedo do que o necessário por causa disso." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "callbacks = [EarlyStopping(monitor = 'val_loss', patience = 2)]" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "# Alteramos então a chamada do método fit:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Train on 48000 samples, validate on 12000 samples\n", "Epoch 1/20\n", "48000/48000 [==============================] - 66s 1ms/step - loss: 0.0044 - acc: 0.9987 - val_loss: 0.0021 - val_acc: 0.9994\n", "Epoch 2/20\n", "48000/48000 [==============================] - 68s 1ms/step - loss: 0.0045 - acc: 0.9987 - val_loss: 0.0025 - val_acc: 0.9989\n", "Epoch 3/20\n", "48000/48000 [==============================] - 67s 1ms/step - loss: 0.0052 - acc: 0.9984 - val_loss: 0.0028 - val_acc: 0.9989\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "model.fit(X_real_train, Y_real_train, validation_data=(X_validation,Y_validation), epochs=20, \n", " batch_size=200, verbose=1, callbacks = callbacks)\n" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CNN Error: 0.93%\n" ] } ], "source": [ "scores = model.evaluate(X_test, y_test, verbose=0)\n", "print(\"CNN Error: %.2f%%\" % (100-scores[1]*100))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note que - com o early stopping, treinamos por menos etapas, mas obtivemos um modelo com performance melhor." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Deep convolutional Neural Network" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vamos agora fazer uma rede com duas camadas convolucionais! " ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "# CNN maior\n", "import numpy\n", "from keras.datasets import mnist\n", "from keras.models import Sequential\n", "from keras.layers import Dense\n", "from keras.layers import Dropout\n", "from keras.layers import Flatten\n", "from keras.layers.convolutional import Conv2D\n", "from keras.layers.convolutional import MaxPooling2D\n", "from keras.utils import np_utils\n", "from keras import backend as K\n", "from sklearn.model_selection import train_test_split\n", "from keras.callbacks import EarlyStopping\n", "K.set_image_dim_ordering('th')\n", "# fixando a random seed:\n", "seed = 7\n", "numpy.random.seed(seed)\n", "# load data\n", "(X_train, y_train), (X_test, y_test) = mnist.load_data()\n", "# reshape to be [samples][pixels][width][height]\n", "X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')\n", "X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32')\n", "# normalizando os inputs 0-255 to 0-1\n", "X_train = X_train / 255\n", "X_test = X_test / 255\n", "# one hot encode outputs\n", "y_train = np_utils.to_categorical(y_train)\n", "y_test = np_utils.to_categorical(y_test)\n", "num_classes = y_test.shape[1]\n", "# separando o treinamento entre treino e validação: \n", "X_real_train,X_validation,Y_real_train,Y_validation = train_test_split(X_train,y_train, test_size = 0.2)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [], "source": [ "# define the larger model\n", "def larger_model():\n", " # create model\n", " model = Sequential()\n", " model.add(Conv2D(30, (5, 5), input_shape=(1, 28, 28), activation='relu'))\n", " model.add(MaxPooling2D(pool_size=(2, 2)))\n", " model.add(Conv2D(15, (3, 3), activation='relu'))\n", " model.add(MaxPooling2D(pool_size=(2, 2)))\n", " model.add(Dropout(0.2))\n", " model.add(Flatten())\n", " model.add(Dense(128, activation='relu'))\n", " model.add(Dense(50, activation='relu'))\n", " model.add(Dense(num_classes, activation='softmax'))\n", " # Compile model\n", " model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n", " return model" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "_________________________________________________________________\n", "Layer (type) Output Shape Param # \n", "=================================================================\n", "conv2d_2 (Conv2D) (None, 30, 24, 24) 780 \n", "_________________________________________________________________\n", "max_pooling2d_2 (MaxPooling2 (None, 30, 12, 12) 0 \n", "_________________________________________________________________\n", "conv2d_3 (Conv2D) (None, 15, 10, 10) 4065 \n", "_________________________________________________________________\n", "max_pooling2d_3 (MaxPooling2 (None, 15, 5, 5) 0 \n", "_________________________________________________________________\n", "dropout_2 (Dropout) (None, 15, 5, 5) 0 \n", "_________________________________________________________________\n", "flatten_2 (Flatten) (None, 375) 0 \n", "_________________________________________________________________\n", "dense_5 (Dense) (None, 128) 48128 \n", "_________________________________________________________________\n", "dense_6 (Dense) (None, 50) 6450 \n", "_________________________________________________________________\n", "dense_7 (Dense) (None, 10) 510 \n", "=================================================================\n", "Total params: 59,933\n", "Trainable params: 59,933\n", "Non-trainable params: 0\n", "_________________________________________________________________\n" ] } ], "source": [ "# build the model\n", "model = larger_model()\n", "model.summary()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note a diferença brutal entre a quantidade de parâmetros da primeira rede que treinamos e essa. Uma redução de 10 vezes! Vamos ver se essa redução de parâmetros tém impacto negativo na perforamnce." ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Train on 48000 samples, validate on 12000 samples\n", "Epoch 1/20\n", "48000/48000 [==============================] - 68s 1ms/step - loss: 0.4338 - acc: 0.8694 - val_loss: 0.1082 - val_acc: 0.9696\n", "Epoch 2/20\n", "48000/48000 [==============================] - 63s 1ms/step - loss: 0.1089 - acc: 0.9669 - val_loss: 0.0825 - val_acc: 0.9746\n", "Epoch 3/20\n", "48000/48000 [==============================] - 67s 1ms/step - loss: 0.0773 - acc: 0.9759 - val_loss: 0.0632 - val_acc: 0.9800\n", "Epoch 4/20\n", "48000/48000 [==============================] - 65s 1ms/step - loss: 0.0626 - acc: 0.9805 - val_loss: 0.0517 - val_acc: 0.9859\n", "Epoch 5/20\n", "48000/48000 [==============================] - 65s 1ms/step - loss: 0.0520 - acc: 0.9830 - val_loss: 0.0452 - val_acc: 0.9870\n", "Epoch 6/20\n", "48000/48000 [==============================] - 66s 1ms/step - loss: 0.0492 - acc: 0.9841 - val_loss: 0.0451 - val_acc: 0.9863\n", "Epoch 7/20\n", "48000/48000 [==============================] - 65s 1ms/step - loss: 0.0422 - acc: 0.9860 - val_loss: 0.0406 - val_acc: 0.9881\n", "Epoch 8/20\n", "48000/48000 [==============================] - 65s 1ms/step - loss: 0.0370 - acc: 0.9881 - val_loss: 0.0354 - val_acc: 0.9907\n", "Epoch 9/20\n", "48000/48000 [==============================] - 63s 1ms/step - loss: 0.0343 - acc: 0.9891 - val_loss: 0.0379 - val_acc: 0.9891\n", "Epoch 10/20\n", "48000/48000 [==============================] - 65s 1ms/step - loss: 0.0315 - acc: 0.9901 - val_loss: 0.0340 - val_acc: 0.9902\n", "Epoch 11/20\n", "48000/48000 [==============================] - 63s 1ms/step - loss: 0.0309 - acc: 0.9897 - val_loss: 0.0385 - val_acc: 0.9889\n", "Epoch 12/20\n", "48000/48000 [==============================] - 65s 1ms/step - loss: 0.0272 - acc: 0.9910 - val_loss: 0.0320 - val_acc: 0.9909\n", "Epoch 13/20\n", "48000/48000 [==============================] - 65s 1ms/step - loss: 0.0257 - acc: 0.9908 - val_loss: 0.0337 - val_acc: 0.9898\n", "Epoch 14/20\n", "48000/48000 [==============================] - 64s 1ms/step - loss: 0.0233 - acc: 0.9923 - val_loss: 0.0356 - val_acc: 0.9900\n", "Large CNN Error: 0.88%\n" ] } ], "source": [ "callbacks = [EarlyStopping(monitor = 'val_loss', patience = 2)]\n", "# Fit the model\n", "model.fit(X_real_train, Y_real_train, validation_data=(X_validation,Y_validation), epochs=20, \n", " batch_size=200, verbose=1, callbacks = callbacks)\n", "# Final evaluation of the model\n", "scores = model.evaluate(X_test, y_test, verbose=0)\n", "print(\"Large CNN Error: %.2f%%\" % (100-scores[1]*100))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "O modelo Melhorou ainda mais! \n", "Espero que este tutorial ajude na compreensão do uso da biblioteca do Keras para construção de redes neurais simples. Para mais informações, o site do próprio keras tem explicações e tutoriais bem detalhados sobre mais casos de uso! \n", "https://keras.io/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Divirtam-se! " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.12" }, "toc": { "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 2 }