Detecção de anomalias em imagens

Classifique e individualize anomalias com convolutional

Marco Cerliani em Rumo à Ciência de Dados Seguir Jul 11 · 5 min ler Foto de mahdis mousavi em Unsplash

Em Aprendizado de Máquina é normal lidar com tarefas de Detecção de Anomalias. A Ciência de Dados freqüentemente está envolvida em problemas onde eles têm que mostrar, explicar e prever anomalias.

Também fiz um post sobre Detecção de Anomalias com Séries Temporais , onde estudei um comportamento interno do sistema e forneci previsões de anomalias no futuro.

Neste post eu tento resolver um desafio diferente. Eu mudo o domínio de interesse: trocando de Séries Temporais por Imagens. Dada uma imagem, queremos ter uma dupla finalidade: prever a presença de anomalias e individualizá-las , dando uma representação colorida dos resultados.

O DATASET

Eu tenho os dados da internet: O conjunto de dados de crack contém imagens (formato de url) de rachaduras na parede. 1428 imagens são fornecidas: metade delas mostra pedaços de parede novos e não corrompidos; a parte restante mostra rachaduras de várias dimensões e tipos.

A primeira etapa consiste em fazer um pedido get para ler as imagens, redimensioná-las e transformá-las no formato de matriz.

 images = [] para url em tqdm.tqdm (df ['content']): 
response = requests.get (url)
img = Image.open (BytesIO (response.content))
img = img.resize ((224, 224))
numpy_img = img_to_array (img)
img_batch = np.expand_dims (numpy_img, axis = 0)
images.append (img_batch.astype ('float16'))
images = np.vstack (imagens)

Como você pode ver nas amostras abaixo, em nossos dados estão presentes diferentes tipos de rachaduras na parede, alguns deles não são tão fáceis de identificar também para mim.

Exemplos de rachaduras e sem rachaduras

O MODELO

Queremos construir um modelo de aprendizado de máquina capaz de classificar imagens de parede e detectar ao mesmo tempo onde as anomalias estão localizadas. Para alcançar este duplo propósito, o método mais eficiente consiste em construir um classificador forte. Ele será capaz de ler e classificar nossas imagens de entrada como "danificadas" ou "não danificadas". Na última etapa, utilizaremos o conhecimento aprendido pelo nosso classificador para extrair informações úteis que nos ajudarão a detectar também onde estão as anomalias.

Mas vamos prosseguir com a ordem e começar a montar nossa Rede Neural…

Para este tipo de tarefa eu escolhi uma bala de prata de visão computacional, a fidelidade VGG16. Nós carregamos e refazemos o trem do VGG16. Isso é muito fácil de fazer em Keras com apenas algumas linhas de código.

 vgg_conv = vgg16.VGG16 (pesos = 'imagenet', include_top = False, input_shape = (224, 224, 3)) para camada em vgg_conv.layers [: - 8]: 
layer.trainable = False

Em detalhes, importamos a arquitetura VGG permitindo o treinamento dos dois últimos blocos convolucionais. Isso permitirá que nosso modelo se especialize em nossa tarefa de classificação. Para esse propósito, também excluímos as camadas superiores do modelo original, recolocando-as em outra estrutura.

 x = vgg_conv.output 
x = GlobalAveragePooling2D () (x)
x = denso (2, ativação = "softmax") (x)
model = Model (vgg_conv.input, x)
model.compile (loss = "categorical_crossentropy", otimizador = optimizers.SGD (lr = 0,0001, momentum = 0,9), métricas = ["precisão"])

No estágio de classificação, a camada GlobalAveragePooling reduz o tamanho da camada anterior, tomando a média de cada mapa de recursos. Essa escolha, mais o uso omitido da camada densa intermediária, permite evitar overfitting .

O treinamento é simples e fácil se você tiver à disposição uma GPU. O COLAB nos deu as armas que precisávamos para acelerar esse processo. Também usamos um gerador de dados simples fornecido por Keras para aumento de imagem.

No final, conseguimos atingir uma precisão geral de 0,90, nada mal!

Da documentação do sklearn

LOCALIZE ANOMALIAS

Agora, com o nosso modelo treinado, brincamos com para extrair toda a informação útil que nos permitirá mostrar rachaduras nas nossas imagens de parede. Tentamos tornar este processo fácil e agradável de ver no final com a representação do mapa de calor .

As informações úteis que precisamos estão localizadas no topo. Particularmente nós acessamos:

  • Camadas convolucionais : superior nós vamos em nossa estrutura de VGG e características mais importantes que a rede criou. Selecionamos a última camada convolucional (' block5_conv3 ') e cortamos aqui nosso modelo de classificação. Recriamos um modelo intermediário que, dada a imagem original como entrada, exibe o mapa de ativação relacionado. Pensando em dimensionalidade, nosso modelo intermediário aumenta os canais (novos recursos) e reduz as dimensões (altura e largura) de nossa imagem inicial.
  • Camada Densa Final : para cada classe de interesse, precisamos desses pesos, que são responsáveis por fornecer os resultados finais da classificação.

Com esses objetos comprimidos em nossas mãos, temos todo o conhecimento para localizar as rachaduras. Queremos "pintá-los" em uma imagem original para tornar os resultados fáceis de entender e agradáveis de ver. 'Descompactar' estas informações é fácil em python: nós só temos que fazer upsampling bilinear para redimensionar cada mapa de ativação e computar um produto escalar.

Esta mágica é acessível executando uma função simples:

 def plot_activation(img):  pred = model.predict(img[np.newaxis,:,:,:]) 
pred_class = np.argmax(pred)

weights = model.layers[-1].get_weights()[0]
class_weights = weights[:, pred_class]

intermediate = Model(model.input,
model.get_layer("block5_conv3").output)
conv_output = intermediate.predict(img[np.newaxis,:,:,:])
conv_output = np.squeeze(conv_output)

h = int(img.shape[0]/conv_output.shape[0])
w = int(img.shape[1]/conv_output.shape[1])

act_maps = sp.ndimage.zoom(conv_output, (h, w, 1), order=1)
out = np.dot(act_maps.reshape((img.shape[0]*img.shape[1],512)),
class_weights).reshape(img.shape[0],img.shape[1])

plt.imshow(img.astype('float32').reshape(img.shape[0],
img.shape[1],3))
plt.imshow(out, cmap='jet', alpha=0.35)
plt.title('Crack' if pred_class == 1 else 'No Crack')

Eu exibo os resultados na imagem abaixo, onde eu plotei os mapas de calor de crack em imagens de teste classificadas como crack. Podemos ver que o mapa de calor é capaz de generalizar bem e apontar pedaços de parede contendo rachaduras.

Mostrar anomalias nas imagens do Crack

RESUMO

Neste post, produzimos uma solução de aprendizado de máquina para identificação e localização de anomalias. Todas estas funcionalidades são acessíveis implementando um modelo de classificação único. Durante o treinamento, nossa Rede Neural adquire todas as informações relevantes que lhe permitem operar a classificação. Após essa fase, montamos as peças finais que nos informaram onde está o crack na imagem, sem trabalho adicional!