RETAIN é um modelo preditivo interpretável para aplicações de saúde. Dados os registros dos pacientes, ele pode fazer previsões e explicar como cada código médico (códigos de diagnóstico, códigos de medicamentos ou códigos de procedimento) em cada visita contribui para a previsão. A interpretação é possível devido ao uso do mecanismo de atenção neural.
Usando o RETAIN, você pode calcular quão positiva/negativamente cada código médico (diagnóstico, medicamento ou código de procedimento) em diferentes consultas contribui para a pontuação final. Nesse caso, estamos prevendo se determinado paciente será diagnosticado com Insuficiência Cardíaca (IC). Você pode perceber que os códigos altamente relacionados à IC trazem contribuições positivas. RETAIN também aprende a prestar mais atenção às informações novas do que às antigas. Você pode perceber que a Disritmia Cardíaca (DC) dá uma contribuição maior à medida que ocorre na consulta mais recente.
RETAIN implementa um algoritmo apresentado no seguinte artigo:
RETAIN: An Interpretable Predictive Model for Healthcare using Reverse Time Attention Mechanism
Edward Choi, Mohammad Taha Bahadori, Joshua A. Kulas, Andy Schuetz, Walter F. Stewart, Jimeng Sun,
NIPS 2016, pp.3504-3512
O artigo RETAIN formula o modelo como sendo capaz de fazer previsões em cada intervalo de tempo (por exemplo, tentar prever quais diagnósticos o paciente receberá em cada visita) e trata a classificação da sequência (por exemplo, dado um prontuário do paciente, ele será diagnosticado com insuficiência cardíaca em o futuro?) como um caso especial, uma vez que a classificação da sequência faz a previsão apenas no último passo de tempo.
Este código, entretanto, é implementado para realizar a tarefa de classificação de sequência. Por exemplo, você pode usar este código para prever se um determinado paciente é um paciente com insuficiência cardíaca ou não. Ou você pode prever se esse paciente será readmitido no futuro. A versão mais geral do RETAIN será lançada no futuro.
PASSO 1: Instalação
Instale python, Theano. Usamos Python 2.7, Theano 0.8. Theano pode ser facilmente instalado no Ubuntu conforme sugerido aqui
Se você planeja usar computação GPU, instale CUDA
Baixe/clone o código RETAIN
PASSO 2: Maneira rápida de testar RETAIN com MIMIC-III
Esta etapa descreve como treinar o RETAIN, com número mínimo de etapas usando MIMIC-III, para prever a mortalidade dos pacientes usando seus registros de consultas.
Primeiro, você precisará solicitar acesso ao MIMIC-III, um registro eletrônico de saúde disponível publicamente, coletado de pacientes de UTI há mais de 11 anos.
Você pode usar "process_mimic.py" para processar o conjunto de dados MIMIC-III e gerar um conjunto de dados de treinamento adequado para RETAIN. Coloque o script no mesmo local onde os arquivos CSV MIMIC-III estão localizados e execute o script. O comando de execução é python process_mimic.py ADMISSIONS.csv DIAGNOSES_ICD.csv PATIENTS.csv <output file>
.
Execute RETAIN usando os arquivos ".seqs" e ".morts" gerados por process_mimic.py. O arquivo “.seqs” contém a sequência de atendimentos de cada paciente. Cada visita consiste em vários códigos de diagnóstico. No entanto, recomendamos usar o arquivo ".3digitICD9.seqs", pois os resultados serão muito mais interpretáveis. (Ou você pode usar o software de classificação clínica de nível único para CID9 para diminuir o número de códigos para algumas centenas, o que melhorará ainda mais o desempenho) O arquivo ".morts" contém a sequência de rótulos de mortalidade para cada paciente. O comando é python retain.py <3digitICD9.seqs file> 942 <morts file> <output path> --simple_load --n_epochs 100 --keep_prob_context 0.8 --keep_prob_emb 0.5
. 942
é o número total de códigos ICD9 de 3 dígitos usados no conjunto de dados.
Para testar o modelo para interpretação, consulte a Etapa 6. Pessoalmente, descobri que a icterícia perinatal (CID9 774) tem alta correlação com a mortalidade.
O modelo atinge AUC acima de 0,8 com o comando acima, mas as interpretações não são muito claras. Você poderia ajustar os hiperparâmetros, mas duvido que as coisas melhorem drasticamente. Afinal, apenas 7.500 pacientes fizeram mais de uma consulta hospitalar, e a maioria deles faz apenas duas consultas.
PASSO 3: Como preparar seu próprio conjunto de dados
O conjunto de dados de treinamento do RETAIN precisa ser uma lista de lista de lista Python cPickled. A lista mais externa corresponde aos pacientes, a intermediária à sequência de visitas que cada paciente realizou e a mais interna aos códigos médicos (por exemplo, códigos de diagnóstico, códigos de medicamentos, códigos de procedimentos, etc.) que ocorreram em cada visita. Primeiro, os códigos médicos precisam ser convertidos para um número inteiro. Então, uma única visita pode ser vista como uma lista de números inteiros. Então um paciente pode ser visto como uma lista de visitas. Por exemplo, [5,8,15] significa que o paciente recebeu os códigos 5, 8 e 15 em uma determinada consulta. Se um paciente fez duas consultas [1,2,3] e [4,5,6,7], pode ser convertido para uma lista de lista [[1,2,3], [4,5,6,7 ]]. Vários pacientes podem ser representados como [[[1,2,3], [4,5,6,7]], [[2,4], [8,3,1], [3]]], o que significa há dois pacientes onde o primeiro paciente fez duas visitas e o segundo paciente fez três visitas. Esta lista de lista de lista precisa ser selecionada usando cPickle. Iremos nos referir a este arquivo como “arquivo de visita”.
O número total de códigos médicos exclusivos é necessário para executar o RETAIN. Por exemplo, se o conjunto de dados estiver usando 14.000 códigos de diagnóstico e 11.000 códigos de procedimento, o número total será 25.000.
O conjunto de dados do rótulo (vamos chamá-lo de "arquivo de rótulo") precisa ser uma lista Python cPickled. Cada elemento corresponde ao verdadeiro rótulo de cada paciente. Por exemplo, 1 pode ser o paciente caso e 0 pode ser o paciente controle. Se houver dois pacientes onde apenas o primeiro paciente é um caso, então deveríamos ter [1,0].
O "arquivo de visita" e o "arquivo de rótulo" precisam ter 3 conjuntos respectivamente: conjunto de treinamento, conjunto de validação e conjunto de teste. A extensão do arquivo deve ser ".train", ".valid" e ".test", respectivamente.
Por exemplo, se você quiser usar um arquivo chamado "my_visit_sequences" como o "arquivo de visita", então RETAIN tentará carregar "my_visit_sequences.train", "my_visit_sequences.valid" e "my_visit_sequences.test".
Isto também é verdade para o "arquivo de etiqueta"
Você pode usar as informações de horário das visitas como uma fonte adicional de informação. Vamos chamar isso de “arquivo de tempo”. Observe que as informações de tempo podem ser qualquer coisa: duração entre visitas consecutivas, número cumulativo de dias desde a primeira visita, etc. O "arquivo de tempo" precisa ser preparado como uma lista de lista Python cPickled. A lista mais externa corresponde aos pacientes e a mais interna às informações de horário de cada atendimento. Por exemplo, dado um "arquivo de visita" [[[1,2,3], [4,5,6,7]], [[2,4], [8,3,1], [3]]] , seu "arquivo de tempo" correspondente poderia ser semelhante a [[0, 15], [0, 45, 23]], se estivermos usando a duração entre as visitas consecutivas. (é claro que os números são falsos e defini a duração da primeira visita como zero.) Use a opção --time_file <path to time file>
para usar "arquivo de tempo" Lembre-se de que o ".train", ". válido", a regra ".test" também se aplica ao "arquivo de tempo".
Adicional: Usando suas próprias representações de código médico
RETAIN aprende internamente a representação vetorial de códigos médicos durante o treinamento. Esses vetores são inicializados com valores aleatórios, é claro.
No entanto, você também pode usar suas próprias representações de código médico, se tiver uma. (Eles podem ser treinados usando algoritmos do tipo Skip-gram. Consulte Med2Vec ou este para obter mais detalhes.) Se você quiser fornecer as representações do código médico, deve ser uma lista de listas (basicamente uma matriz) de N linhas e Colunas M onde N é o número de códigos exclusivos em seu "arquivo de visita" e M é o tamanho das representações de código. Especifique o caminho para seu arquivo de representação de código usando --embed_file <path to embedding file>
. Além disso, mesmo se você usar suas próprias representações de código médico, poderá treiná-las novamente (também conhecidas como ajustá-las) enquanto treina RETAIN. Use a opção --embed_finetune
para fazer isso. Se você não estiver fornecendo suas próprias representações de código médico, o RETAIN usará uma inicializada aleatoriamente, o que obviamente requer esse processo de ajuste fino. Como o padrão é usar o ajuste fino, você não precisa se preocupar com isso.
PASSO 4: Executando RETAIN
A entrada mínima necessária para executar o RETAIN é o "arquivo de visita", o número de códigos médicos exclusivos no "arquivo de visita", o "arquivo de rótulo" e o caminho de saída. O caminho de saída é onde os pesos aprendidos e o log serão salvos.
python retain.py <visit file> <# codes in the visit file> <label file> <output path>
Especificar a opção --verbose
imprimirá o processo de treinamento após cada 10 minilotes.
É possível especificar o tamanho do W_emb de incorporação, o tamanho da camada oculta da GRU que gera alfa e o tamanho da camada oculta da GRU que gera beta. Os respectivos comandos são --embed_size <integer>
, --alpha_hidden_dim_size <integer>
e --beta_hidden_dim_size <integer>
. Por exemplo --alpha_hidden_dim_size 128
dirá ao RETAIN para usar uma GRU com camada oculta de 128 dimensões para gerar alfa.
As desistências são aplicadas a dois locais: 1) à incorporação de entrada, 2) ao vetor de contexto c_i. As respectivas taxas de abandono podem ser ajustadas usando --keep_prob_embed {0.0, 1.0}
e --keep_prob_context {0.0, 1.0}
. Os valores de dropout afetam o desempenho, por isso é recomendável ajustá-los para seus dados.
Regularizações L2 podem ser aplicadas a W_emb, w_alpha, W_beta e w_output.
Opções adicionais podem ser especificadas, como o tamanho do lote, o número de épocas, etc. Informações detalhadas podem ser acessadas por python retain.py --help
Minha recomendação pessoal: use regularização moderada (0,0001 ~ 0,001) em todos os quatro pesos e use abandono moderado apenas no vetor de contexto. Mas isso depende inteiramente dos seus dados, portanto, você deve sempre ajustar os hiperparâmetros por conta própria.
PASSO 5: Obtendo seus resultados
RETAIN verifica a AUC do conjunto de validação após cada época e, se for maior que todos os valores anteriores, salvará o modelo atual. O arquivo de modelo é gerado por numpy.savez_compressed.
Etapa 6: testando seu modelo
Utilizando o arquivo "test_retain.py", você pode calcular as contribuições de cada código médico em cada consulta. Primeiro você precisa ter um modelo treinado que foi salvo por numpy.savez_compressed. Observe que você precisa saber a configuração com a qual treinou RETAIN (por exemplo, uso de --time_file
, uso de --use_log_time
.)
Novamente, você precisa do “arquivo de visita” e do “arquivo de etiqueta” preparados da mesma maneira. Desta vez, porém, você não precisa seguir a regra ".train", ".valid", ".test". O script de teste tentará carregar o nome do arquivo conforme fornecido.
Você também precisa das informações de mapeamento entre os códigos médicos de string reais e seus códigos inteiros. (por exemplo, "Hipertensão" é mapeado para 24) Este arquivo (vamos chamá-lo de "arquivo de mapeamento") precisa ser um dicionário Python cPickled onde as chaves são os códigos médicos da string e os valores são os números inteiros correspondentes. (por exemplo, o arquivo de mapeamento gerado por process_mimic.py é o arquivo ".types"). Este arquivo é necessário para imprimir as contribuições de cada código médico em um formato amigável.
Para opções adicionais como --time_file
ou --use_log_time
, você deve usar exatamente a mesma configuração com a qual treinou o modelo. Para informações mais detalhadas, use a opção "--help".
A entrada mínima para executar o script de teste é o "arquivo de modelo", "arquivo de visita", "arquivo de etiqueta", "arquivo de mapeamento" e "arquivo de saída". "arquivo de saída" é onde as contribuições serão armazenadas. python test_retain.py <model file> <visit file> <label file> <mapping file> <output file>