¿Cómo corregir 'las matrices de objetos no se pueden cargar cuando allow_pickle = False' para la función imdb.load_data ()?

113

Estoy tratando de implementar el ejemplo de clasificación binaria usando el conjunto de datos IMDb en Google Colab . He implementado este modelo antes. Pero cuando intenté hacerlo nuevamente después de unos días, devolvió un error de valor: 'Las matrices de objetos no se pueden cargar cuando allow_pickle = False' para la función load_data ().

Ya intenté resolver esto, refiriéndome a una respuesta existente para un problema similar: Cómo arreglar 'Las matrices de objetos no se pueden cargar cuando allow_pickle = False' en el algoritmo sketch_rnn Pero resulta que simplemente agregar un argumento allow_pickle no es suficiente.

Mi código:

from keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

El error:

ValueError                                Traceback (most recent call last)
<ipython-input-1-2ab3902db485> in <module>()
      1 from keras.datasets import imdb
----> 2 (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

2 frames
/usr/local/lib/python3.6/dist-packages/keras/datasets/imdb.py in load_data(path, num_words, skip_top, maxlen, seed, start_char, oov_char, index_from, **kwargs)
     57                     file_hash='599dadb1135973df5b59232a0e9a887c')
     58     with np.load(path) as f:
---> 59         x_train, labels_train = f['x_train'], f['y_train']
     60         x_test, labels_test = f['x_test'], f['y_test']
     61 

/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py in __getitem__(self, key)
    260                 return format.read_array(bytes,
    261                                          allow_pickle=self.allow_pickle,
--> 262                                          pickle_kwargs=self.pickle_kwargs)
    263             else:
    264                 return self.zip.read(key)

/usr/local/lib/python3.6/dist-packages/numpy/lib/format.py in read_array(fp, allow_pickle, pickle_kwargs)
    690         # The array contained Python objects. We need to unpickle the data.
    691         if not allow_pickle:
--> 692             raise ValueError("Object arrays cannot be loaded when "
    693                              "allow_pickle=False")
    694         if pickle_kwargs is None:

ValueError: Object arrays cannot be loaded when allow_pickle=False
Kanad
fuente
1
¿Qué significa este error?
Charlie Parker
3
@CharlieParker Aparentemente, se ha agregado un parámetro en la función numpy.load (). Anteriormente lo era np.load(path), ahora es np.load(path, boolean)De forma predeterminada, el booleano (allow_pickle) es falso
Kanad
¡Gracias! ¡¿Pero eso significa que Numpy ahora me deja en vinagre cosas sin mi permiso cuando las guarda ?! ¡extraño! Miré los np.savezdocumentos, pero no había ninguna referencia al decapado, así que no tengo idea de cómo supo en primer lugar que las cosas que estaba guardando eran cosas de Pytorch y no solo numpy ... ¡extrañas! Si sabe lo que está pasando, comparta con nosotros :)
Charlie Parker
Mi creencia después de encontrarme con el mismo problema es que depende totalmente de lo que esté guardando en un .npz. Si está guardando tipos integrados, entonces no decapado. Sin embargo, si escribe un objeto, python / numpy lo encurtirá (es decir, lo serializará). Esto, imagino, abre un riesgo de seguridad, por lo que las versiones posteriores de numpy dejaron de permitir que sea predeterminado ... aunque solo es una corazonada.
Robert Lugg

Respuestas:

123

Aquí hay un truco para forzar imdb.load_dataa permitir el encurtido, en su cuaderno, reemplazando esta línea:

(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

por esto:

import numpy as np
# save np.load
np_load_old = np.load

# modify the default parameters of np.load
np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)

# call load_data with allow_pickle implicitly set to true
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)

# restore np.load for future normal usage
np.load = np_load_old
cheez
fuente
Sugiero agregar "import numpy as np" al principio. Numpy puede importarse con un nombre diferente, o no importarse en absoluto ...
Kristóf
Me ayuda mucho
staticor
7
Obteniendo errorTypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
Hayat
1
El problema de los valores múltiples para el argumento de palabras clave se ha abordado en stackoverflow.com/a/58586450/5214998
Sajad Norouzi
91

Este problema todavía está pendiente en keras git. Espero que se resuelva lo antes posible. Hasta entonces, intente degradar su versión numpy a 1.16.2. Parece solucionar el problema.

!pip install numpy==1.16.1
import numpy as np

Esta versión de numpy tiene el valor predeterminado allow_picklecomo True.

