{"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":{"_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","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/test/testset","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":"df.head()","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":{},"cell_type":"markdown","source":"## Respostas do grupo\n\nQuantas imagens possuímos para treino?","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"# Cuidado ao usar o método count(), ele retorna a contagem de atributos não nulos. Logo, se houver um atributo com valor nulo, ele não entrará na contagem.\ndf.count()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"root = '../input/vehicle/train/train'\nfor root, directories, files in os.walk(root):\n    if len(files)==0:\n        pass\n    else:\n        print(root)#exibir dretório\n        print(len(files))#exibir quantidade de arquivos por pastas","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df.shape[0]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Quantas imagens possuímos para teste?","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"root = '../input/vehicle/test/testset'\ndata = []\nfor file in sorted(os.listdir(root)):\n    data.append(file)\n\ndft = pd.DataFrame(data, columns=['file_path'])\ndft.count()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_data = '../input/vehicle/test/testset'\nos.listdir(test_data)\nfor root_test, directories_test, files_test in os.walk(test_data):\n    print(root_test)\n    print(len(files_test))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dft.shape[0]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Quantas imagens possuímos por classe?\n\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df.groupby('class').size()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pics_by_class = df.groupby(['class']).count()\npics_by_class.rename(columns = {'file_path':'quantity'}, inplace = True)\npics_by_class_order = pics_by_class.sort_values(by='quantity')\npics_by_class_order","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['class'].value_counts(ascending=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Existe alguma classe muito desbalanceada? Ex: Se uma classe tiver muito mais amostras do que outra classe, o dataset está desbalanceado.\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"df['class'].value_counts().plot(kind='bar')\nplt.title('Class counts')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"max_value = pics_by_class_order.max().quantity\n\nunbalanced = [] \nmean = pics_by_class_order.mean()[0]\ntolerance = mean*0.15#desvio padrao, abaixo do 1ºquartil ou acima 4º quartil\n\nfor pics in pics_by_class_order.iloc[:, -1]:\n    if pics<(mean-tolerance) or pics>(mean+tolerance):\n        unbalanced.append(pics)\n\nprint(unbalanced)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df['class'].value_counts().mean()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"(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","execution_count":null},{"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":{},"cell_type":"markdown","source":"Todas as imagens do dataset possuem o mesmo tamanho?\n","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"from PIL import Image \nroot = \"../input/vehicle/train/train/Ambulance\"\nfor file in sorted(os.listdir(os.path.join(root))):\n    data = Image.open(os.path.join(root,file))\n    print(data.size)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"unique_sizes = set()\nroot = \"../input/vehicle/train/train/Ambulance\"\nfor file in sorted(os.listdir(os.path.join(root))):\n    data = Image.open(os.path.join(root,file))\n    unique_sizes.add(data.size)\nprint(f\"Tamanhos únicos encontrados {len(unique_sizes)} para uma única classe\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"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","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"data = defaultdict(lambda: defaultdict(list))\nmodified_df = df\nwidth = []\nheight = []\nfor idx, row in tqdm(df.iterrows(), total=len(df)):\n    image = Image.open(row[1])\n    data[row[0]]['width'].append(image.size[0])\n    width.append(image.size[0])\n    data[row[0]]['height'].append(image.size[1])\n    height.append(image.size[1])\ndef plot_dist(category):\n    '''plot height/width dist curves for given category'''\n    fig, ax = plt.subplots(figsize=(10, 10))\n    sns.distplot(data[category]['height'], color='darkorange', ax=ax).set_title(category, fontsize=16)\n    sns.distplot(data[category]['width'], color='purple', ax=ax).set_title(category, fontsize=16)\n    plt.xlabel('size', fontsize=15)\n    plt.legend(['height', 'width'])\n    plt.show()\nfor category in df['class'].unique():\n    plot_dist(category)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Existe uma correção entre largura ou altura e a respectiva classe? Dica, utilize a função corr do pandas","execution_count":null},{"metadata":{"trusted":true},"cell_type":"code","source":"modified_df['width'] = width\nmodified_df['height'] = height\ndiv = {v:i+1 for i, v in enumerate(modified_df['class'].unique()) }\nmodified_df['mod_class'] = [div[x] for x in modified_df.iloc[:, 0]]\nmodified_df.corr()","execution_count":null,"outputs":[]}],"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}