Deep Learning e COVID-19 utilizando imagens de Raio X.

Uma aplicação prática utilizando Keras, TensorFlow e Deep Learning.

Toni Esteves
10 min readMar 23, 2020
Photo by Markus Spiske on Unsplash

ATENÇÃO: A metodologia que utilizarei nesse artigo é apenas para fins educacionais. Este não é um estudo cientifico validado rigorosamente, tampouco será publicado em uma revista. Este artigo é para leitores interessados em (1) Visão Computacional / Aprendizado Profundo e que desejam aprender através de métodos práticos e (2) são inspirados nos eventos atuais.

Recentemente uma nova variação do COVID-19 (coronavirus) foi identificado em 2019 em Wuhan, China. A maioria das pessoas se infecta com variações mais comuns do coronavírus ao longo da vida, sendo as crianças pequenas mais propensas a se infectarem com estes. Esta variação ainda não havia sido identificado anteriormente em humanos. Os coronavírus mais comuns que infectam humanos são o alpha coronavírus 229E e NL63 e beta coronavírus OC43, HKU1. Assim, os coronavírus são uma grande família de vírus que causam doenças que variam desde o resfriado comum até doenças mais graves, como a Síndrome Respiratória do Oriente Médio (MERS) e a Síndrome Respiratória Aguda Grave (SARS).

Com o número de casos acelerando em todo o mundo desenvolvido, os governos estão lentamente despertando para a escala da questão, e seria de esperar ver o mundo unido contra essa ameaça. No entanto, em nível nacional e individual, ainda estamos observando divisões e desconfiança. Relatos de ataques racistas, roubo e comportamento irresponsável são comuns. Os médicos estão pedindo ao público que leve a situação a sério e se abrigue no local, evitando todas as viagens e socializações não essenciais.

Número de casos de COVID-19 para um número selecionado de nações. (Fonte: Reuters)

As soluções baseadas em IA foram recentemente exploradas extensivamente para o uso da detecção de pneumonia em estudos, e essas abordagens também foram propostas durante esta pandemia. Modelos personalizados foram relatados para atingir taxas de sensibilidade e especificidade de aproximadamente 90%. No entanto, sua especificidade na identificação da causa da pneumonia, particularmente contra outras doenças virais (como a gripe), ainda está sendo debatida calorosamente. Sua natureza experimental inerente requer que abordagens confirmatórias também sejam usadas em conjunto, como parte de uma abordagem multidisciplinar para o diagnóstico.
Neste artigo, exploraremos a viabilidade e as dificuldades na construção de um sistema capaz de detectar várias causas de pneumonia nas radiografias do tórax, usando um processo de aprendizado de transferência relativamente fácil e um conjunto de dados restrito. Naturalmente, os métodos descritos aqui são apenas para fins educacionais. Este não é um estudo cientificamente rigoroso e não deve ser usado para fins médicos.

Como identificar o COVID-19 através de imagens de raio X.

Para direcionar o problema em questão, coletamos o próprio conjunto de dados, combinando o conjunto de dados de raios X do tórax no Kaggle com o conjunto de dados de raios X do tórax COVID-19 coletado pelo Dr. Joseph Paul Cohen, da Universidade de Montreal. Ambos os conjuntos de dados consistem em imagens anteriores anteriores do tórax de pacientes com pneumonia. Como o conjunto de dados COVID-19 é atualizado diariamente à medida que mais casos são publicados, acessamos a instância disponível em 21de março de 2020.

O principal objetivo á obter a precisão na identificação da pneumonia para o conjunto de dados apresentado, avaliando se a estrutura de rede neural adotada.

Step 1 — Preparando o Conjunto de Dados.

O conjunto de dados de imagem de raios-X COVID-19 que usaremos para este tutorial foi coletado pelo Dr. Joseph Cohen, um pós-doutorado na Universidade de Montreal.

Há uma semana, o Dr. Cohen começou a coletar imagens de raios-X de casos COVID-19 e publicá-las no seu GitHub.

Dentro do repositório, você encontrará exemplos de casos COVID-19, além de MERS, SARS e ARDS.

Para criar o conjunto de dados de imagem de raio-x COVID-19 para este tutorial, eu:

  • Analiso o arquivo metadata.csv encontrado no repositório do Dr. Cohen.
    Selecionadas todas as linhas que são positivos para COVID-19 (ou seja, ignorando os casos MERS, SARS e ARDS).
  • Utilizo as imagens que possuem vista posterior dos pulmões. (Acredito que essa é a visão usada para os meus casos “saudáveis”).
  • No total, isso me deixou com 87 imagens de raios-X de casos positivos de COVID-19 que separei em treino(38), teste(36) e validação(15).

