Wie kann man beheben, dass 'Objekt-Arrays nicht geladen werden können, wenn allow_pickle = False' für die Funktion imdb.load_data ()?


113

Ich versuche, das Beispiel für die binäre Klassifizierung mithilfe des IMDb-Datasets in Google Colab zu implementieren . Ich habe dieses Modell schon einmal implementiert. Als ich es jedoch nach einigen Tagen erneut versuchte, gab es einen Wertefehler zurück: 'Objektarrays können nicht geladen werden, wenn allow_pickle = False' für die Funktion load_data ().

Ich habe bereits versucht, dieses Problem zu lösen, indem ich mich auf eine vorhandene Antwort auf ein ähnliches Problem bezog: So beheben Sie das Problem , dass 'Objektarrays nicht geladen werden können, wenn allow_pickle = False' im Sketch_rnn-Algorithmus. Es stellt sich jedoch heraus, dass das Hinzufügen eines allow_pickle-Arguments nicht ausreicht.

Mein Code:

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

Der Fehler:

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
Was bedeutet dieser Fehler?
Charlie Parker

3
@CharlieParker Anscheinend wurde in der Funktion numpy.load () ein Parameter hinzugefügt. Früher war es np.load(path), jetzt ist es np.load(path, boolean)Standardmäßig ist der Boolesche Wert (allow_pickle) falsch
Kanad

Vielen Dank! aber heißt das, dass numpy jetzt ohne meine Erlaubnis beim Speichern Dinge für mich einlegt?! seltsam! Ich habe mir die np.savezDokumente angesehen, aber es gab keinen Hinweis auf das Beizen, daher habe ich keine Ahnung, woher es überhaupt wusste, dass die Dinge, die ich gespeichert habe, Pytorch-Zeug waren und nicht nur numpy ... seltsam! Wenn Sie wissen, was los ist, teilen Sie es uns mit :)
Charlie Parker

Mein Glaube, nachdem ich auf dasselbe Problem gestoßen bin, ist, dass es völlig davon abhängt, was Sie in einer .npz speichern. Wenn Sie eingebaute Typen speichern, erfolgt kein Beizen. Wenn Sie jedoch ein Objekt schreiben, wird es von Python / Numpy ausgewählt (dh serialisiert). Ich stelle mir vor, dass dies ein Sicherheitsrisiko darstellt, sodass spätere Versionen von numpy nicht mehr standardmäßig sind ... nur eine Vermutung.
Robert Lugg

Antworten:


123

Hier ist ein Trick, den Sie erzwingen müssen imdb.load_data, damit das Beizen in Ihrem Notizbuch diese Zeile ersetzt:

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

dadurch:

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

Ich schlage vor, am Anfang "import numpy as np" hinzuzufügen. Numpy kann unter einem anderen Namen importiert oder überhaupt nicht importiert werden ...
Kristóf

Es hilft mir sehr
Statiker oder

7
Immer FehlerTypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
Hayat

1
Das Problem der Mehrfachwerte für das Schlüsselwortargument wurde in stackoverflow.com/a/58586450/5214998
Sajad Norouzi

91

Dieses Problem ist immer noch bei Keras Git. Ich hoffe es wird so schnell wie möglich gelöst. Versuchen Sie bis dahin, Ihre Numpy-Version auf 1.16.2 herunterzustufen. Es scheint das Problem zu lösen.

!pip install numpy==1.16.1
import numpy as np

Diese Version von numpy hat den Standardwert allow_pickleas True.


4
Ich würde die Lösung von MappaGnosis verwenden, anstatt die numpy-Version herunterzustufen: Für mich ist das Herumtollen mit der Version Tanz ein letzter Ausweg!
Eric

2
1.16.4 hat auch das Problem
Kensai

Danke @kensai. Weiß jemand, ob dies in Numpy 1.17 gelöst wurde?
Nsheff

In Numpy 1.18 ist dieses Problem immer noch vorhanden. Ich musste auf numpy 1.16.1 umsteigen und es wurde jetzt gelöst. Danke.
BC Smith

55

