Comment réparer 'Les tableaux d'objets ne peuvent pas être chargés lorsque allow_pickle = False' pour la fonction imdb.load_data ()?


113

J'essaie d'implémenter l'exemple de classification binaire en utilisant l'ensemble de données IMDb dans Google Colab . J'ai déjà implémenté ce modèle. Mais quand j'ai essayé de le faire à nouveau après quelques jours, cela a renvoyé une erreur de valeur: `` Les tableaux d'objets ne peuvent pas être chargés lorsque allow_pickle = False '' pour la fonction load_data ().

J'ai déjà essayé de résoudre cela, en faisant référence à une réponse existante pour un problème similaire: Comment réparer `` Les tableaux d'objets ne peuvent pas être chargés lorsque allow_pickle = False '' dans l'algorithme sketch_rnn Mais il s'avère que l'ajout d'un argument allow_pickle n'est pas suffisant.

Mon code:

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

L'erreur:

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

1
Que signifie cette erreur?
Charlie Parker

3
@CharlieParker Apparemment, il y a eu un ajout d'un paramètre dans la fonction numpy.load (). Auparavant c'était np.load(path), maintenant c'est np.load(path, boolean)Par défaut, le booléen (allow_pickle) est faux
Kanad

Merci! mais cela signifie-t-il que numpy maintenant des choses pour moi sans ma permission lors de l'enregistrement?! bizarre! J'ai regardé des np.savezdocuments mais il n'y avait aucune référence au décapage, donc je ne sais pas comment il savait même en premier lieu que les choses que je sauvegardais étaient des trucs de Pytorch et pas seulement stupides ... bizarres! Si vous savez ce qui se passe, partagez avec nous :)
Charlie Parker

Ma conviction après avoir rencontré le même problème est que cela dépend totalement de ce que vous enregistrez dans un fichier .npz. Si vous enregistrez des types intégrés, pas de décapage. Cependant, si vous écrivez un objet, python / numpy le décapera (ie le sérialisera). J'imagine que cela ouvre un risque de sécurité, donc les versions ultérieures de numpy ont cessé de l'autoriser par défaut ... juste une intuition cependant.
Robert Lugg

Réponses:


123

Voici une astuce pour forcer imdb.load_dataà autoriser pickle en remplaçant cette ligne dans votre cahier:

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

par ça:

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

Je suggère d'ajouter "import numpy as np" au début. Numpy peut être importé sous un nom différent, ou pas du tout importé ...
Kristóf

Ça m'aide beaucoup
staticor

7
Obtenir une erreurTypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
Hayat

1
Le problème des valeurs multiples pour l'argument de mot-clé a été abordé dans stackoverflow.com/a/58586450/5214998
Sajad Norouzi

91

Ce problème est toujours d'actualité sur keras git. J'espère que cela sera résolu le plus tôt possible. Jusque-là, essayez de rétrograder votre version numpy à 1.16.2. Cela semble résoudre le problème.

!pip install numpy==1.16.1
import numpy as np

Cette version de numpy a la valeur par défaut de allow_pickleas True.


4
J'utiliserais la solution de MappaGnosis plutôt que de déclasser la version numpy: pour moi, jouer avec la version dance est un dernier recours!
eric

2
1.16.4 a également le problème
kensai

Merci @kensai. Est-ce que quelqu'un sait si cela a été résolu dans numpy 1.17?
nsheff

Dans numpy 1.18, ce problème est toujours présent. J'ai dû passer à numpy 1.16.1 et c'est résolu maintenant. Merci.
BC Smith

55

Suite à ce problème sur GitHub, la solution officielle consiste à éditer le fichier imdb.py. Ce correctif a bien fonctionné pour moi sans qu'il soit nécessaire de rétrograder numpy. Trouvez le fichier imdb.py à tensorflow/python/keras/datasets/imdb.py(le chemin complet pour moi était: C:\Anaconda\Lib\site-packages\tensorflow\python\keras\datasets\imdb.py- les autres installations seront différentes) et changez la ligne 85 selon le diff:

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

La raison du changement est la sécurité pour empêcher l'équivalent Python d'une injection SQL dans un fichier pickled. Le changement ci-dessus affectera UNIQUEMENT les données imdb et vous conservez donc la sécurité ailleurs (en ne rétrogradant pas numpy).


1
Comme je l'ai dit, j'utilise Colab, comment puis-je apporter des modifications au fichier imdb.py?
Kanad

Ce n'est pas un problème Colab car IMDB est téléchargé localement la première fois que vous le référencez. Donc, il y aura une copie locale quelque part sur votre ordinateur (essayez les chemins suggérés ci-dessus - ou, si vous définissez un répertoire pour Colab, essayez-le d'abord) et ouvrez simplement le fichier imdb.py dans n'importe quel IDE ou même un éditeur de texte pour faire le changement (j'ai utilisé Notepad ++ pour éditer le fichier imdb.py qui a été téléchargé lors de l'utilisation de Jupyter - donc un environnement très similaire à Colab!).
MappaGnosis

la solution qui fonctionne pour moi est> np.load (data_path, encoding = 'latin1', allow_pickle = True)
Jorge Santos Neill

C'est la solution que j'utilise, car déconner avec les versions (en particulier de numpy), comme dans la réponse acceptée, est quelque chose que j'essaie d'éviter. Ceci est également plus pythonique car il résout explicitement le problème. (Notez également que les dernières versions de Keras, sur github, intègrent ce correctif)
Eric

