Come risolvere il problema "Impossibile caricare gli array di oggetti quando allow_pickle = False" per la funzione imdb.load_data ()?


113

Sto cercando di implementare l'esempio di classificazione binaria utilizzando il set di dati IMDb in Google Colab . Ho implementato questo modello prima. Ma quando ho provato a farlo di nuovo dopo alcuni giorni, ha restituito un errore di valore: 'Gli array di oggetti non possono essere caricati quando allow_pickle = False' per la funzione load_data ().

Ho già provato a risolverlo, facendo riferimento a una risposta esistente per un problema simile: come correggere 'Gli array di oggetti non possono essere caricati quando allow_pickle = False' nell'algoritmo sketch_rnn Ma risulta che la semplice aggiunta di un argomento allow_pickle non è sufficiente.

Il mio codice:

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

L'errore:

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
cosa significa questo errore?
Charlie Parker

3
@CharlieParker Apparentemente c'è stata un'aggiunta di un parametro nella funzione numpy.load (). In precedenza lo era np.load(path), ora è np.load(path, boolean)Per impostazione predefinita, il valore booleano (allow_pickle) è falso
Kanad

Grazie! ma questo significa che ora numpy mette sottaceti per me senza il mio permesso durante il salvataggio ?! strano! Ho guardato i np.savezdocumenti ma non c'era alcun riferimento al decapaggio, quindi non ho idea di come facesse a sapere in primo luogo che le cose che stavo salvando erano roba da Pytorch e non solo insensibile ... strano! Se sai cosa sta succedendo, condividi con noi :)
Charlie Parker

La mia convinzione dopo aver riscontrato lo stesso problema è che dipende totalmente da ciò che stai salvando in un .npz. Se stai salvando i tipi incorporati, allora nessun decapaggio. Tuttavia, se scrivi un oggetto, python / numpy lo selezionerà (cioè lo serializzerà). Immagino che questo apra un rischio per la sicurezza, quindi le versioni successive di numpy hanno smesso di consentirne l'impostazione predefinita ... solo un'intuizione però.
Robert Lugg

Risposte:


123

Ecco un trucco da forzare imdb.load_dataper consentire il pickle, nel tuo notebook, sostituendo questa riga:

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

da questo:

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

Suggerisco di aggiungere "import numpy as np" all'inizio. Numpy può essere importato con un nome diverso o non importato affatto ...
Kristóf

Mi aiuta molto
statica o

7
Errore di TypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
acquisizione

1
Il problema di valori multipli per argomento chiave è stato affrontato in stackoverflow.com/a/58586450/5214998
Sajad Norouzi

91

Questo problema è ancora presente su keras git. Spero che venga risolto il prima possibile. Fino ad allora, prova a eseguire il downgrade della tua versione di numpy alla 1.16.2. Sembra risolvere il problema.

!pip install numpy==1.16.1
import numpy as np

Questa versione di numpy ha il valore predefinito di allow_pickleas True.


4
Userei la soluzione di MappaGnosis piuttosto che eseguire il downgrade della versione numpy: per me andare in giro con la versione dance è l'ultima risorsa!
eric

2
1.16.4 ha anche il problema
kensai

Grazie @kensai. Qualcuno sa se questo è stato risolto in numpy 1.17?
nsheff

In numpy 1.18 ancora questo problema è presente. Ho dovuto passare a numpy 1.16.1 e ora è stato risolto. grazie.
BC Smith

55

A seguito di questo problema su GitHub, la soluzione ufficiale è modificare il file imdb.py. Questa correzione ha funzionato bene per me senza la necessità di eseguire il downgrade di numpy. Trova il file imdb.py in tensorflow/python/keras/datasets/imdb.py(il percorso completo per me era: C:\Anaconda\Lib\site-packages\tensorflow\python\keras\datasets\imdb.py- le altre installazioni saranno diverse) e cambia la riga 85 come da diff:

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

Il motivo del cambiamento è la sicurezza per impedire l'equivalente Python di un'iniezione SQL in un file in salamoia. La modifica di cui sopra avrà effetto SOLO sui dati imdb e quindi manterrai la sicurezza altrove (non declassando numpy).


1
Come ho detto, sto usando Colab, come posso apportare modifiche al file imdb.py?
Kanad

Questo non è un problema di Colab poiché IMDB viene scaricato localmente la prima volta che lo fai riferimento. Quindi, ci sarà una copia locale da qualche parte sul tuo computer (prova i percorsi suggeriti sopra - o, se imposti una directory per Colab, prova prima lì) e apri semplicemente il file imdb.py in qualsiasi IDE o anche un editor di testo per apporta la modifica (ho usato Notepad ++ per modificare il file imdb.py che è stato scaricato lavorando in Jupyter, quindi un ambiente molto simile a Colab!).
MappaGnosis

la soluzione che funziona per me è> np.load (data_path, encoding = 'latin1', allow_pickle = True)
Jorge Santos Neill

Questa è la soluzione che uso, dato che scherzare con le versioni (specialmente di numpy), come nella risposta accettata, è qualcosa che cerco di evitare. Questo è anche più pitonico in quanto risolve esplicitamente il problema. (Nota anche le versioni più recenti di Keras, su GitHub, incorporano effettivamente questa correzione)
Eric