Nach diesem Problem auf GitHub besteht die offizielle Lösung darin, die Datei imdb.py zu bearbeiten. Dieses Update hat bei mir gut funktioniert, ohne dass Numpy herabgestuft werden musste. Suchen Sie die Datei imdb.py unter tensorflow/python/keras/datasets/imdb.py(vollständiger Pfad für mich war: C:\Anaconda\Lib\site-packages\tensorflow\python\keras\datasets\imdb.py- andere Installationen sind anders) und ändern Sie Zeile 85 gemäß dem Diff:

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

Der Grund für die Änderung ist die Sicherheit, um das Python-Äquivalent einer SQL-Injection in einer ausgewählten Datei zu verhindern. Die obige Änderung wirkt sich NUR auf die IMDB-Daten aus und Sie behalten daher die Sicherheit an anderer Stelle (indem Sie numpy nicht herabstufen).


1
Wie gesagt, ich verwende Colab. Wie kann ich Änderungen an der Datei imdb.py vornehmen?
Kanad

Dies ist kein Colab-Problem, da IMDB beim ersten Verweisen lokal heruntergeladen wird. Es wird also irgendwo auf Ihrem Computer eine lokale Kopie vorhanden sein (versuchen Sie es mit den oben vorgeschlagenen Pfaden - oder, wenn Sie ein Verzeichnis für Colab festlegen, versuchen Sie es zuerst dort) und öffnen Sie einfach die Datei imdb.py in einer beliebigen IDE oder sogar einem Texteditor für Nehmen Sie die Änderung vor (ich habe Notepad ++ verwendet, um die Datei imdb.py zu bearbeiten, die bei der Arbeit in Jupyter heruntergeladen wurde - also eine sehr ähnliche Umgebung wie Colab!).
MappaGnosis

Die Lösung, die für mich funktioniert, ist> np.load (data_path, encoding = 'latin1', allow_pickle = True)
Jorge Santos Neill

Dies ist die Lösung, die ich benutze, da ich versuche, mit Versionen (insbesondere von Numpy) herumzuspielen, wie in der akzeptierten Antwort. Dies ist auch pythonischer, da es das Problem explizit nur behebt. (Beachten Sie auch, dass die neuesten Versionen von Keras bei Github dieses Update tatsächlich enthalten.)
Eric

35

Ich habe gerade allow_pickle = True als Argument für np.load () verwendet und es hat bei mir funktioniert.


Ich beobachte, dass das Zulassen von Pickle das Array ändert. Das .npy-Array vor dem Speichern und nach dem Laden löst eine Ausnahme aus, wenn versucht wird, mit np.array_equal
yasht

18

In meinem Fall arbeitete mit:

np.load(path, allow_pickle=True)

12

Ich denke die Antwort von cheez ( https://stackoverflow.com/users/122933/cheez ) ist die einfachste und effektivste. Ich würde ein wenig darauf eingehen, damit eine Numpy-Funktion nicht für den gesamten Sitzungszeitraum geändert wird.

Mein Vorschlag ist unten. Ich verwende es, um den Reuters-Datensatz von Keras herunterzuladen, der die gleiche Art von Fehler anzeigt:

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)

Können Sie mehr darüber erklären, was hier passiert?
Kanad

1
Ich konnte die Keras-Datasets nicht laden. Ich suchte im Internet und fand eine Lösung, die besagte, dass ich die Datei de imdb.py bearbeiten sollte, andere wiesen auf Änderungen in der Numpy-Installation (wie hier) oder auf die Änderung von Tensorflow in eine Entwicklungsversion hin. Ich bin auf eine gute Lösung gestoßen. IMHO war das das einfachste und effektivste.
Gustavo Mirapalheta

1
@ Kanad - Lambda ist eine anonyme Funktion. Gustavo erstellte eine Funktionserweiterung für np.load, verwendete die erweiterte Version und setzte sie dann auf den Standardwert zurück.
EngrStudent


4

Keine der oben aufgeführten Lösungen hat bei mir funktioniert: Ich verwende Anaconda mit Python 3.7.3. Was für mich funktioniert hat war

  • Führen Sie "conda install numpy == 1.16.1" von Anaconda Powershell aus

  • Schließen Sie das Notebook und öffnen Sie es erneut


