Primeira vez aqui? Seja bem vindo e cheque o FAQ!
x

Explorando o paper "Data Valuation for Medical Imaging".

0 votos
20 visitas
perguntada Nov 1 em Aprendizagem de Máquinas por VITOR B BORGES (1 ponto)  
editado Nov 6 por VITOR B BORGES

Trabalho Final de Métodos Númericos e Modelos Computacionais em Economia, revisão de literatura do artigo "Data Valuation for Medical Imaging" de Siyi Tang, Amirata Ghorbani, Rikiya Yamashita, Sameer Rehman, Jared A. Dunnmon, James Zou & Daniel L. Rubin.

Compartilhe

1 Resposta

0 votos
respondida Nov 6 por VITOR B BORGES (1 ponto)  

\( \large \textbf{Introdução -} \)

O artigo em questão explora um método de quantificar a qualidade de cada ponto de dado da base de treino de uma rede neural convolucional (RNC). A rede neural treinada no artigo utiliza imagens de raio-X do pulmão para diagnóstico de pneumonia.

Minha motivação para escolher este artigo como base do experimento prático foi a possibilidade de obtenção de imagens de exame Eco Doppler, para disgnóstico de Trombose Venosa. Isto não se concretizou devido à considerações relacionadas à divulgação dos diagnósticos, e a privacidade dos pacientes e do médico envolvidos.

Como alternativa, foram utilizadas imagens de uma seção do gráfico de Candlesticks, de diferetes escalas temporais, para ativos do S&P500. O objetivo da rede é classificar essas imagens de acordo com a variação dos preços 5 períodos após o padrão observado, as classes são 'compra' e 'venda'.

Um exemplo de imagem da base é a seguinte:

A imagem será apresentada aqui.

A imagem acima corresponde a variação de preço por ação da 'Apple' entre as datas de 2016-03-31 à 2017-05-31, cada candle corresponde á variação do preço em um dos meses do período.

Uma das principais características da base de dados de Raio-X, utilizada no artigo, é a mal-classificação dos pontos de dado de acordo com o diagnóstico real da imagem. Segundo os pesquisadores isto pode comprometer acurácia do modelo, e em sequência é proposto um método de ordenação dos dados de treino da rede, de acordo com a contribuição individual daquele dado para a acurácia conjunta.

O método de avaliação utilizado é o conceito do \( \textbf{valor de Shapley} \) da Teoria dos Jogos.

\(\)

\( \large \textbf{Teoria dos Jogos -} \)

O Valor de Shapley é contextualizado em um jogo cooperativo com \( n \) agentes em uma coalizão. A função \( v: S \rightarrow \mathbb{R} \), atribui à coalizão \( S \) um valor que corresponde à soma dos payoffs esperados que os membros da coalizão podem obter.

A função \( \varphi_{i}(v) \) retorna uma proporção 'justa' de distribuir o payoff da coalizão de acordo com a contribuição individual de cada agente. Esta função é definida da seguinte forma:

\[ \varphi_{i}(v) = \sum_{S \subseteq N / \{i\}} \frac{|S|!(n - |S| - 1)!}{n!} (v(S \cup \{ i \}) - v(S)) \]

Uma maneira de interpretar o que está sendo explicitado nesta fórmula é a seguinte:

\[ \scriptsize \varphi_{i}(v) = \frac{1}{número \space de \space agentes} \sum_{coalizões \space que \space excluem \space i} \frac{contribuição \space marginal \space de \space i \space para \space a \space coalizão}{número \space de \space coalizões \space que \space excluem \space i \space com \space esse \space tamanho} \]

\(\)

\( \large \textbf{Exercício Empírico -} \)

Os experimentos foram realizados na linguagem de programação Python 3. Os modelos de rede neural treinados foram importados da biblioteca keras do tensorflow e a os valores de shapley foram estimados com a biblioteca shap.

A arquitetura de todos os modelos treinados é a mesma, suas camadas estarão explicitadas no código à seguir:

########## RNC
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.preprocessing.image import ImageDataGenerator
import tensorflow as tf 

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=(300, 300, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), padding = 'same'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Conv2D(128, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss = 'binary_crossentropy',
              optimizer = 'Adamax',
              metrics = ['accuracy',tf.keras.metrics.Precision(), tf.keras.metrics.Recall()])