35

Je viens d'utiliser allow_pickle = True comme argument de np.load () et cela a fonctionné pour moi.


J'observe que permettre au pickle change le tableau. Le tableau .npy avant l'enregistrement et après le chargement crée une exception lors de la tentative d'affirmation de l'égalité à l'aide de np.array_equal
yasht

18

Dans mon cas, j'ai travaillé avec:

np.load(path, allow_pickle=True)

12

Je pense que la réponse de cheez ( https://stackoverflow.com/users/122933/cheez ) est la plus simple et la plus efficace. Je développerais un peu dessus pour ne pas modifier une fonction numpy pendant toute la période de session.

Ma suggestion est ci-dessous. Je l'utilise pour télécharger le jeu de données reuters de keras qui montre le même type d'erreur:

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)

Pouvez-vous expliquer plus sur ce qui se passe ici?
Kanad

1
Je ne pouvais pas charger les ensembles de données Keras. J'ai cherché sur Internet et j'ai trouvé une solution qui disait que je devais éditer le fichier de imdb.py, d'autres ont signalé des changements dans l'installation de numpy (comme ici) ou le changement de Tensorflow vers une version de développement. Je suis tombé sur une solution de cheez. IMHO qui était le plus simple et le plus efficace.
Gustavo Mirapalheta

1
@Kanad - lambda est une fonction anonyme. Gustavo a créé une fonction-augment pour le np.load, utilisé la version augmentée, puis remis à la valeur par défaut.
EngrStudent


4

aucune des solutions énumérées ci-dessus n'a fonctionné pour moi: je lance anaconda avec python 3.7.3. Ce qui a fonctionné pour moi était

  • exécutez "conda install numpy == 1.16.1" depuis Anaconda powershell

  • fermez et rouvrez le notebook


Merci, c'est ce que j'ai recherché. À propos, il semble que 1.16.2 est la dernière version où allow_pickle=Trueest la valeur par défaut.
Matěj Račinský

3

sur le notebook jupyter en utilisant

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)

a bien fonctionné, mais le problème apparaît lorsque vous utilisez cette méthode dans spyder (vous devez redémarrer le noyau à chaque fois ou vous obtiendrez une erreur comme:

TypeError: () a obtenu plusieurs valeurs pour l'argument de mot-clé 'allow_pickle'

J'ai résolu ce problème en utilisant la solution ici :


3

J'ai atterri ici, j'ai essayé vos voies et je n'ai pas pu comprendre.

Je travaillais en fait sur un code prédéfini où

pickle.load(path)

a été utilisé alors je l'ai remplacé par

np.load(path, allow_pickle=True)

2

Oui, l'installation d'une version précédente de numpy a résolu le problème.

Pour ceux qui utilisent PyCharm IDE:

dans mon IDE (Pycharm), File-> Settings-> Project Interpreter: j'ai trouvé que mon numpy était 1.16.3, donc je reviens à 1.16.1. Cliquez sur + et tapez numpy dans la recherche, cochez "spécifier la version": 1.16.1 et choisissez -> installer le package.


2

trouvez le chemin vers imdb.py puis ajoutez simplement le drapeau à np.load (chemin, ... drapeau ...)

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

1

Son travail pour moi

        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

4
Et un contexte expliquant pourquoi votre solution fonctionne. (De l'avis).
ZF007

1

Ce que j'ai trouvé, c'est que TensorFlow 2.0 (j'utilise 2.0.0-alpha0) n'est pas compatible avec la dernière version de Numpy, c'est-à-dire v1.17.0 (et peut-être v1.16.5 +). Dès que TF2 est importé, il lance une énorme liste de FutureWarning, qui ressemble à ceci:

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'.

Cela a également entraîné l'erreur allow_pickle lors de la tentative de chargement du jeu de données imdb à partir de keras

J'ai essayé d'utiliser la solution suivante qui fonctionnait très bien, mais je devais le faire à chaque projet où j'importais TF2 ou tf.keras.

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

La solution la plus simple que j'ai trouvée était soit d'installer numpy 1.16.1 globalement, soit d'utiliser des versions compatibles de tensorflow et numpy dans un environnement virtuel.

Mon objectif avec cette réponse est de souligner que ce n'est pas seulement un problème avec imdb.load_data, mais un problème plus important provoqué par l'incompatibilité des versions TF2 et Numpy et peut entraîner de nombreux autres bogues ou problèmes cachés.


0

Tensorflow a un correctif dans la version tf-nightly.

!pip install tf-nightly

La version actuelle est «2.0.0-dev20190511».


0

La réponse de @cheez parfois ne fonctionne pas et appelle récursivement la fonction encore et encore. Pour résoudre ce problème, vous devez copier la fonction en profondeur. Vous pouvez le faire en utilisant la fonction partial, le code final est donc:

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

0

Je ne poste généralement pas sur ces choses mais c'était super ennuyeux. La confusion vient du fait que certains des imdb.pyfichiers Keras ont déjà été mis à jour:

with np.load(path) as f:

à la version avec allow_pickle=True. Assurez-vous de vérifier le fichier imdb.py pour voir si ce changement a déjà été implémenté. S'il a été ajusté, ce qui suit fonctionne correctement:

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

0

La façon la plus simple est de changer imdb.pyparamètre allow_pickle=Trueà np.loadla ligne où imdb.pyjette l' erreur.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.