Jak naprawić „Tablice obiektów nie mogą być ładowane, gdy allow_pickle = False” dla funkcji imdb.load_data ()?


113

Próbuję zaimplementować przykład klasyfikacji binarnej przy użyciu zestawu danych IMDb w Google Colab . Wdrożyłem ten model już wcześniej. Ale kiedy próbowałem to zrobić ponownie po kilku dniach, zwróciło to błąd wartości: „Nie można załadować tablic obiektów, gdy allow_pickle = False” dla funkcji load_data ().

Próbowałem już to rozwiązać, odnosząc się do istniejącej odpowiedzi na podobny problem: Jak naprawić `` Tablice obiektów nie mogą być załadowane, gdy allow_pickle = False '' w algorytmie sketch_rnn Okazuje się, że samo dodanie argumentu allow_pickle nie jest wystarczające.

Mój kod:

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

Błąd:

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
co oznacza ten błąd?
Charlie Parker

3
@CharlieParker Najwyraźniej w funkcji numpy.load () został dodany parametr. Wcześniej tak było np.load(path), teraz jest np.load(path, boolean)Domyślnie, wartość logiczna (allow_pickle) ma wartość false
Kanad.

dzięki! ale czy to oznacza, że ​​odrętwienie teraz trawi dla mnie rzeczy bez mojej zgody podczas zapisywania ?! dziwne! Spojrzałem na np.savezdoktorów, ale nie było żadnego odniesienia do marynowania, więc nie mam pojęcia, skąd w ogóle wiedziałem, że rzeczy, które oszczędzałem, to rzeczy Pytorch i nie tylko nudne ... dziwne! Jeśli wiesz, co się dzieje, podziel się z nami :)
Charlie Parker

Po napotkaniu tego samego problemu uważam , że zależy on całkowicie od tego , co zapisujesz w pliku .npz. Jeśli zapisujesz typy wbudowane, nie wytrawiaj. Jednakże, jeśli napiszesz obiekt, Python / numpy wytropi go (tj. Serializuje). Wyobrażam sobie, że stwarza to zagrożenie bezpieczeństwa, więc późniejsze wersje numpy przestały zezwalać na to, by było to domyślne ... tylko przeczucie.
Robert Lugg

Odpowiedzi:


123

Oto sztuczka, którą można wymusić, imdb.load_dataaby zezwolić na marynowanie w notatniku, zastępując tę ​​linię:

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

przez to:

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

Proponuję na początku dodać „import numpy as np”. Numpy może być importowane pod inną nazwą lub wcale ...
Kristóf

Bardzo mi to pomaga
staticor

7
Pojawia się błądTypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
Hayat

1
Problem wielu wartości argumentu słowa kluczowego został rozwiązany na stackoverflow.com/a/58586450/5214998
Sajad Norouzi

91

Ten problem nadal występuje w keras git. Mam nadzieję, że zostanie rozwiązany tak szybko, jak to możliwe. Do tego czasu spróbuj obniżyć wersję numpy do 1.16.2. Wydaje się, że rozwiązuje problem.

!pip install numpy==1.16.1
import numpy as np

Ta wersja numpy ma domyślną wartość allow_pickleas True.


4
Wolałbym skorzystać z rozwiązania z MappaGnosis, zamiast obniżyć wersję numpy: dla mnie szaleństwo z wersją taniec to ostatnia deska ratunku!
eric

2
1.16.4 również ma problem
kensai

Dzięki @kensai. Czy ktoś wie, czy zostało to rozwiązane w Numpy 1.17?
nsheff

W numpy 1.18 nadal ten problem jest obecny. Musiałem przejść na numpy 1.16.1 i teraz zostało to rozwiązane. Dziękuję Ci.
BC Smith

55

W następstwie tego problemu na GitHub, oficjalnym rozwiązaniem jest edycja pliku imdb.py. Ta poprawka działała dobrze dla mnie bez konieczności obniżania wersji Numpy. Znajdź plik imdb.py pod adresem tensorflow/python/keras/datasets/imdb.py(pełna ścieżka dla mnie brzmiała: C:\Anaconda\Lib\site-packages\tensorflow\python\keras\datasets\imdb.py- inne instalacje będą inne) i zmień wiersz 85 zgodnie z różnicą:

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

Przyczyną tej zmiany jest ochrona przed stosowaniem w Pythonie odpowiednika iniekcji SQL w piklowanym pliku. Powyższa zmiana wpłynie TYLKO na dane imdb i dlatego zachowasz bezpieczeństwo w innym miejscu (nie obniżając wartości numpy).


1
Jak powiedziałem, używam Colab, jak mogę wprowadzić zmiany w pliku imdb.py?
Kanad

Nie jest to problem Colab, ponieważ IMDB jest pobierany lokalnie przy pierwszym odwołaniu do niego. Więc gdzieś na twoim komputerze będzie lokalna kopia (wypróbuj sugerowane ścieżki powyżej - lub, jeśli ustawisz katalog dla Colab, spróbuj najpierw tam) i po prostu otwórz plik imdb.py w dowolnym IDE lub nawet w edytorze tekstu, aby dokonać zmiany (użyłem Notepad ++ do edycji pliku imdb.py, który został pobrany podczas pracy w Jupyter - więc bardzo podobne środowisko do Colab!).
MappaGnosis

rozwiązaniem, które działa dla mnie jest> np.load (data_path, encoding = 'latin1', allow_pickle = True)
Jorge Santos Neill

To jest rozwiązanie, którego używam, ponieważ majstrowanie przy wersjach (zwłaszcza numpy), jak w przyjętej odpowiedzi, jest czymś, czego staram się unikać. Jest to również bardziej Pythonowe, ponieważ wyraźnie rozwiązuje problem. (Zwróć też uwagę, że najnowsze wersje Keras na githubie faktycznie zawierają tę poprawkę)
eric