O próximo passo foi amostrar imagens de raios-X de pacientes saudáveis.

Para fazer isso, usei o conjunto de dados de imagens de raios X do tórax do Kaggle (Pneumonia) e coletei 87 imagens de raios X de pacientes saudáveis ​. Existem vários problemas com o conjunto de dados de radiografia de tórax do Kaggle, ou seja, etiquetas ruidosas/incorretas, mas serviu como um ponto de partida suficientemente bom para esta prova de conceito do detector COVID-19.

No total meu conjunto de dados possuia 89 imagens. Após um processo de aumento de dados obtive um total de 178 imagens, divididas igualmente entre imagens de raios-X positivos para COVID-19 e imagens de raios-X de pacientes saudáveis divididos entre treino, teste e validação.

Step 2 — Construindo o Modelo

Após criarmos o nosso modelo Sequential() começamos a empilhar camadas de forma a construir a arquitetura do nosso modelo de rede convolucional.

model = Sequential()
model.add(Conv2D(16, (3, 3), activation=’relu’, padding=”same”, input_shape=(150,150, 3)))
model.add(Conv2D(16, (3, 3), padding=”same”, activation=’relu’))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(32, (3, 3), activation=’relu’, padding=”same”, input_shape=(150,150, 3)))
model.add(Conv2D(32, (3, 3), padding=”same”, activation=’relu’))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(64, (3, 3), activation=’relu’, padding=”same”))
model.add(Conv2D(64, (3, 3), padding=”same”, activation=’relu’))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(96, (3, 3), dilation_rate=(2, 2), activation=’relu’, padding=”same”))
model.add(Conv2D(96, (3, 3), padding=”valid”, activation=’relu’))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, (3, 3), dilation_rate=(2, 2), activation=’relu’, padding=”same”))
model.add(Conv2D(128, (3, 3), padding=”valid”, activation=’relu’))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())model.add(Dense(64, activation=’relu’))
model.add(Dropout(0.5))
model.add(Dense(2 , activation=’softmax’))

Se você desejar uma explicação mais detalhada sobre o que cada camada faz, você pode acompanhar esse outro post que fiz aqui, que aborda justamente a função das camadas de uma rede neural convolucional.

Step 3 — Treinando o Modelo

Acima é possível observar o treino da nossa rede ao logo das 100 épocas, acompanhado dos valores de perda e acurácia, para os conjuntos de treino e valição. No entanto observe que por conta do callback EarlyStop, alcançando uma perda satisfatória na 34º época e o treino é interrompido.

Step 4 — Validando o Modelo

Abaixo veremos como ficou a acurácia e a perda do nosso modelo do nosso modelo para os conjuntos de treino e teste.

A imagem acima apresenta o histórico da acurácia do nosso modelo ao longo das épocas. É possível observar pelo eixo y que ao longo de 100 épocas presentes no eixo x, conseguimos uma acurácia acima de 100% e uma perda mínima de menos de 10%. Vamos utilizar agora nosso modelo treinado para classifcar as imagens.

Limitações

Cabe ressaltar que não temos dados suficientes (confiáveis) para treinar um detector COVID-19, ou seja nossa acurácia de 100% muito provavelmente representa um possível sobreajuste do nosso modelo (overfitting).

Step 5— Análise de Resultados e Análise Estatística

Abaixo temos um resumo das métrica alcançadas. Obtivemos uma acurácia de 82%, o que não é nada mal.

Seria suficiente avaliarmos apenas a acurácia nesse cenário?

--------------------------------------------------------------------
Report for Model File: 2020-03-20 02-18-25/11-val_accuracy-1.00-val_loss-0.69.hdf5
--------------------------------------------------------------------
precision recall f1-score support

Covid 0.82 0.86 0.84 36
Normal 0.85 0.81 0.83 36

accuracy 0.83 72
macro avg 0.83 0.83 0.83 72
weighted avg 0.83 0.83 0.83 72

--------------------------------------------------------------------

Observe que temos ainda algumas métricas acima: Precision, Recall e F1-Score.

  • A precisão(Precision) pode ser usada em uma situação em que os Falsos Positivos são considerados mais prejudiciais que os Falsos Negativos. Por exemplo, ao classificar uma ação como um bom investimento, é necessário que o modelo esteja correto, mesmo que acabe classificando bons investimentos como maus investimentos (situação de Falso Negativo) no processo. Ou seja, o modelo deve ser preciso em suas classificações, pois a partir do momento que consideramos um investimento bom quando na verdade ele não é, uma grande perda de dinheiro pode acontecer.
  • O recall(Revocação) pode ser usado em uma situação em que os Falsos Negativos são considerados mais prejudiciais que os Falsos Positivos. Por exemplo, o modelo deve de qualquer maneira encontrar todos os pacientes doentes, mesmo que classifique alguns saudáveis como doentes (situação de Falso Positivo) no processo. Ou seja, o modelo deve ter alto recall, pois classificar pacientes doentes como saudáveis pode ser uma tragédia.