35

Ho appena usato allow_pickle = True come argomento per np.load () e ha funzionato per me.


Sto osservando che il permesso di pickle cambia l'array. L'array .npy prima del salvataggio e dopo il caricamento mostra un'eccezione quando si tenta di affermare l'uguaglianza utilizzando np.array_equal
yasht

18

Nel mio caso ha lavorato con:

np.load(path, allow_pickle=True)

12

Penso che la risposta di cheez ( https://stackoverflow.com/users/122933/cheez ) sia la più semplice ed efficace. Ho elaborato un po 'su di esso in modo che non modifichi una funzione numpy per l'intero periodo della sessione.

Il mio suggerimento è di seguito. Lo sto usando per scaricare il set di dati di reuters da keras che mostra lo stesso tipo di errore:

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)

Puoi spiegare di più su cosa sta succedendo qui?
Kanad

1
Non ero in grado di caricare i set di dati di Keras. Ho cercato su Internet e ho trovato una soluzione che diceva che dovevo modificare il file de imdb.py, altri indicavano modifiche nell'installazione di numpy (come qui) o modifica di Tensorflow in una versione di sviluppo. Mi sono imbattuto in una soluzione di cheez. IMHO quello è stato il più semplice ed efficace.
Gustavo Mirapalheta

1
@Kanad - lambda è una funzione anonima. Gustavo ha creato un aumento di funzione per np.load, ha utilizzato la versione aumentata, quindi è tornato al valore predefinito.
EngrStudent


4

nessuna delle soluzioni sopra elencate ha funzionato per me: eseguo anaconda con python 3.7.3. Quello che ha funzionato per me è stato

  • eseguire "conda install numpy == 1.16.1" da Anaconda powershell

  • chiudere e riaprire il blocco appunti


Grazie, è quello che ho cercato. A proposito, sembra che 1.16.2 sia la versione più recente in cui allow_pickle=Trueè il valore predefinito.
Matěj Račinský

3

su jupyter notebook utilizzando

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)

ha funzionato bene, ma il problema appare quando usi questo metodo in Spyder (devi riavviare il kernel ogni volta o otterrai un errore come:

TypeError: () ha ottenuto più valori per l'argomento della parola chiave "allow_pickle"

Ho risolto questo problema utilizzando la soluzione qui :


3

Sono atterrato qui, ho provato i tuoi metodi e non sono riuscito a capirlo.

In realtà stavo lavorando su un codice prestabilito dove

pickle.load(path)

è stato utilizzato, quindi l'ho sostituito con

np.load(path, allow_pickle=True)

2

Sì, l'installazione di una versione precedente di numpy ha risolto il problema.

Per coloro che utilizzano PyCharm IDE:

nel mio IDE (Pycharm), File-> Impostazioni-> Interprete del progetto: ho trovato il mio numpy 1.16.3, quindi torno alla 1.16.1. Fai clic su + e digita numpy nella ricerca, seleziona "specifica versione": 1.16.1 e scegli -> installa pacchetto.


2

trova il percorso per imdb.py quindi aggiungi semplicemente il flag a np.load (percorso, ... flag ...)

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

1

Per me funziona

        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
E un contesto che spiega perché la tua soluzione funziona. (Dalla recensione).
ZF007

1

Quello che ho scoperto è che TensorFlow 2.0 (sto usando 2.0.0-alpha0) non è compatibile con l'ultima versione di Numpy cioè v1.17.0 (e forse v1.16.5 +). Non appena TF2 viene importato, genera un enorme elenco di FutureWarning, che assomiglia a questo:

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

Ciò ha anche provocato l'errore allow_pickle quando si è tentato di caricare il set di dati imdb da keras

Ho provato a utilizzare la seguente soluzione che ha funzionato bene, ma ho dovuto eseguire ogni singolo progetto in cui stavo importando TF2 o tf.keras.

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

La soluzione più semplice che ho trovato è stata installare numpy 1.16.1 a livello globale o utilizzare versioni compatibili di tensorflow e numpy in un ambiente virtuale.

Il mio obiettivo con questa risposta è sottolineare che non è solo un problema con imdb.load_data, ma un problema più ampio dovuto all'incompatibilità delle versioni TF2 e Numpy e può causare molti altri bug o problemi nascosti.


0

Tensorflow ha una correzione nella versione tf-nightly.

!pip install tf-nightly

La versione corrente è "2.0.0-dev20190511".


0

La risposta di @cheez a volte non funziona e chiama in modo ricorsivo la funzione ancora e ancora. Per risolvere questo problema dovresti copiare la funzione in profondità. Puoi farlo usando la funzione partial, quindi il codice finale è:

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

Di solito non invio a queste cose, ma questo è stato super fastidioso. La confusione deriva dal fatto che alcuni dei imdb.pyfile Keras sono già stati aggiornati:

with np.load(path) as f:

alla versione con allow_pickle=True. Assicurati di controllare il file imdb.py per vedere se questa modifica è già stata implementata. Se è stato modificato, quanto segue funziona bene:

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

0

Il modo più semplice è modificare l' imdb.pyimpostazione allow_pickle=Truein np.loadcorrispondenza della riga in cui imdb.pygenera l'errore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.