Utilizando TransferLearning para detectar o correto uso de máscaras

Matheus Ricardo dos Santos
5 min readSep 14, 2021

Este artigo contém a implementação das técinicas de feature extraction e fine tuning utilizando o Tensorflow.

1. Introdução

O objetivo deste artigo é descrever os passos necessários para criar uma rede convolucional que seja capaz de detectar se uma pessoa está utilizando corretamente a máscara a partir de uma foto de seu rosto. Para isso, será utlizada uma tecnica conhecida como Transfer Learning.

A intuição por trás do aprendizado de transferência para classificação de imagens é que se um modelo for treinado em um conjunto de dados grande e geral o suficiente, esse modelo servirá efetivamente como um modelo genérico do mundo visual. Você pode então tirar proveito desses mapas de recursos aprendidos sem ter que começar do zero, treinando um grande modelo em um grande conjunto de dados.
https://www.tensorflow.org/tutorials/images/transfer_learning

Esta técnica pode ser utilizada para usufruir do conhecimento e de informações aprendidas por modelos conhecidos e treinados em milhões de dados. Estes dados não precisam fazer parte do mesmo problema que estamos resolvendo. No exemplo a seguir, vamos classificar o uso de máscaras através da estrutura de uma rede(ResNet) treinada para classificar animais e que utilizou como base de dados o ImageNet.

2. Base de dados

A base de dados contém 9000 imagens distribuidas igualmente em três classes:

  • with_mask
  • without_mask
  • wearing_mask_incorrectly

A base foi obtida no Kaggle através do seguinte link: https://www.kaggle.com/vijaykumar1799/face-mask-detection.

3. Construção dos modelos

Feature Extraction e Fine-Tuning são duas técnicas de Transfer Learning bastante utilizadas. Contruiremos dois modelos utilizadando cada uma destas tecnicas.

3.1 Feature Extraction

Esta técnica consiste em utilizar a representação aprendidas por uma rede anterior para extrair recursos significativos de novos exemplos. Um modelo convolucional robusto provavelmente é capaz de aprender a detectar bordas, curvas e texturas de imagens. Esta habilidade é importante para extrair características de uma inifina gama de problemas.

Primeriamente precisamos importar um modelo pré-treinado. Utilizaremos a arquitetura VGG16 com o dataset ImageNet:

from tensorflow.keras.applications import VGG16
model = VGG16(weights="imagenet", include_top=False)

O parametro include_top=False é importante pois ele remove as camadas de classificação da VGG16 mantendo somente as camadas responsáveis pela extração de características.

Com o modelo carregado podemos realizar as extrações. Para isso, basta passar as imagens para o modelo.

features = model.predict(batchImages, batch_size=bs)# redimensiona o output para que tenha apenas 1 dimensão
features = features.reshape((features.shape[0], 512 * 7 * 7))

Por fim, basta treinar um classificador com as features geradas:

from sklearn.neural_network  import MLPClassifieri = int(labels.shape[0] * 0.75)model = MLPClassifier(solver="adam",a lpha=1e-5,hidden_layer_sizes=(250, 100, ))model.fit(features[:i], labels[:i])

Como resultado obtivemos 99% de acurácia com apenas alguns passos simples:

3.2 Fine Tuning

Esta técnica consiste em descongelar algumas das camadas superiores de uma base de modelo congelada e, em conjunto, treinar as camadas classificadoras recém-adicionadas e as últimas camadas do modelo base.

Para este exemplo vamos utilizar o modelo ResNet50 treinado na base imagenet.

from tensorflow.keras.applications import ResNet50# mais uma vez passamos include_top=False
baseModel = ResNet50(weights="imagenet", include_top=False,input_tensor=Input(shape=(224, 224, 3)))

Agora precisamos modificar o modelo importado adicionando as camadas de classificação no topo:

# import the necessary packages
from tensorflow.keras.layers import Dropout
from tensorflow.keras.layers import Flatten
from tensorflow.keras.layers import Dense
# a fully connect network
class FCHeadNet:
@staticmethod
def build(baseModel, classes, D):

# initialize the head model that will be placed on top of
# the base, then add a FC layer
headModel = baseModel.output
headModel = Flatten(name="flatten")(headModel)
headModel = Dense(D, activation="relu")(headModel)
headModel = Dropout(0.5)(headModel)

# add a softmax layer
headModel = Dense(classes, activation="softmax")(headModel)
return headModel

Criando o modelo final:

from tensorflow.keras.models import ModelheadModel = FCHeadNet.build(baseModel, num_classes, 256)model = Model(inputs=baseModel.input, outputs=headModel)

Antes de iniciar o treino precisamos congelar algumas camadas do modelo base

# congela todas a camadas
for layer in baseModel.layers:
layer.trainable = False
# descongelar apenas algumas camadas
for layer in baseModel.layers[165:]:
if (layer.__class__.__name__ != 'BatchNormalization'):
layer.trainable = True

Segundo a documentação do prórpio TensorFlow é recomendado não descongelar as camadas de BatchNormalization:

Quando você descongelar um modelo que contém camadas BatchNormalization, a fim de fazer o ajuste fino, você deve manter as camadas BatchNormalization no modo de inferência passando training = False ao chamar o modelo base. Caso contrário, as atualizações aplicadas aos pesos não treináveis ​​destruirão o que o modelo aprendeu.

Por fim, basta compitar o modelo e configurar o treino:

from tensorflow.keras.optimizers import SGDopt = SGD(learning_rate=0.001)model.compile(loss="categorical_crossentropy", optimizer=opt, metrics=["accuracy"])history = model.fit(features, labels, steps_per_epoch=44, validation_data=(val_features, val_labels), validation_steps=44, epochs=5, max_queue_size=10, verbose=1)

Como resultado obtivemos um modelo com 98% de acurácia

4. Conclusões

Ambos os modelos obtiveram ótimos resultados com apenas a implementação de alguns passos simples. Isto mostra o poder que as técnicas de TransferLearning trazem para facilitar a contrução de modelos e diminuir o tempo de treino.

Os códigos acima apresentam apenas os passos relacionados ao carregamento e à manipulação dos modelos. No entando, existem alguns passos importantes que foram omitidos. Estes passos são relacionados ao carregamento e à conversão das imagens para hdf5 e à utilização de processos de data augmentation.

Os códigos completos estão dispostos no seguinte repositório:

5. Referências

Como base para os códigos acima foram utilizados os códigos destes dois notebooks:

--

--