Assim, para o nosso cenário o Recall consegue ter uma importância maior que a acurácia. De fato não queremos mandar para casa algum paciente que esteja com suspeita de infecção pelo COVID-19, alegando que o mesmo não tem nada. Assim, conseguimos um Recall de 86.11% para as classes positivas, àquelas que possume o COVID-19

Pior que insegurança é a falsa sensação de segurança.

Além disso, consideramos também a análise da área sob a curva (AUC) que representa o grau ou medida de separabilidade, informando o quanto o modelo é capaz de distinguir entre as duas classes estudadas. No modelo replicado encontramos uma área sob curva de 83,33%.

Curvas ROC tipicamente apresentam taxas positivas verdadeiras no eixo Y e taxa de falsos positivos no eixo X. Isso significa que o canto superior esquerdo do gráfico é o ponto ideal : uma taxa positiva falsa de zero e uma taxa positiva verdadeira de um. Para fins práticos, isso não é muito realista, mas significa que uma área maior sob a curva (AUC) geralmente é melhor. A inclinação das curvas ROC também é importante, pois é ideal para maximizar a taxa positiva real e minimizar a taxa de falsos positivos.

Para efetuar a análise estatística do modelo replicado faremos uso da área sob curva. A ideia principal que usaremos é uma técnica proposta por [Efron 1979], chamada boostrap, que através de replicação utiliza a amostra como substituto da população e simula a amostragem através de um processo de reamostragem com reposição, fornecendo uma estimativa precisa da variação na distribuição amostral.

Como não podemos prever todos os casos existentes dos COVID-19 é preciso tirar proveito da análise estatística, onde através de um espaço amostral (amostra) tentaremos inferir todos os casos possíveis (população). É preciso salientar também que nosso conjunto de dados é muito pequeno (um total de 178 casos entre infectados e saudáveis), o que torna ainda mais necessário esse tipo de inferência estatística

Assim partindo do princípio que obtivemos uma AUC de 83,11%, vamos calcular a distribuicção amostral em relação a essa métrica, contornando a falta de informações suficientes sobre a população a partir dessa técnica de reamostragem.

Para a realização desse procedimento construímos 10.000 réplicas de boostrap, a fim de obter limites para intervalos de confiança de 95% bem como o erro padrão.

Standart Deviation: 0.044
Confidence interval for the score: [0.744 - 0.916]

A partir desses dados podemos afirmar com 95% de confiança que a nossa distribuição amostral da área sob a curva ficaria entre 0,74 e 0,91, com um erro padrão de 0,04. Queremos dizer com isso que em 95% dos casos o nosso modelo treinado alcançaria essa mesma precisão de precisão de classificação com uma variação entre 86,4% até 91,7%.

Step 6 — Resultados

O modelo conseguiu alcanc ̧ar resultados expressivos para uma ferramenta de diagnóstico, porém não tão eficiente para uma aplicação do mundo real. Mátricas como AUC e a acurácia obtiveram de certo modo um bom desempenho contudo, revelaram-se indicadores com precisão abaixo do esperado para o problema que se propõem resolver.

86% ainda é uma porcentagem baixa para determinar o grau de contaminação de uma pessoa, principalmente lidando com uma pandemia de escala global).

Nota: Nosso conjunto de dados não possui tanto dados assim o que pode significar que nosso modelo pode estar sobreajustado (overfitting). No entanto como já mencionei anteriormente, este estudo é apenas para fins de estudos práticos.

Todo esse código está disponível em um notebook no Google Colab que você pode pegar aqui e no meu Github.

Finalmente, espero que esse material tenha sido útil e faça sentido pra você, principalmente aos iniciantes. De forma elementar apresentamos conceitos relacionados a detecção do COVID-19 através de modelos de redes convolucionais utilizando Keras. Além disso nas referências do artigo é possível encontrar um material muito útil utilizado para elaboração desse artigo que pode te ajudar a ampliar seus conhecimentos na área.

Lembrando que qualquer feedback , seja positivo ou negativo é só entrar em contato através do meu twitter ou linkedin ou os comentários aqui em baixo :).

Referências

--

--

Toni Esteves

I’m a Computer Scientist and Quantitative researcher. This is my notepad for applied ML / DS / Deep Learning topics. Follow me on Twitter for more!