batch_size = 1
train_datagen = ImageDataGenerator(rescale = 1./255, 
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True)
# Testing Augmentation - Only Rescaling
test_datagen = ImageDataGenerator(rescale = 1./255)
# Generates batches of Augmented Image data
train_generator = train_datagen.flow_from_directory('Train/', target_size = (300, 300), 
                                                    batch_size = batch_size,
                                                    class_mode = 'binary') 
# Generator for validation data
validation_generator = test_datagen.flow_from_directory('Test/', 
                                                        target_size = (300, 300),
                                                        batch_size = batch_size,
                                                        class_mode = 'binary')
# Fit the model on Training data
model.fit_generator(train_generator,
                    epochs = 5,
                    validation_data = validation_generator,
                    verbose = 1)
# Evaluating model performance on Testing data
loss, accuracy, precision, recall = model.evaluate(validation_generator)
print("\nModel's Evaluation Metrics: ")
print("---------------------------")
print("Accuracy: {} \nLoss: {} \nPrecision: {} \nRecall: {}".format(accuracy, loss, precision, recall))

A base de treino do modelo principal contém 700 imagens, e a base de teste 300. As bases foram reduzidas devido á complexidade computacional de estimação do valor de shapley, que como explicitado na fórmula é de algumas ordens acima da complexidade fatorial. O programa rodou por várias horas.

O código que calcula o o valor de shaley para cada uma das imagens de treino é o seguinte:

import os
import numpy as np
import pandas as pd
import cv2
import shap
import random
import time
from IPython.display import clear_output

def create_train_dataset():

img_width = 300
img_height = 300

img_data_array = []
class_name = []
file_name = []

for class_ in os.listdir('Train/'):

    for file in os.listdir(os.path.join('Train/', class_)):

        image_path = os.path.join('Train/', class_,  file)
        image = cv2.imread( image_path, cv2.COLOR_BGR2RGB)
        image = cv2.resize(image, (img_height, img_width),interpolation = cv2.INTER_AREA)
        image = np.array(image)
        image = image.astype('float32')
        image /= 255 
        img_data_array.append(image)
        class_name.append(class_)
        file_name.append(file)


return file_name, img_data_array, class_name

def create_test_dataset():

img_width = 300
img_height = 300

img_data_array = []
class_name = []
file_name = []

for class_ in os.listdir('Test/'):

    for file in os.listdir(os.path.join('Test/', class_)):

        image_path = os.path.join('Test/', class_,  file)
        image = cv2.imread( image_path, cv2.COLOR_BGR2RGB)
        image = cv2.resize(image, (img_height, img_width),interpolation = cv2.INTER_AREA)
        image = np.array(image)
        image = image.astype('float32')
        image /= 255 
        img_data_array.append(image)
        class_name.append(class_)
        file_name.append(file)


return file_name, img_data_array, class_name

ifile_name, iimg_data, iclass_name = create_train_dataset()
tfile_name, timg_data, tclass_name = create_test_dataset()

icontent = dict(zip(ifile_name,iimg_data))
tcontent = dict(zip(tfile_name,timg_data))
iclasses = dict(zip(ifile_name,iclass_name))
tclasses = dict(zip(tfile_name,tclass_name))

iimg_data = np.array(iimg_data)
timg_data = np.array(timg_data)

start_time = time.time()

explainer = shap.DeepExplainer(loaded_model, np.array(timg_data)[0:64])

shapley_values = open('shapley_values.csv', 'a')

for i in range(len(pd.read_csv('shapley_values.csv')['file_name']),700):

    clear_output(wait = True)

    img = iimg_data[i:i+1]
    shap_values = explainer.shap_values(img)

    shapley_values.write(f'{ifile_name[i]},{sum(sum(sum(shap_values[0][0])))},{iclass_name[i]}\n')

    print(f'{i/700:.3f}%')

print("--- %s seconds ---" % (time.time() - start_time))

Após estimados os valores de shapley, as imagens foram classificadas e estocadas de maneira ordenada da melhor até a pior contribuição para eficácia. O experimento vai removendo iterativamente os x% melhores dados, e treinando novamente a rede para mensurar o efeitos disso nas medidas de: Acurácia, Precisão, Recall e Função Perda.

