Classificação de roupas com Deep Learning

Rafael Messias Grecco
6 min readFeb 10, 2021

--

O primeiro Hello, World

Acredito que muitos aqui já devem ter feito seu primeiro Hello, world em alguma linguagem, para aqueles que não fizeram aqui está o código em python print('Hello, world').

Relembrando esse momento mágico do Hello, world que todos tivemos, o dataset que vamos trabalhar hoje é considerado o Hello, world do Deep Learning e Visão Computacional.

Sem mais mistérios, o dataset é o Fashion MNIST que contém 70 mil imagens de 10 classes diferentes. Dessas 70 mil imagens 60 mil são para treino e 10 mil para teste e cada uma dessas imagens tem uma dimensão de 28 x 28 pixels e essas estão distribuídas em 10 labels

Fashion MNIST

O dataset que vamos utilizar foi criado para substituir o MNIST Tradicional uma vez que o mesmo já não representava um real desafio, onde as imagens eram digitos que CNNs conseguiam atingir mais de 99% de acurácia.

MNIST Tradicional

Obtenção dos dados

Para obter esse dataset há duas maneiras, uma é direto pelo repositório no github Link e a outra é importar a partir do TensorFlow, neste projeto vou importar a partir do TensorFlow com a função fashion_mnist.load_data().

Importando as Bibliotecas necessárias

Nesta etapa após a última biblioteca setamos algumas ferramentas com a finalidade de obter gráficos com mais qualidade.

Exploração dos Dados

Sendo este um dataset padrão e muito utilizado, nossos dados já estão pré-processados, no entanto vamos verificar as dimensões dos arrays que temos até o momento.

Vamos aproveitar e ver uma imagem convertida em array também, vale ressaltar que em nosso array o maior valor é 255 que corresponde ao branco e o menor é 0 que corresponde ao preto absoluto.

Em X_train_ini[0][:7][:7] pedimos para trazer a primeira imagem e as suas primeiras 7 linhas e 7 colunas. A saída da célula acima foi:

Como pode-se ver, nas dimensões nos foi retornado um array em 3 dimensões, a primeira é o número total de imagens, a segunda e a terceira são respectivamente a altura e a largura das imagens.

Como já explicado, nós temos 10 labels, no entanto como as imagens estão distribuídas nesses labels? Por exemplo será que o número de imagens de bolsas é muito maior que o número de imagens de camisas, caso sim, temos um problema, pois isso pode afetar o desempenho do modelo, então vamos verificar como nosso dataset está balanceado, para isso vamos usar a biblioteca Numpy . Primeira vamos ver como está o dataset de Treino.

A saída dessa célula foi

Fazendo o mesmo processo, mas aplicado ao dataset de Teste nos foi retornado

Como podemos ver tanto o dataset de treino como o de teste estão muito bem balanceados, todos os labels possuem o mesmo número de imagens. Vale ressaltar que não necessariamente tinha que ter o mesmo valor, isso é o ideal, no entanto basta que não tenha uma diferença enorme entre eles.

Para encerrar essa etapa de exploração de dados, vamos plotar algumas imagens do nosso dataset

Pré-Processamento das imagens

Temos que realizar esse processo antes de treinar a rede neural e a mesma será divida em algumas etapas:

  • Normalizar os Pixels
  • Redimensionar as imagens
  • One-Hot Encoding

Normalizar os Pixels

Nesta etapa vamos fazer os valores de cada pixel, que como já foi mencionado está no intervalo [0,255], ficarem no intervalo [0,1], essencialmente queremos transformar os valores dos pixels para o tipo float. Para fazer isso basta dividir todos os pixels pelo maior valor possível, nesse caso 255.0.

O TensorFlow espera que nosso array seja do tipo float32, usando a função astype vamos fazer isso nessa etapa também

Para fins de produtividade foi criada uma função lambdapara fazer a normalização e a conversão em float32 , depois foi só aplicar essa função aos datasets X_train_ini e X_test_ini.

Redimensionar as imagens

O **TensorFlow** espera uma lista com 4 dimensões e se voltarmos no começo vamos ver que os datasets de treino e teste estão nos retornando uma lista com 3 dimensões. A lista que o TensorFlow espera é da forma (m, a, l, c), onde

  • m = Número de imagens
  • a = Altura
  • l = Largura
  • c = Número de canais

Como podemos ver o vetor que nos foi retornado na etapa de exploração de dados tem essas 3 primeiras dimensões exigidas, falta apenas adicionar o número de canais, como as imagens estão em escala cinza, o número de canais é 1.

Obs: Caso fossem imagens coloridas (RGB), o número de canais seria 3.

Para realizar essa mudança vamos usar a função reshape() no X_train e noX_test

Nas duas últimas linhas imprimimos como ficou o shape de X_train e X_test a saída foi:

Como podemos verificar, agora temos uma lista com 4 dimensões na forma (m, a, l, c), com a função reshape() nós adicionamos o número de canais.

One-Hot Encoding

Nossos labels estão no que chamamos de Integer encoding é possível utilizar dessa forma, no entanto pode fazer com que o modelo de deep learning entenda que existe uma relação entre as ordens dos labels.

Por exemplo, Camisetas/Top tem label igual a 0, Calça tem label igual a 1 isso pode levar o modelo a concluir que esses valores possuem uma relação e com isso o desempenho é afetado. Caso nossos labels tivessem uma relação ordinal não precisaríamos dessa etapa.

Caso queira mais informações sobre sobre One-hot Encoding, Leia este artigo.

Podemos realizar esse processo de forma muito simples e rápida utilizando o Keras com a função to_categorical , como estamos trabalhando com os labels, vamos usar o Y_train e Y_test

E pronto aplicamos o One-Hot Encoding, eu recomendo que o utilize sempre em seus projetos que não possuem uma relação ordinal entre os labels.

Com essa etapa concluímos o Pré-Processamento de imagens e vamos a partir de agora aplicar esses dados em uma rede e treina-la.

Rede Neural Convolucional

Existem muitas arquiteturas de CNN. Para este projeto vamos usar uma simplificação da VGGNet, implementada pelo renomado cientista de dados Adrian Rosebroke, no entanto com algumas modificações.

Compilando e Treinando a Rede neural

Geralmente para a loss functionusa-se a sparse_categorical_crossentropy, no entanto como alteramos nossos labels de integer Encoding para One-hot Encoding não podemos usa-la, logo devido a isso vamos usar a categorical_crossentropy como loss function .

Na etapa de treinamento em validation_split pedimos para reservar 30% do nosso dataset para validação.

Avaliando o Modelo

A saída da célula acima é

Então como podemos observar, obtemos 93% de acurácia

Vamos plotar a evolução do nosso Modelo

Podemos notar um pequeno overfitting em alguns pontos do gráfico (O ideal é que a accuracy fique acima da curva val_accuracy). No entanto como vimos anteriormente isso não prejudicou muito a acurácia do nosso modelo.

E chegamos ao fim do projeto, espero que tenha gostado do artigo e agora replique-o em seu computador, experimente usar esse mesmo dataset com redes neurais mais simples ou mais complexas.

Caso queira o código completo, ele está hospedado no meu repositório do Github, Basta clicar aqui.

--

--

Rafael Messias Grecco

Electrical engineering student and technology enthusiast. Projects in fields such as Machine Learning, Time Series and Computer Vision. https://www.linkedin.com