Os modelos de visão baseados em transformadores estão evoluindo gradualmente e são relatados como tão bons quanto os modelos convolucionais em tarefas de classificação, segmentação e reconhecimento de ação. Temos toda uma gama de modelos Convolucionais para tarefas de visão e são mais populares do que os baseados em Transformer. Este blog investiga o modelo SWin Transformer Vision que foi apresentado na Conferência Internacional de Visão Computacional (ICCV) 2021 pela equipe de pesquisa da Microsoft. Ele compara seu desempenho com vários modelos baseados em SOTA Convolution na tarefa Dog Breed Image Classification.
Os modelos baseados em transformadores se tornarão a próxima grande novidade em Visão Computacional? Com os transformadores sendo uma solução bem-sucedida para tarefas de linguagem, ele unificará os vários subcampos de IA e apresentará soluções poderosas para problemas mais complexos? Então, arregaço as mangas para avaliar como eles são bons na tarefa de classificação para começar.
A miríade de raças de cães com mudanças sutis em suas aparências físicas tem sido um desafio para veterinários, donos de cães, funcionários de abrigos de animais e potenciais donos de cães para identificar a raça certa. Eles precisam identificar a raça para fornecer treinamento adequado, tratamento e atender às suas necessidades nutricionais. Os dados são provenientes do Stanford Dog Dataset , que contém aproximadamente 20 mil imagens de 120 raças de cães em todo o mundo. Esses dados foram divididos quase igualmente em conjunto de treinamento e teste para uma identificação de raça de cão de competição Kaggle.
O objetivo da solução é construir um sistema de identificação de raças de cães capaz de identificar corretamente raças de cães com dados mínimos e identificar corretamente até mesmo raças de cães de aparência semelhante. Esta é uma tarefa de classificação multiclasse e, para cada imagem, o modelo deve prever a probabilidade de todas as 120 raças. Aquele com a maior probabilidade é a raça mais provável do cão na imagem.
Embora não haja desequilíbrio de classes, os dados podem ser insuficientes para treinar a rede neural. O aumento da imagem usando perturbações aleatórias da imagem e modelos pré-treinados será capaz de contornar esse problema.
As 5 principais raças com mais imagens são scottish_deerhound, maltese_dog, afghan_hound, entlebucher e bernese_mountain_dog. As últimas 5 raças com menos imagens são golden_retriever, brabancon_griffon, komondor, eskimo_dog e briard.
Uma rápida análise das dimensões espaciais das imagens de treinamento é feita para entender a distribuição da altura da imagem, largura e suas proporções.
Imagens com proporções muito baixas (<0,5) e muito altas (>2,3) são consideradas imagens anômalas. 1,5 é considerado uma boa proporção.
Ao analisar várias raças de cães, os pares de raças abaixo geralmente são parecidos.
Esta arquitetura é baseada no “Swin Transformer: Hierarchical Vision Transformer using Shifted Windows” desenvolvido pela Microsoft Research Team. Este artigo discute uma arquitetura ViT aprimorada que produz uma representação hierárquica de mapas de recursos, reduzindo a complexidade computacional do mecanismo de auto-atenção de quadrático para linear. É comprovado que fornece resultados idênticos às redes de convolução SOTA, como EfficientNet, no problema de classificação da Imagenet.
Os blocos de construção desta arquitetura são explicados nas notas abaixo:
No NLP, os tokens que são os elementos de processamento de um modelo são as palavras em uma frase em que o tamanho de 1 token é 1 (apenas 1 palavra). Os ViT ( Vi sion T ransformers) tratam “patches de imagem” como tokens onde cada patch é uma partição de uma imagem que consiste em um grupo de pixels vizinhos. Cada patch de imagem é um token. O tamanho de 1 token em qualquer ViT é patch_height * patch_width * número de canais. Com base nas dimensões do patch, obtemos vários patches ou tokens para uma única imagem. Se o tamanho da imagem (H*W*3) for 224 * 224 * 3 pixels e o tamanho do patch for 4 * 4, obteremos 224/4 * 224/4 = 56 * 56 patches ou 3136 tokens da imagem. Cada token ou patch terá tamanho 4*4*3 = 48 dimensões ou 48 pixels de dados. Portanto, a entrada para a arquitetura dessa imagem consiste em 3.136 tokens, cada um com tamanho de 48 dimensões.
O mecanismo subjacente do transformador SWIN é análogo a qualquer arquitetura baseada em CNN, onde as dimensões espaciais da imagem são diminuídas e o número de canais é aumentado. O transformador SWIN em cada estágio da arquitetura hierárquica também reduz o número de patches de imagem ou o número de tokens enquanto aumenta as dimensões do token. Com esse mecanismo em mente, fica mais fácil entender a arquitetura SWIN facilmente.
Em cada estágio da arquitetura, podemos ver o número de tokens diminuindo enquanto o tamanho do token aumenta.
A arquitetura SWIN-T, além do “ Patch Partitioner”, também é composta por 3 outros blocos de construção - Linear Embedding, Swin Transformer Block, Patch Merging. Esses blocos de construção são repetidos e processam mapas de recursos de maneira hierárquica.
Cada um dos 3136 tokens de 48 dimensões do “Patch Partitioner” são alimentados para uma camada de feed forward para incorporar o token de 48 vetores de recursos em um vetor de recursos de tamanho 'C'. 'C' aqui atua como a capacidade do transformador e a arquitetura SWIN tem 4 variantes baseadas nela.
O patch de imagem e a incorporação linear são implementados em conjunto em uma única convolução cujo tamanho de kernel e comprimento de passo é o mesmo que o tamanho do patch. O número de canais no convolucional será 'C'.
O SWin Transformer Block é diferente do bloco transformador padrão na arquitetura ViT. Nos Transformadores SWin, o
O estágio 1 consiste em 2 blocos transformadores SWIN-T (consulte a imagem), onde o primeiro bloco transformador possui janela MSA (W-MSA) e o segundo bloco transformador possui módulo Shifted Window MSA (SW-MSA). No Bloco Transformador SWin, as entradas e saídas das camadas W-MSA e SW-MSA são passadas por Camadas de Normalização. Em seguida, ele é submetido a uma ativação de 2 camadas da Rede Feed Forward com Unidades Lineares de Erro Gaussiano (GELU). Existem conexões residuais dentro de cada bloco e entre esses 2 blocos.
Módulos Janela MSA (W-MSA) e Janela Deslocada MSA (SW-MSA)
A camada de atenção padrão no ViT era global, calculando a atenção de um patch com todos os outros patches na imagem, levando a uma complexidade quadrática proporcional às dimensões da imagem. Isso não escala muito bem para imagens de alta resolução.
O mecanismo de autoatenção no módulo W-MSA ou SW-MSA é local que calcula a autoatenção apenas entre manchas dentro da mesma janela da imagem e não fora das janelas.
As janelas são como partições maiores da imagem, onde cada janela é composta por patches M*M. Substituir a autoatenção global pela autoatenção local reduziu a complexidade computacional de quadrática para linear.
A principal diferença entre os módulos de atenção W-MSA e SW-MSA está na forma como as janelas da imagem são configuradas.
No módulo W-MSA, uma estratégia regular de particionamento de janela é seguida. A imagem é particionada uniformemente em janelas não sobrepostas a partir do pixel superior esquerdo da imagem, e cada janela contém patches M*M ou M2 .
No módulo SW-MSA, a configuração da janela é deslocada da camada W-MSA, deslocando as janelas por patches (M/2, M/2) da estratégia de particionamento regular.
Como a atenção é restrita localmente dentro de uma janela no W-MSA, a janela deslocada permite que a atenção entre janelas ainda produza os benefícios da atenção global. Isso é possível porque os limites da janela 1 na camada W-MSA são compartilhados com as janelas W2, W4 e W5 na camada SW-MSA. Portanto, a atenção global acontece indiretamente via “atenção local em janelas deslocadas”.
A camada Patch Merging reduz o número de tokens à medida que a rede se aprofunda cada vez mais. A primeira camada de fusão de patch concatena os recursos de cada grupo de patches vizinhos 2 × 2.
O pacote tfswin no PyPI tem variantes TF-Keras pré-treinadas dos transformadores SWIN e é construído com base na implementação oficial do pytorch . Seu código está disponível no github . tfswin é usado para treinar as imagens da raça do cão.
from tfswin import SwinTransformerBase224, preprocess_input def build_model1(swintransformer): tf.keras.backend.clear_session() inputs = Input(shape=(resize_height, resize_width, 3)) outputs = Lambda(preprocess_input)(inputs) outputs = swintransformer(outputs) outputs = Dense(num_classes, activation='softmax')(outputs) swin_model = Model(inputs=inputs, outputs=outputs) return swin_model #build the model swintransformer = SwinTransformerBase224(include_top=False,pooling='avg') swin_model1 = build_model1(swintransformer) #set the layers of the pretrained model as non-trainable for layer in swin_model1.layers[2].layers: layer.trainable = False swin_model1.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.001),loss='categorical_crossentropy',metrics=['accuracy'])
#Logloss of the test set using various ResNet variants +------------+---------------+-------------------------+----------+ | Model Name | Retrained | Top Layers Replacement | Log_Loss | +------------+---------------+-------------------------+----------+ | ResNet50 | None | ConvBlock_FC_Output | 0.96463 | | ResNet50 | None | GlobalAvgPooling_Output | 0.58147 | | ResNet50 | last 4 layers | ConvBlock_FC_Output | 2.10158 | | ResNet50 | last 4 layers | GlobalAvgPooling_Output | 0.57019 | +------------+---------------+-------------------------+----------+
Código correspondente ao modelo ResNet50 com menor perda de log
from tensorflow.keras.layers import Input,Conv2D,Dense,BatchNormalization,Flatten,Concatenate, Dropout,MaxPooling2D from tensorflow.keras.models import Model from tensorflow.keras.applications.resnet50 import ResNet50, preprocess_input def build_model(): tf.keras.backend.clear_session() inputs = Input(shape=(resize_height, resize_width, 3)) #added preprocess_input method as a layer to convert input images to those expected by Resnet processed_inputs = preprocess_input(inputs) #use the pretrained ResNet model (Parameter pooling = 'avg' will take care of the Gobal Average Pooling of the ResNet model features) base_model = ResNet50(weights="imagenet", include_top=False,pooling='avg')(processed_inputs) #output layer output = Dense(units=num_classes,activation='softmax',name='Output')(base_model) resnet_model = Model(inputs=inputs, outputs=output) return resnet_model #build the model resnet_model = build_model() #set the layers of the resnet pretrained model as non-trainable except for its last 4 layers which needs to be re-trained for this data for layer in resnet_model.layers[3].layers[:-4]: layer.trainable = False #compile the model resnet_model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),loss='categorical_crossentropy',metrics=['accuracy']) print(resnet_model.summary()) history = resnet_model.fit(train_ds, epochs=50, validation_data=val_ds, callbacks=callbacks_list)
#Logloss of the standalone model variants +----------------------------+-------------+ | Model Name | Log_Loss | +----------------------------+-------------+ | EfficientNetV2M | 0.28347 | | Inception ResNet | 0.28623 | | NasNetLarge | 0.33285 | | Xception | 0.34187 | | Inception_V3 | 0.54297 | | EfficientNetV2M_GlobalAveg | 0.50423 | | InceptionV3_GlobalAveg | 0.46402 | +----------------------------+-------------+
+--------------------------------------------------------------------------+-----------+ | Model Name | Log_Loss | +--------------------------------------------------------------------------+-----------+ | Ensemble1 - EfficientNEt,InceptionResNet,NasNet,Xception) | 0.17363 | | Ensemble2 - EfficientNEt,InceptionResNet,NasNet,Xception and InceptionV3 | 0.16914 | | Ensemble3 - Ensemble2 with 50% dropout. | 0.16678 | | Ensemble4 - Ensemble of various EfficientNet Architecture | 0.16519 | +--------------------------------------------------------------------------+-----------+
Each of these models accepts varied input formats and in Keras they have their own preprocessing functions.
Resultado de Benchmarking
+----------------------------------+------------+----------------------+----------+ | Model Name | Parameters | Train time (seconds) | Log_Loss | +----------------------------------+------------+----------------------+----------+ | EfficientNet_ConvBlock_Output | 54.7M | ~260s | 0.28347 | | InceptionResNet_ConvBlock_Output | 56.1M | ~260s | 0.28623 | | NASNetLarge_ConvBlock_Output | 89.6M | ~330s | 0.33285 | | XCeption_ConvBlock_Output | 23.3M | ~240s | 0.34187 | | InceptionV3_ConvBlock_Output | 24.2M | ~225s | 0.54297 | | EfficientNet_GlobalAvg | 53.3M | ~260s | 0.50423 | | InceptionV3_GlobalAvg | 22M | ~215s | 0.46402 | | swin_base224 | 86.8M | ~550s | 0.47289 | | swin_base384 | 87M | ~600s | 0.41902 | | swin_large384 | 195M | ~1000s | 0.42207 | +----------------------------------+------------+----------------------+----------+
Os transformadores SWIN tiveram um desempenho melhor do que todas as variantes ResNet50 e o modelo InceptionV3.
A perda de log do transformador SWIN nesses dados é ligeiramente maior em comparação com os modelos InceptionResNet, EfficientNet, Xception e NasNet Large quando suas saídas são processadas posteriormente pela camada convolucional seguida por Maxpooling.
O desempenho do SWIN, no entanto, é tão bom quanto o modelo EfficientNet quando suas saídas médias são processadas diretamente pela camada de saída.
Os modelos SWIN são maiores em comparação com qualquer um dos modelos convolucionais e, portanto, afetarão a taxa de transferência e a latência do sistema.
Este estudo provou ser útil para entender a aplicação de modelos baseados em transformadores para visão computacional.
Você pode encontrar o código para os notebooks no meu Github e a GUI para este caso de uso aqui.
https://www.kaggle.com/competitions/dog-breed-identification
https://arxiv.org/pdf/2103.14030.pdf