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.