Pyradiomics: Error de memoria durante la extracción de funciones (para muchas imágenes o una máscara grande)

Creado en 27 sept. 2017  ·  16Comentarios  ·  Fuente: AIM-Harvard/pyradiomics

Cuando intenté extraer características en muchas imágenes en un bucle usando PyRadiomics, encontré un error de memoria. Pude reproducir dos tipos de errores de memoria con un script simple y solo una imagen y máscara, llamando repetidamente a la extracción de características en la misma imagen.

Puse el código para reproducir el error aquí en esencia
Puede encontrar los datos de la imagen de prueba para ejecutar el script (así como el archivo de script en sí de nuevo) aquí

Hay dos casos de error diferentes:

  1. Intentando extraer características de una máscara bastante grande (-> "MemoryError" en numpy)
  2. Intentando extraer características de pequeñas máscaras para muchas imágenes en un bucle (-> "No se pudo asignar memoria para la imagen" en SimpleITK)

Puede reproducirlos (des) comentando las líneas que definen qué máscara usar (consulte también el comentario explicativo superior en el script).

Detalles del error del 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

Detalles del error del 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 comentarios

@JoostJM háganos saber si tiene alguna idea de lo que está sucediendo o si deberíamos investigar más.

@michaelschwier , ¿qué tipo de hardware estás usando? Específicamente, ¿cuánta RAM tenía disponible al ejecutar el script?
Probé su script en mi computadora (Intel Xeon E3-1241, 16 GB de RAM) y no tuve problemas con su máscara grande (ejecuté 11 iteraciones, la memoria fluctúa, la necesidad máxima es de 2 GB). También estoy ejecutando el script de máscara pequeña (~ 600 iteraciones ahora, todavía requiere solo unos 200 MB de RAM), pero esto también parece estar funcionando bien.

Es posible que no haya suficiente RAM disponible para ejecutar pyradiomics. Ya incorporamos mejoras para reducir la huella de memoria al extraer características, como recortar en el cuadro delimitador de la segmentación antes de la extracción de características. Sin embargo, la generación de matrices de textura, especialmente cuando se utilizan máscaras grandes, simplemente requiere mucha memoria. Para verificar más, ejecutaré un perfil de memoria a lo largo del tiempo de su script.