Tirth Patel
fuente
4
Usaría la solución de MappaGnosis en lugar de degradar la versión numpy: para mí, jugar con la versión dance es un último recurso.
Eric
2
1.16.4 también tiene el problema
kensai
Gracias @kensai. ¿Alguien sabe si esto se resolvió en numpy 1.17?
nsheff
En numpy 1.18 todavía este problema está presente. Tuve que cambiar a numpy 1.16.1 y se resolvió ahora. gracias.
BC Smith
55

Siguiendo este problema en GitHub, la solución oficial es editar el archivo imdb.py. Esta solución funcionó bien para mí sin la necesidad de degradar numpy. Busque el archivo imdb.py en tensorflow/python/keras/datasets/imdb.py(la ruta completa para mí fue: C:\Anaconda\Lib\site-packages\tensorflow\python\keras\datasets\imdb.py- otras instalaciones serán diferentes) y cambie la línea 85 según la diferencia:

-  with np.load(path) as f:
+  with np.load(path, allow_pickle=True) as f:

El motivo del cambio es la seguridad para evitar el equivalente en Python de una inyección SQL en un archivo decapado. El cambio anterior SOLO afectará a los datos de imdb y, por lo tanto, conservará la seguridad en otro lugar (al no degradar numpy).

MappaGnosis
fuente
1
Como dije, estoy usando Colab, ¿cómo puedo hacer cambios en el archivo imdb.py?
Kanad
Este no es un problema de Colab ya que IMDB se descarga localmente la primera vez que lo hace referencia. Entonces, habrá una copia local en algún lugar de su computadora (pruebe las rutas sugeridas arriba - o, si configura un directorio para Colab, pruebe allí primero) y simplemente abra el archivo imdb.py en cualquier IDE o incluso un editor de texto para realice el cambio (utilicé Notepad ++ para editar el archivo imdb.py que se descargó cuando trabajaba en Jupyter, por lo que es un entorno muy similar a Colab).
MappaGnosis
la solución que me funciona es> np.load (data_path, encoding = 'latin1', allow_pickle = True)
Jorge Santos Neill
Esta es la solución que uso, ya que jugar con las versiones (especialmente de numpy), como en la respuesta aceptada, es algo que trato de evitar. Esto también es más pitónico, ya que explícitamente solo soluciona el problema. (Tenga en cuenta también que las versiones más recientes de Keras, en github, incorporan esta solución)
eric
35

Acabo de usar allow_pickle = True como argumento para np.load () y funcionó para mí.

Madhuparna Bhowmik
fuente
Estoy observando que permitir pickle cambia la matriz. La matriz .npy antes de guardar y después de cargar emite una excepción al intentar afirmar la igualdad usando np.array_equal
yasht
18

En mi caso trabajé con:

np.load(path, allow_pickle=True)
travs15
fuente
12

Creo que la respuesta de cheez ( https://stackoverflow.com/users/122933/cheez ) es la más fácil y efectiva. Lo explicaría un poco más para que no modificara una función numpy durante todo el período de sesión.

Mi sugerencia está a continuación. Lo estoy usando para descargar el conjunto de datos de reuters de keras, que muestra el mismo tipo de error:

old = np.load
np.load = lambda *a,**k: old(*a,**k,allow_pickle=True)

from keras.datasets import reuters
(train_data, train_labels), (test_data, test_labels) = reuters.load_data(num_words=10000)

np.load = old
del(old)
Gustavo Mirapalheta
fuente
¿Puede explicar más sobre lo que está sucediendo aquí?
Kanad
1
No podía cargar los conjuntos de datos de Keras. Busqué en Internet y encontré una solución que decía que debería editar el archivo imdb.py, otros señalaron cambios en la instalación de numpy (como aquí) o cambiar Tensorflow a una versión de desarrollo. Me encontré con la solución cheez. En mi humilde opinión, ese fue el más fácil y efectivo.
Gustavo Mirapalheta
1
@Kanad - lambda es una función anónima. Gustavo creó un aumento de función para np.load, usó la versión aumentada y luego volvió a establecer el valor predeterminado.
EngrStudent
9

Puedes intentar cambiar el valor de la bandera

np.load(training_image_names_array,allow_pickle=True)
Brayan Armando Yaquian Gonzale
fuente
Excelente. Esta funcionando. Esta debería ser la respuesta aceptada.
Biranchi
4

ninguna de las soluciones enumeradas anteriormente funcionó para mí: ejecuto anaconda con python 3.7.3. Lo que funcionó para mí fue

  • ejecutar "conda install numpy == 1.16.1" desde Anaconda powershell

  • cerrar y volver a abrir el cuaderno

Farid Khafizov
fuente
Gracias, eso es lo que busqué. Por cierto, parece que 1.16.2 es la versión más reciente donde allow_pickle=Trueestá el valor predeterminado.
Matěj Račinský
3

en el cuaderno jupyter usando

np_load_old = np.load

# modify the default parameters of np.load
np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)