Danke, das habe ich gesucht. Übrigens sieht es so aus, als wäre 1.16.2 die neueste Version mit dem allow_pickle=TrueStandardwert.
Matěj Račinský

3

auf jupyter notebook mit

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)

hat gut funktioniert, aber das Problem tritt auf, wenn Sie diese Methode in spyder verwenden (Sie müssen den Kernel jedes Mal neu starten, sonst erhalten Sie eine Fehlermeldung wie:

TypeError: () hat mehrere Werte für das Schlüsselwortargument 'allow_pickle' erhalten.

Ich löste dieses Problem , die Lösung unter Verwendung von hier :


3

Ich bin hier oben gelandet, habe deine Wege ausprobiert und konnte es nicht herausfinden.

Ich habe tatsächlich an einem vorgegebenen Code gearbeitet, wo

pickle.load(path)

wurde verwendet, also habe ich es durch ersetzt

np.load(path, allow_pickle=True)

2

Ja, die Installation einer früheren Version von numpy hat das Problem behoben.

Für diejenigen, die PyCharm IDE verwenden:

In meiner IDE (Pycharm), Datei-> Einstellungen-> Projektinterpreter: Ich habe festgestellt, dass meine Nummer 1.16.3 ist, und kehre daher zu 1.16.1 zurück. Klicken Sie auf + und geben Sie numpy in die Suche ein, kreuzen Sie "Version angeben": 1.16.1 an und wählen Sie -> Paket installieren.


2

Finde den Pfad zu imdb.py und füge dann einfach das Flag zu np.load hinzu (Pfad, ... Flag ...)

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

1

Es ist Arbeit für mich

        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
Und ein Kontext, der erklärt, warum Ihre Lösung funktioniert. (Aus der Überprüfung).
ZF007

1

Was ich gefunden habe ist, dass TensorFlow 2.0 (ich verwende 2.0.0-alpha0) nicht mit der neuesten Version von Numpy kompatibel ist, dh v1.17.0 (und möglicherweise v1.16.5 +). Sobald TF2 importiert wird, wird eine riesige Liste von FutureWarning ausgegeben, die ungefähr so ​​aussieht:

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

Dies führte auch zu dem Fehler allow_pickle, wenn versucht wurde, das imdb-Dataset von Keras zu laden

Ich habe versucht, die folgende Lösung zu verwenden, die einwandfrei funktioniert hat, aber ich musste sie bei jedem einzelnen Projekt ausführen, bei dem ich TF2 oder tf.keras importierte.

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

Die einfachste Lösung, die ich gefunden habe, war, entweder numpy 1.16.1 global zu installieren oder kompatible Versionen von Tensorflow und numpy in einer virtuellen Umgebung zu verwenden.

Mein Ziel mit dieser Antwort ist es, darauf hinzuweisen, dass es nicht nur ein Problem mit imdb.load_data ist, sondern ein größeres Problem, das durch die Inkompatibilität von TF2- und Numpy-Versionen verursacht wird und zu vielen anderen versteckten Fehlern oder Problemen führen kann.


0

Tensorflow hat einen Fix in der tf-nightly-Version.

!pip install tf-nightly

Die aktuelle Version ist '2.0.0-dev20190511'.


0

Die Antwort von @cheez funktioniert manchmal nicht und ruft die Funktion immer wieder rekursiv auf. Um dieses Problem zu lösen, sollten Sie die Funktion gründlich kopieren. Sie können dies mithilfe der Funktion partialtun. Der endgültige Code lautet also:

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

Normalerweise poste ich nicht auf diese Dinge, aber das war super nervig. Die Verwirrung ergibt sich aus der Tatsache, dass einige der Keras- imdb.pyDateien bereits aktualisiert wurden:

with np.load(path) as f:

zur Version mit allow_pickle=True. Überprüfen Sie in der Datei imdb.py, ob diese Änderung bereits implementiert wurde. Wenn es angepasst wurde, funktioniert Folgendes einwandfrei:

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

0

Am einfachsten ist es, die imdb.pyEinstellung an der Zeile zu ändern allow_pickle=True, np.loadan der imdb.pyFehler ausgegeben werden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.