Pyradiomics: Erro de memória durante a extração de recurso (para muitas imagens ou máscara grande)

Criado em 27 set. 2017  ·  16Comentários  ·  Fonte: AIM-Harvard/pyradiomics

Quando tentei extrair recursos em muitas imagens em um loop usando PyRadiomics, encontrei um erro de memória. Consegui reproduzir dois tipos de erros de memória com um script simples e apenas uma imagem e máscara, chamando repetidamente a extração de recurso na mesma imagem.

Eu coloquei o código para reproduzir o erro aqui na essência
Você pode encontrar os dados da imagem de teste para executar o script (bem como o próprio arquivo de script novamente) aqui

Existem dois casos de erro diferentes:

  1. Tentando extrair recursos de uma máscara bastante grande (-> "MemoryError" em numpy)
  2. Tentando extrair recursos de pequenas máscaras para muitas imagens em um loop (-> "Falha ao alocar memória para imagem" em SimpleITK)

Você pode reproduzi-los (des) comentando sobre as linhas que definem qual máscara usar (veja também o principal comentário explicativo no script).

Detalhes do erro do caso 1:

Traceback (most recent call last):
  File "d:/Test/PyRadiomicsMemoryExceptionTest.py", line 26, in <module>
    featureVector = extractor.execute(testImage, testMask, label = 1)
  File "C:\Python36\lib\site-packages\pyradiomics-1.2.0.post25.dev0+g13274ff-py3.6-win32.egg\radiomics\featureextractor.py", line 354, in execute
    shapeClass = self.featureClasses['shape'](croppedImage, croppedMask, **self.settings)
  File "C:\Python36\lib\site-packages\pyradiomics-1.2.0.post25.dev0+g13274ff-py3.6-win32.egg\radiomics\shape.py", line 62, in __init__
    physicalCoordinates -= numpy.mean(physicalCoordinates, axis=0)  # Centered at 0
  File "C:\Python36\lib\site-packages\numpy\core\fromnumeric.py", line 2909, in mean
    out=out, **kwargs)
  File "C:\Python36\lib\site-packages\numpy\core\_methods.py", line 54, in _mean
    arr = asanyarray(a)
  File "C:\Python36\lib\site-packages\numpy\core\numeric.py", line 583, in asanyarray
    return array(a, dtype, copy=False, order=order, subok=True)
MemoryError

Detalhes do erro do caso 2:

Traceback (most recent call last):
  File "d:/Test/PyRadiomicsMemoryExceptionTest.py", line 27, in <module>
    featureVector = extractor.execute(testImage, testMask, label = 1)
  File "C:\Python36\lib\site-packages\pyradiomics-1.2.0.post25.dev0+g13274ff-py3.6-win32.egg\radiomics\featureextractor.py", line 346, in execute
    featureVector.update(self.getProvenance(imageFilepath, maskFilepath, mask))
  File "C:\Python36\lib\site-packages\pyradiomics-1.2.0.post25.dev0+g13274ff-py3.6-win32.egg\radiomics\featureextractor.py", line 440, in getProvenance
    for k, v in six.iteritems(generalinfoClass.execute()):
  File "C:\Python36\lib\site-packages\pyradiomics-1.2.0.post25.dev0+g13274ff-py3.6-win32.egg\radiomics\generalinfo.py", line 56, in execute
    generalInfo[el] = getattr(self, 'get%sValue' % el)()
  File "C:\Python36\lib\site-packages\pyradiomics-1.2.0.post25.dev0+g13274ff-py3.6-win32.egg\radiomics\generalinfo.py", line 139, in getVolumeNumValue
    ccif.Execute(labelMap)
  File "C:\Python36\lib\site-packages\SimpleITK\SimpleITK.py", line 20584, in Execute
    return _SimpleITK.ConnectedComponentImageFilter_Execute(self, *args)
RuntimeError: Exception thrown in SimpleITK ConnectedComponentImageFilter_Execute: c:\d\vs14-win32-pkg\simpleitk-build\itk-prefix\include\itk-4.11\itkImportImageContainer.hxx:199:
Failed to allocate memory for image.
bug installation