funcionó bien, pero el problema aparece cuando usa este método en spyder (tiene que reiniciar el kernel cada vez o obtendrá un error como:

TypeError: () obtuvo varios valores para el argumento de palabra clave 'allow_pickle'

Resolví este problema usando la solución aquí :

Yasser Albarbay
fuente
3

Aterricé aquí, probé tus caminos y no pude entenderlo.

De hecho, estaba trabajando en un código predeterminado donde

pickle.load(path)

se usó, así que lo reemplacé con

np.load(path, allow_pickle=True)
Shristi Gupta
fuente
2

Sí, la instalación de una versión anterior de numpy resolvió el problema.

Para aquellos que usan PyCharm IDE:

en mi IDE (Pycharm), Archivo-> Configuración-> Intérprete del proyecto: encontré que mi número es 1.16.3, así que vuelvo a 1.16.1. Haga clic en + y escriba numpy en la búsqueda, marque "especificar versión": 1.16.1 y elija -> instalar paquete.

Wissam
fuente
2

encuentre la ruta a imdb.py y luego simplemente agregue la bandera a np.load (ruta, ... bandera ...)

    def load_data(.......):
    .......................................
    .......................................
    - with np.load(path) as f:
    + with np.load(path,allow_pickle=True) as f:
Leonhard Rathnak
fuente
1

Es trabajo para mi

        np_load_old = np.load
        np.load = lambda *a: np_load_old(*a, allow_pickle=True)
        (x_train, y_train), (x_test, y_test) = reuters.load_data(num_words=None, test_split=0.2)
        np.load = np_load_old
ReimuChan
fuente
4
Y algo de contexto que explique por qué funciona su solución. (De la revisión).
ZF007
1

Lo que encontré es que TensorFlow 2.0 (estoy usando 2.0.0-alpha0) no es compatible con la última versión de Numpy, es decir, v1.17.0 (y posiblemente v1.16.5 +). Tan pronto como se importa TF2, arroja una gran lista de FutureWarning, que se parece a esto:

FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_qint8 = np.dtype([("qint8", np.int8, 1)])
/anaconda3/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:541: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_qint8 = np.dtype([("qint8", np.int8, 1)])
/anaconda3/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:542: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_quint8 = np.dtype([("quint8", np.uint8, 1)])
/anaconda3/lib/python3.6/site-packages/tensorboard/compat/tensorflow_stub/dtypes.py:543: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.

Esto también resultó en el error allow_pickle cuando se intentó cargar el conjunto de datos imdb desde keras

Intenté usar la siguiente solución que funcionó bien, pero tuve que hacerlo en cada proyecto en el que estaba importando TF2 o tf.keras.

np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)

La solución más fácil que encontré fue instalar numpy 1.16.1 globalmente o usar versiones compatibles de tensorflow y numpy en un entorno virtual.

Mi objetivo con esta respuesta es señalar que no es solo un problema con imdb.load_data, sino un problema mayor debido a la incompatibilidad de las versiones TF2 y Numpy y puede resultar en muchos otros errores o problemas ocultos.

sidk
fuente
0

Tensorflow tiene una solución en la versión tf-nightly.

!pip install tf-nightly

La versión actual es '2.0.0-dev20190511'.

Joocheol Kim
fuente
0

La respuesta de @cheez en algún momento no funciona y llama de forma recursiva a la función una y otra vez. Para resolver este problema, debe copiar la función en profundidad. Puede hacer esto usando la función partial, por lo que el código final es:

import numpy as np
from functools import partial

# save np.load
np_load_old = partial(np.load)

# modify the default parameters of np.load
np.load = lambda *a,**k: np_load_old(*a, allow_pickle=True, **k)

# call load_data with allow_pickle implicitly set to true
(train_data, train_labels), (test_data, test_labels) = 
imdb.load_data(num_words=10000)

# restore np.load for future normal usage
np.load = np_load_old
Sajad Norouzi
fuente
0

Normalmente no publico en estas cosas, pero esto fue muy molesto. La confusión proviene del hecho de que algunos de los imdb.pyarchivos de Keras ya se han actualizado:

with np.load(path) as f:

a la versión con allow_pickle=True. Asegúrese de verificar el archivo imdb.py para ver si este cambio ya se implementó. Si se ha ajustado, lo siguiente funciona bien:

from keras.datasets import imdb
(train_text, train_labels), (test_text, test_labels) = imdb.load_data(num_words=10000)
James
fuente
0

La forma más sencilla es cambiar la imdb.pyconfiguración allow_pickle=Truea np.loadla línea donde imdb.pyarroja el error.

Nasif Imtiaz Ohi
fuente