Sin embargo, tu pequeña máscara representa un caso interesante. Es posible que esto se bloquee porque más tarde porque la RAM es suficiente para las primeras iteraciones, pero se agota cuando el vector de resultados crece demasiado (aunque este vector es relativamente pequeño en comparación con el uso general de memoria de la piradiómica.

En cuanto a soluciones. Si ya falla en el primer filtro de imagen de componente conectado (como es el caso en su estuche de máscara grande), no estoy seguro de qué hacer. Puede eliminar esa parte del código deshabilitando la información adicional (parámetro additionalInfo establecido en False ), pero creo que fallará en alguna otra parte del código (la memoria más intensiva las funciones son la generación de matrices de textura).
Para el estuche de su pequeña máscara, consulte el script por lotes que se incluye en los ejemplos. Este script escribe los resultados de cada caso (agregándolos a un archivo), evitando así una acumulación de uso de memoria al extraer un lote grande. En teoría, el script por lotes solo debería fallar debido a una falta de memoria si el caso es demasiado grande para extraerlo (independientemente de cuántos casos se extrajeron antes).

Aquí están los gráficos del uso de memoria a lo largo del tiempo para las grandes (~ 20 iteraciones) y las pequeñas (~ 200 iteraciones). No obtuve errores de memoria y detuve el proceso.

Mascarilla grande
large mask memory usage

Máscara pequeña
small mask memory usage

Si aún obtiene errores de memoria, ¿podría hacer una gráfica similar?
Usé un paquete de Python simple llamado mprof ( pip install memory_profiler ) y luego ejecuté su script usando python C:\Python27\scripts\mprof run PyRadiomicsMemoryExceptionTest.py . Una vez que esto haya terminado, puede ver el gráfico ejecutando python C:\Python27\scripts\mprof plot

@JoostJM Gracias por su respuesta y comprobar su máquina.
Mi sistema es Win 10 con 16 GB de RAM. Durante todas mis pruebas, siempre hubo al menos 7 GB de RAM disponibles. Desafortunadamente, la herramienta mprof no funciona para mí (Windows), arroja una excepción de que no puede acceder al código fuente.

Así que hice una observación de memoria "manual" mirando el consumo de memoria del proceso en el Administrador de tareas. En el caso de la máscara grande, el proceso se bloquea cuando se utilizan alrededor de 1,4 GB de memoria. Para el caso de la máscara pequeña, el proceso nunca consume más de 350 MB de memoria.

Sin embargo: estaba usando un Python de 32 bits. Entonces, en el caso de la máscara grande, puedo entender que se ejecuta en nuestra memoria (aunque todavía debería tener algo de margen en 1.4). Sin embargo, para el caso de la máscara pequeña no debería ser un problema: /

Ahora también instalé un Python de 64 bits en paralelo y no puedo reproducir los errores hasta ahora (> 1200 iteraciones en la máscara pequeña). Entonces para mí esa podría ser la solución. Sin embargo, el choque de la pequeña máscara en 32 bits todavía me desconcierta ...

Deberíamos pensar en no admitir explícitamente Python de 32 bits. No admitimos explícitamente plataformas de 32 bits en Slicer porque teníamos muchos errores relacionados con la memoria.

Sugeriría no dedicar tiempo a depurar este problema en 32 bits y agregar una nota a la guía del usuario de que se debe usar Python de 64 bits.

¿Podría incluso agregar una advertencia durante la instalación de piradiomics al detectar python de 32 bits?

¿Podría incluso agregar una advertencia durante la instalación de piradiomics al detectar python de 32 bits?

Definitivamente, o incluso fracasar.

Hola,

He estado intentando ejecutar test.py para comprobar que la radiomics está funcionando, pero sigue diciendo que no puede importar featureextractor de radiomics. ¿Alguien tiene el mismo problema?

Gracias por adelantado

Tengo un problema similar.
Me enfrento a un error de memoria cuando intento ejecutar mi modelo. Estoy enviando 6500 imágenes para entrenar con 7 leyendas cada una.
Estoy usando Ubuntu.

@ Yukti-09, ¿qué versión específica de PyRadiomics estás usando? que parámetros? ¿Cuánta RAM tiene su sistema?

No usar piradiómica

¡Hola! Estoy usando piradiómica para imágenes de ultrasonido 2D para la extracción de características. Estoy usando una base de datos de acceso abierto de imágenes de ultrasonido de tiroides (disponible: tiroides http://cimalab.intec.co/applications/thyroid/). Cuando utilizo piradiómica para la extracción de características de la máscara, se requieren más de 16 GB de RAM. ¿Se requiere alguna configuración para procesar la piradiómica para limitar el uso de memoria? La máscara es pequeña en comparación con la imagen completa. Si la extracción de características de la máscara está ocupando tanta memoria, ¿qué pasará si hago lo mismo para toda la imagen? Amablemente guía.

@ReemaParekh ¿qué tipo de configuración está utilizando al realizar la extracción?

Tengo una imagen USG de tamaño 360x560 y uso la extracción de características basada en vóxeles que se aplica a toda la imagen y todas las clases de características están activadas. En este caso, el uso de memoria alcanzó los 20 GB en algunos casos. Estoy usando la siguiente configuración para lo mismo.
featureVector = extractor.execute (image3D, máscara, etiqueta = 1, voxelBased = True)
settings = {}
configuración ['binWidth'] = 25

configuración ['force2D'] = Verdadero

configuración ['force2Ddimension'] = 0
settings ['maskedKernel'] = True
configuración ['initvalue'] = 5
configuración ['kernelRadius'] = 10
settings ['resampledPixelSpacing'] = None # [3,3,3] es un ejemplo para definir el remuestreo (vóxeles con tamaño 3x3x3mm)
configuración ['interpolador'] = sitk.sitkBSpline
settings ['verbose'] = Verdadero

Además de esto, si escribo force2D = true, entonces mi código no funciona. De lo contrario, funciona pero requiere mucha memoria. Tengo una imagen 2D, pero no puedo usar una imagen 2D directamente en el programa de piradiómica, así que he convertido la imagen 2D en 1x360x560 para procesar. image3D = sitk.JoinSeries (imagen)

El requisito de memoria suena válido. Tenga en cuenta que la radiómica basada en vóxeles puede consumir bastante memoria, especialmente cuando se extrae la imagen completa y se habilitan todas las funciones. La salida son mapas float64 para cada característica, lo que en su caso significa 360x560x8 bytes por mapa de características. Además, existe un requisito de memoria adicional para mapas de características intermedias, máscara, etc.

En cuanto a force2D, ¿a qué te refieres con "no funciona"? PyRadiomics debería poder manejar tanto entradas verdaderamente 2D, como cuando habilita force2D. Lo único que puedo imaginar que va mal en su código es que si su imagen tiene un tamaño de sitk 1x360x560, significa que x es su dimensión force2D, y debe establecer force2Ddimension en 2 (razón de la matriz, que está ordenada como z, y , X).

¿Fue útil esta página
0 / 5 - 0 calificaciones