Os resultados encontrados foram os seguintes:

A imagem será apresentada aqui.

Uma análise visual dos gráficos sugere que o efeito da remoção dos melhores dados causou uma redução significante no recall do modelo, esta relação de dependência será inferida com mais delicadeza na seção de Resultados Econométricos.

Iremos repetir o experimento, porém desta vez removendo iterativamente os piores valores e mensurar o efeito disso nas mesmas métricas.

A imagem será apresentada aqui.

Novamente uma análise mais rasa dos gráficos sugere uma relação causal entre a remoção dos dados ruins e o aumento das medidas de precisão e Recall. Desta vez a relação de aumento da Precisão é bem mais expressiva.

O artigo científico em questão consegue obter uma relação causal entre os valores e a Acurácia do modelo, atingindo no melhor dos casos uma eficiência de 70%. Isso acontece pois os dados médicos de baixo shapley, que provavelmente haviam problemas de classificação, foram removidos da base de treino e a rede conseguiu aprender apenas as características verdadeiras das imagens bem-classificadas.

Sob essa hipótese, os pesquisadores pediram para três radiologistas reclassificarem as 100 piores e as melhores de acordo com Shapley. Após realizar um teste qui-quadrado, inferiram que realmente a distribuição de imagens com erros de classificação nas 100 piores era bem maior que nas 100 melhores.

Uma característica dos dados que foram usados no exercício empírico é a não existência de erros de classificação, visto que o único requisito para a classificação correta é a verificação do preço em algum dos períodos seguintes. O experimento de requisitar para especialistas uma reclassificação dos valores extremos de Shapley foi realizado apenas com fins de reproduzir o artigo.

Os resultados foram os seguintes:

Dois colegas com experiência em análise gráfica e day-trading reclassificaram as imagens mais extremas e a seguinte acurácia foi obtida:

A imagem será apresentada aqui.

A imagem será apresentada aqui.

Uma terceira reclassificação foi realizada porém desta vez por um leigo, que nunca havia visto um gráfico no formato candles, os resultados:

A imagem será apresentada aqui.

É interessante observar que os especialistas, na média, não obteram acurácias suficientes para uma estratégia de investimentos sustentável. O leigo obteve uma acurácia melhor que um dos especialistas, e uma acurácia melhor que vários dos modelos complexos e custosos treinados. Esta conclusão levanta considerações sobre a eficiência da análise gráfica como estratégia de investimento, porém esta discussão se encontra fora do escopo deste experimento.

\(\)

\( \large \textbf{Resultados Econométricos -} \)

Nesta seção iremos inferir que a remoção dos valores extremos de Shapley realmente afetou as métricas do modelo. Iremos observar o p-valor da hipótese de existência de correlação na regressão entre o x% de dados removidos e o valor da métrica, O R-quadrado desta regressão e o coeficiente de correlação de Pearson.

A imagem será apresentada aqui.

Note que a Precisão da regressão sobre quando removemos os dados de baixa qualidade, obteve não só um p-valor de 0 como um coeficiente de Pearon e R-quadrado com módulo bastante alto. O Recall da regressão de quando removemos os melhores dados também apresentou resultados muito bons.

As demais regressões podem até ter indicado existência de correlação entre os efeitos, porém seu R-quadrado e módulo da correlação não se mostraram tão expressivos. Por isso é mais seguro assumir que os valores encontrados são pura aleatoriedade no sorteio das amostras, e que os valores de Shapley não as influenciaram.

\(\)

\( \large \textbf{Agradecimentos -} \)

Gostaria de agradecer primeiramente aos meus colegas que se fizeram dispostos à avaliar imagens de ‘candles’ para me ajudar neste trabalho, também ao meu pai que fez um esforço à mais para primeiro entender o que eram aqueles retângulos na tela, e depois classficá-los. (kkkkk)

Também aos colegas de turma que comentaram nos exercícios que foram resolvidos ao longo do semestre, e sempre estiveram presentes no grupo de Whatsapp.

E por último ao professor Cajueiro que me permitiu participar deste curso mesmo estando ainda na graduação, e sempre disponibilizou os melhores conteúdos e exercícios que auxiliaram no nosso aprendizado.

...