Todos 16 comentários

@JoostJM deixe-nos saber se você tem alguma idéia do que está acontecendo, ou se devemos investigar mais.

@michaelschwier , que tipo de hardware você está usando? Especificamente, quanta RAM você tinha disponível ao executar o script?
Testei seu script no meu computador (Intel Xeon E3-1241, 16 GB de RAM) e não tive problemas com sua máscara grande (executei 11 iterações, flutua na memória, no máximo precisa de cerca de 2 GB). Também estou executando o script de máscara pequena (~ 600 iterações agora, ainda requer apenas cerca de 200 MB de RAM), mas também parece estar funcionando bem.

É possível que não haja RAM suficiente disponível para executar a piradiômica. Já incorporamos aprimoramentos para reduzir o consumo de memória ao extrair recursos, como recorte na caixa delimitadora da segmentação antes da extração de recursos. No entanto, a geração de matrizes de textura, especialmente ao usar grandes máscaras, simplesmente requer muita memória. Para verificar ainda mais, executarei um perfil de memória ao longo do tempo de seu script.

Sua pequena máscara representa um caso interessante. É possível que isso falhe porque mais tarde, porque a RAM é suficiente para as primeiras iterações, mas se esgota quando o vetor de resultados fica muito grande (embora esse vetor seja relativamente pequeno em comparação com o uso geral da memória da piradiômica.

Quanto às soluções. Se já falhar no primeiro filtro de imagem de componente conectado (como é o caso em seu caso de máscara grande), não tenho certeza do que fazer. Você pode remover essa parte do código desabilitando a informação adicional (parâmetro additionalInfo definido como False ), mas acho que irá falhar em alguma outra parte do código (o que mais intensamente usa a memória funções são a geração de matrizes de textura).
Para o seu caso de máscara pequena, verifique o script em lote contido nos exemplos. Este script grava os resultados de cada caso (anexando a um arquivo), evitando assim o aumento do uso de memória ao extrair um lote grande. Em teoria, o script em lote só deve falhar devido a uma falta de memória se qualquer um dos casos for muito grande para extrair (independentemente de quantos casos foram extraídos antes).

Aqui estão os gráficos de uso de memória ao longo do tempo para os grandes (~ 20 iterações) e pequenos (~ 200 iterações). Não obtive erros de memória e interrompi o processo.

Máscara grande
large mask memory usage

Máscara Pequena
small mask memory usage

Se você ainda receber seus erros de memória, poderia fazer um gráfico semelhante?
Usei um pacote python simples chamado mprof ( pip install memory_profiler ) e, em seguida, executei seu script usando python C:\Python27\scripts\mprof run PyRadiomicsMemoryExceptionTest.py . Depois de terminar, você pode ver o gráfico executando python C:\Python27\scripts\mprof plot

@JoostJM Obrigado por sua resposta e verificação em sua máquina.
Meu sistema é Win 10 com 16 GB de RAM. Durante todos os meus testes, sempre houve pelo menos 7 GB de RAM ainda disponíveis. Infelizmente, a ferramenta mprof não funciona para mim (Windows), ela lança uma exceção de que não pode acessar o código-fonte !?

Portanto, fiz uma observação "manual" da memória, observando o consumo de memória do processo no Gerenciador de Tarefas. No caso da máscara grande, o processo trava ao usar cerca de 1,4 GB de memória. No caso da máscara pequena, o processo nunca consome mais do que 350 MB de memória.

No entanto: eu estava usando um Python de 32 bits. Portanto, no caso da máscara grande, posso entender que ela funciona muito com a memória (embora ainda deva ter algum espaço para 1,4). Para o caso de máscara pequena, não deve ser um problema: /

Agora também instalei um Python de 64 bits em paralelo e não consigo reproduzir os erros até agora (> 1200 iterações na pequena máscara). Então, para mim, essa pode ser a solução. No entanto, a queda da pequena máscara em 32 bits ainda me intriga ...

Devemos pensar explicitamente em não suportar python de 32 bits. Não oferecemos suporte explicitamente a plataformas de 32 bits no Slicer porque tínhamos muitos erros relacionados à memória.

Eu sugeriria não perder tempo com esse problema depurando-o em 32 bits e adicionando uma observação ao guia do usuário de que o python de 64 bits deve ser usado.

Poderia até adicionar um aviso durante a instalação da piradiômica ao detectar python de 32 bits !?

Poderia até adicionar um aviso durante a instalação da piradiômica ao detectar python de 32 bits !?

Definitivamente, ou mesmo fracasso.

Oi,

Tenho tentado executar algum test.py para verificar se o radiomics está funcionando, mas continua dizendo que não é possível importar featureextractor do radiomics. Alguém está tendo o mesmo problema?

desde já, obrigado

Eu tenho um problema semelhante.
Estou enfrentando um erro de memória quando tento executar meu modelo. Estou enviando 6.500 imagens para treinar com 7 legendas cada.
Estou usando o Ubuntu.

@ Yukti-09, qual versão específica do PyRadiomics você está usando? quais parâmetros? Quanta RAM o seu sistema possui?

Não usando piradiômica

Oi! Estou usando piradiômica para imagem de ultrassom 2D para extração de recursos. Estou usando um banco de dados de acesso aberto de imagens de ultrassom da tireoide (disponível: tireoide http://cimalab.intec.co/applications/thyroid/). Quando estou usando piradiômica para extração de recursos da máscara, é necessário mais de 16 GB de RAM. Há alguma configuração necessária para processar a piradiômica para limitar o uso de memória? A máscara é pequena em comparação com a imagem inteira. Se a extração de recursos da máscara está consumindo muita memória, o que acontecerá se eu fizer o mesmo para a imagem inteira? Guia gentilmente.

@ReemaParekh que tipo de configuração você está usando ao realizar a extração?

Tenho uma imagem USG de 360x560 e uso a extração de recursos baseada em voxel que é aplicada em toda a imagem e todas as classes de recursos estão ativadas. Neste caso, o uso de memória atingiu 20 GB em alguns casos. Estou usando as configurações abaixo para o mesmo.
featureVector = extractor.execute (image3D, mask, label = 1, voxelBased = True)
configurações = {}
configurações ['binWidth'] = 25

configurações ['force2D'] = Verdadeiro

configurações ['force2Ddimension'] = 0
configurações ['maskedKernel'] = Verdadeiro
configurações ['initvalue'] = 5
configurações ['kernelRadius'] = 10
settings ['resampledPixelSpacing'] = None # [3,3,3] é um exemplo para definir reamostragem (voxels com tamanho 3x3x3mm)
settings ['interpolator'] = sitk.sitkBSpline
configurações ['verbose'] = Verdadeiro

Além disso, se eu escrever force2D = true, meu código não está funcionando. Caso contrário, funciona, mas requer muita memória. Tenho imagens 2D, mas não consigo usar imagens 2D diretamente no programa de piradiômica, então converti a imagem 2D em 1x360x560 para processar. image3D = sitk.JoinSeries (imagem)

O requisito de memória parece válido. Esteja ciente de que a radiômica baseada em voxel pode consumir bastante memória, especialmente ao extrair a imagem inteira e habilitar todos os recursos. A saída são mapas float64 para cada recurso, o que no seu caso significa 360x560x8 bytes por mapa de recurso. Além disso, há algum requisito de memória adicional para mapas de recursos intermediários, máscara etc.

Quanto ao force2D, o que você quer dizer com "não funciona"? O PyRadiomics deve ser capaz de lidar tanto com a entrada verdadeiramente 2D, como quando você ativa o force2D. A única coisa que posso imaginar que está dando errado em seu código é que se sua imagem tiver o tamanho local 1x360x560, isso significa que x é sua dimensão force2D, e você deve definir force2Ddimension como 2 (razão da matriz, que é ordenada como z, y , x).

Esta página foi útil?
0 / 5 - 0 avaliações