35

Właśnie użyłem allow_pickle = True jako argument do np.load () i to zadziałało.


Obserwuję, że zezwolenie na marynowanie zmienia tablicę. Tablica .npy przed zapisaniem i po załadowaniu zgłasza wyjątek podczas próby zapewnienia równości za pomocą np.array_equal
yasht


12

Myślę, że odpowiedź z cheez ( https://stackoverflow.com/users/122933/cheez ) jest najłatwiejsza i najskuteczniejsza. Omówiłbym go trochę, aby nie modyfikował funkcji numpy przez cały okres sesji.

Moja sugestia jest poniżej. Używam go do pobrania zestawu danych firmy Reuters z keras, który pokazuje ten sam rodzaj błędu:

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)

Czy możesz wyjaśnić, co się tutaj dzieje?
Kanad

1
Nie mogłem załadować zestawów danych Keras. Przeszukałem Internet i znalazłem rozwiązanie, które mówiło, że powinienem edytować plik de imdb.py, inni wskazywali na zmiany w instalacji numpy (jak tutaj) lub zmianę Tensorflow na wersję rozwojową. Natknąłem się na rozwiązanie Cheez. IMHO to było najłatwiejsze i najskuteczniejsze.
Gustavo Mirapalheta

1
@Kanad - lambda to funkcja anonimowa. Gustavo stworzył rozszerzenie funkcji do np.load, użył wersji rozszerzonej, a następnie przywrócił wartość domyślną.
EngrStudent


4

żadne z wyżej wymienionych rozwiązań nie działało dla mnie: uruchamiam Anacondę z Pythonem 3.7.3. Dla mnie zadziałało

  • uruchom „conda install numpy == 1.16.1” z programu Anaconda powershell

  • zamknij i ponownie otwórz notatnik


Dzięki, tego szukałem. Nawiasem mówiąc, wygląda na to, że 1.16.2 to najnowsza wersja, w której allow_pickle=Truejest wartością domyślną.
Matěj Račinský

3

na notebooku jupyter za pomocą

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)

działało dobrze, ale problem pojawia się, gdy używasz tej metody w spyder (musisz za każdym razem restartować jądro lub pojawi się błąd taki jak:

TypeError: () pobrano wiele wartości dla argumentu słowa kluczowego „allow_pickle”

Rozwiązałem ten problem, korzystając z rozwiązania tutaj :


3

Wylądowałem tutaj, wypróbowałem twoje sposoby i nie mogłem tego rozgryźć.

Właściwie pracowałem nad wcześniej podanym kodem, w którym

pickle.load(path)

był używany, więc zastąpiłem go

np.load(path, allow_pickle=True)

2

Tak, zainstalowanie poprzedniej wersji numpy rozwiązało problem.

Dla tych, którzy używają PyCharm IDE:

w moim IDE (Pycharm), File-> Settings-> Project Interpreter: Okazało się, że mój numpy to 1.16.3, więc wracam do 1.16.1. Kliknij + i wpisz numpy w wyszukiwaniu, zaznacz "Określ wersję": 1.16.1 i wybierz -> zainstaluj pakiet.


2

znajdź ścieżkę do imdb.py, a następnie po prostu dodaj flagę do np.load (ścieżka, ... flaga ...)

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

1

To dla mnie praca

        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
I trochę kontekstu wyjaśniającego, dlaczego Twoje rozwiązanie działa. (Z recenzji).
ZF007

1

Odkryłem, że TensorFlow 2.0 (używam 2.0.0-alpha0) nie jest kompatybilny z najnowszą wersją Numpy tj. V1.17.0 (i prawdopodobnie v1.16.5 +). Zaraz po zaimportowaniu TF2 wyświetla ogromną listę FutureWarning, która wygląda mniej więcej tak:

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

Spowodowało to również błąd allow_pickle podczas próby załadowania zestawu danych imdb z keras

Próbowałem użyć następującego rozwiązania, które działało dobrze, ale musiałem to robić w każdym projekcie, w którym importowałem TF2 lub tf.keras.

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

Najłatwiejszym rozwiązaniem, które znalazłem, było zainstalowanie numpy 1.16.1 globalnie lub użycie kompatybilnych wersji tensorflow i numpy w środowisku wirtualnym.

Moim celem w tej odpowiedzi jest wskazanie, że nie jest to tylko problem z imdb.load_data, ale większy problem wynikający z niekompatybilności wersji TF2 i Numpy i może powodować wiele innych ukrytych błędów lub problemów.


0

Tensorflow ma poprawkę w wersji tf-nightly.

!pip install tf-nightly

Aktualna wersja to „2.0.0-dev20190511”.


0

Odpowiedź @cheez kiedyś nie działa rekursywnie i ponownie i ponownie wywołać funkcję. Aby rozwiązać ten problem, należy głęboko skopiować funkcję. Możesz to zrobić za pomocą funkcji partial, więc ostateczny kod to:

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

Zwykle nie publikuję w tych sprawach, ale to było bardzo irytujące. Zamieszanie wynika z faktu, że niektóre imdb.pypliki Keras zostały już zaktualizowane:

with np.load(path) as f:

do wersji z allow_pickle=True. Upewnij się, że sprawdź plik imdb.py, aby zobaczyć, czy ta zmiana została już zaimplementowana. Jeśli zostało wyregulowane, działa dobrze:

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

0

Najłatwiej jest zmienić imdb.pyustawienie allow_pickle=Truena np.loadw linii, w której imdb.pygeneruje błąd.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.