{"cells":[{"metadata":{},"cell_type":"markdown","source":"# TAU Vehicle Type Recognition Competition\n\nNessa atividade prática estaremos trabalhando em cima de um problema de classificação, onde o objetivo é predizer o tipo de um veículo. Para isso, iremos utilizar o dataset da competição [TAU Vehicle Type Recognition Competition](https://www.kaggle.com/c/vehicle) que é um subconjunto da base de dados [Open Images Dataset](https://storage.googleapis.com/openimages/web/index.html), contendo 17 classes diferentes de veículos, sendo elas:\n\n* Ambulance, Boat, Cart, Limousine, Snowmobile, Truck, Barge, Bus, Caterpillar, Motorcycle, Tank, Van, Bicycle, Car, Helicopter, Segway, Taxi\n\nA primeira fase do projeto é realizar a Análise Exploratória dos Dados (EDA), onde o objetivo é encontrar características que podem ajudar a facilitar o desenvolvimento de um modelo para predição dos tipos de veículos.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nfrom collections import defaultdict\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom PIL import Image # biblioteca para o processamento de imagens\nfrom tqdm import tqdm_notebook as tqdm # biblioteca para exibição de barra de progresso\nfrom pandas.plotting import scatter_matrix\np = sns.color_palette()\n\nfrom collections import OrderedDict\nimport cv2\nimport keras\n# For one-hot-encoding\nfrom keras.utils import np_utils\n# For creating sequenttial model\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D,MaxPooling2D,Dense,Flatten,Dropout\n# For saving and loading models\nfrom keras.models import load_model\nimport tensorflow as tf\n\nimport random\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Primeiramente vamos analisar como o dataset está estruturado","execution_count":null},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"!ls -lh ../input/vehicle/","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"O arquivo `sample_submission.csv` é um arquivo de exemplo de como a submissão, ou arquivo contendo as predições do dataset de test deve ser formatado para ser enviado a competição.\n\nA pasta `test` contém o conjunto de dados de teste\n\nA pasta `train` contém o conjunto de dados de treino","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls -lh ../input/vehicle/train/train","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Dentro da pasta de `train` existe uma subpasta `train` contendo subpastas com imagens de cada classe existente no problema.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"!ls -lh ../input/vehicle/test/testset | head -5","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"O conjunto de dados de teste está presente na subpasta `testset` dentro da pasta `test` e não possui os rótulos, pois somente o Kaggle possui as anotações reais para fazer a avaliação do modelo.\n\nPara facilitar o desenvolvimento do modelo, vamos realizar uma etapa de pré-processamento dos dados para formatá-los em um DataFrame utilizando a biblioteca `pandas`.","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"root = '../input/vehicle/train/train/'\ndata = []\nfor category in sorted(os.listdir(root)):\n    for file in sorted(os.listdir(os.path.join(root, category))):\n        data.append((category, os.path.join(root, category,  file)))\n\ndf = pd.DataFrame(data, columns=['class', 'file_path'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(df.info())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(df.info())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(df.describe())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig = plt.figure(figsize=(25, 16))\nfor num, category in enumerate(sorted(df['class'].unique())):\n    for i, (idx, row) in enumerate(df.loc[df['class'] == category].sample(4).iterrows()):\n        ax = fig.add_subplot(17, 4, num * 4 + i + 1, xticks=[], yticks=[])\n        im = Image.open(row['file_path'])\n        plt.imshow(im)\n        ax.set_title(f'Class: {category}')\nfig.tight_layout()\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(df.groupby('class').size())","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['class'].value_counts().plot(kind='bar');","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"root = '../input/vehicle/test/testset/'\ndata = []\nfor category in sorted(os.listdir(root)):\n    for file in sorted((os.path.join(root, category))):\n        data.append((category, os.path.join(root, category,  file)))\n        \n\ndt = pd.DataFrame(data, columns=['class', 'file_path'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dt.head()\nprint(df.info())\nprint(dt.describe())\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data = []\nlabels = []\n\ncols = []\ncol_imgs = []","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"cols = sorted(cols)\n\n# Creating trainable 224x224 images\n#                    -------\nfor vehicle_class in cols:\n    print(vehicle_class + \" started .....\")\n    for filename in df[vehicle_class]:\n        try:\n            # for empty cols\n            if filename == None:\n                pass\n            else:\n                image = cv2.imread(\"/kaggle/input/vehicle/train/train/{}/\".format(vehicle_class) + filename)\n                image_from_numpy_array = Image.fromarray(image, \"RGB\")\n                resized_image = image_from_numpy_array.resize((224, 224))\n                data.append(np.array(resized_image))\n\n                if vehicle_class == 'Ambulance':\n                    labels.append(0)\n                elif vehicle_class == 'Barge':\n                    labels.append(1)\n                elif vehicle_class == 'Bicycle':\n                    labels.append(2)\n                elif vehicle_class == 'Boat':\n                    labels.append(3)\n                elif vehicle_class == 'Bus':\n                    labels.append(4)\n                elif vehicle_class == 'Car':\n                    labels.append(5)\n                elif vehicle_class == 'Cart':\n                    labels.append(6)\n                elif vehicle_class == 'Caterpillar':\n                    labels.append(7)\n                elif vehicle_class == 'Helicopter':\n                    labels.append(8)\n                elif vehicle_class == 'Limousine':\n                    labels.append(9)\n                elif vehicle_class == 'Motorcycle':\n                    labels.append(10)\n                elif vehicle_class == 'Segway':\n                    labels.append(11)\n                elif vehicle_class == 'Snowmobile':\n                    labels.append(12)\n                elif vehicle_class == 'Tank':\n                    labels.append(13)\n                elif vehicle_class == 'Taxi':\n                    labels.append(14)\n                elif vehicle_class == 'Truck':\n                    labels.append(15)\n                elif vehicle_class == 'Van':\n                    labels.append(16)\n                else:\n                    print(\"Something is wrong.\")\n                \n        except AttributeError:\n            print(\"Attribute error occured for \"+filename)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"vehicle_images_224x224 = np.array(data)\nlabels_224x224 = np.array(labels)\n\n# save\nnp.save(\"all-vehicle-224x224-images-as-arrays\", vehicle_images_224x224)\nnp.save(\"corresponding-labels-for-all-224x224-images\", labels_224x224)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(vehicle_images_224x224.shape)\nprint(labels_224x224.shape)\nprint(np.unique(labels_224x224))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Move images to `test` and `train` dir\nimport shutil\nimport os\n\nos.mkdir(\"/kaggle/working/data\")\nos.mkdir(\"/kaggle/working/data/test\")\nos.mkdir(\"/kaggle/working/data/train\")\n\nclasses = []\n\nfor dir in [\"test\", \"train\"]:\n    for _class in classes:\n        os.mkdir(\"/kaggle/working/data/{}/{}\".format(dir, _class))\n\nfor _class in classes:\n    images = os.listdir(\"/kaggle/input/vehicle/train/train/{}\".format(_class))\n\n    test = images[:300]\n    \n    # downsample to 1.5k images\n    if len(images) < 1500:\n      train = images[300:]\n    else:\n      train = images[300:1500]\n\n    # move images to test-set folder\n    for image in test:\n        shutil.copy(\"/kaggle/input/vehicle/train/train/{}/{}\".format(_class, image), \"/kaggle/working/data/test/{}/{}\".format(_class, image))\n\n    # move images to train-set folder\n    for image in train:\n        shutil.copy(\"/kaggle/input/vehicle/train/train/{}/{}\".format(_class, image), \"/kaggle/working/data/train/{}/{}\".format(_class, image))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import numpy as np\n%matplotlib inline\nimport matplotlib.pyplot as plt\nfrom PIL import Image","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import keras\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.applications import ResNet50\nfrom keras.applications.resnet50 import preprocess_input\nfrom keras import Model, layers\nfrom keras.models import load_model, model_from_json","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"input_path = \"/kaggle/working/data/\"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n    shear_range=10,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    preprocessing_function=preprocess_input)\n\ntrain_generator = train_datagen.flow_from_directory(\n    input_path + 'train',\n    batch_size=32,\n    #class_mode='binary',\n    target_size=(224,224))\n\nvalidation_datagen = ImageDataGenerator(\n    preprocessing_function=preprocess_input)\n\nvalidation_generator = validation_datagen.flow_from_directory(\n    input_path + 'test',\n    shuffle=False,\n    #class_mode='binary',\n    target_size=(224,224))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"conv_base = ResNet50(\n    include_top=False,\n    weights='imagenet')\n\nfor layer in conv_base.layers:\n    layer.trainable = False\n\nx = conv_base.output\nx = layers.GlobalAveragePooling2D()(x)\nx = layers.Dense(128, activation='relu')(x) \npredictions = layers.Dense(7, activation='softmax')(x)\nmodel = Model(conv_base.input, predictions)\n\n# Note sgd \noptimizer = keras.optimizers.SGD(lr=1e-2, momentum=0.9, decay=1e-2/60)\nmodel.compile(loss='categorical_crossentropy',\n              optimizer=optimizer,\n              metrics=['accuracy'])\n\nhistory = model.fit_generator(generator=train_generator,\n                              steps_per_epoch=347 // 32, \n                              epochs=60,\n                              validation_data=validation_generator,\n                              validation_steps=10  \n                             )","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Exploratory Data Analysis (EDA)\n\nA partir desse trecho iremos escrever código para responder as seguintes perguntas:\n\n* Quantas imagens possuímos para treino?\n* Quantas imagens possuímos para teste?\n* Quantas imagens possuímos por classe? \n* Existe alguma classe muito desbalanceada? Ex: Se uma classe tiver muito mais amostras do que outra classe, o dataset está desbalanceado.\n* (Opcional) Desenvolver método que exiba um subconjunto das imagens de diferentes classes. Dica: utilize o `matplotlib` e sua função de `plt.figure` \n* Todas as imagens do dataset possuem o mesmo tamanho?\n* Analise o histrograma de altura e largura para cada classe do dataset. Existem classe que a largura ou a altura podem ajudar distinguir determinadas classes? Ex: a classe cart na média possui imagens mais largas que da classe limousine?\n* Existe uma correção entre largura ou altura e a respectiva classe? Dica, utilize a função `corr` do `pandas`","execution_count":null}],"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":4,"nbformat_minor":4}