Як виправити "Об'єктні масиви не можуть бути завантажені, коли дозволити_pickle = False" для функції imdb.load_data ()?


113

Я намагаюся реалізувати приклад бінарної класифікації за допомогою даних даних IMDb в Google Colab . Я реалізував цю модель раніше. Але коли я спробував це зробити ще раз через кілька днів, він повернув помилку значення: 'Об'єктні масиви не можна завантажувати, коли enable_pickle = False' для функції load_data ().

Я вже намагався вирішити цю проблему, посилаючись на існуючу відповідь на подібну проблему: Як виправити "Об'єктні масиви не можна завантажити, коли enable_pickle = False" в алгоритмі sketch_rnn Але виявляється, що лише додавання аргументу дозволу_pickle недостатньо.

Мій код:

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

Помилка:

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
що означає ця помилка?
Чарлі Паркер

3
@CharlieParker Мабуть, було додано параметр у функції numpy.load (). Раніше це було np.load(path), тепер це np.load(path, boolean)за замовчуванням булевий (enable_pickle) помилковий
Kanad

Дякую! але чи це означає, що нуд зараз підбирає речі без мого дозволу при збереженні ?! дивно! Я подивився на np.savezдокументи, але не мав посилання на маринування, тому я не маю уявлення, як це навіть знав, в першу чергу, що речі, на яких я економив, - це речі Pytorch, а не тільки нудні ... дивні! Якщо ви знаєте, що ділиться з нами :)
Чарлі Паркер

Моє переконання після того , як зіткнувся з тією ж проблемою, полягає в тому, що це повністю залежить від того, що ви економите .npz. Якщо ви зберігаєте вбудовані типи, то не маринуйте. Однак, якщо ви пишете об'єкт, python / numpy маринує його (тобто серіалізує його). Я думаю, це відкриває ризик для безпеки, тому пізніші версії numpy перестали дозволяти йому бути за замовчуванням ... однак, лише переконання.
Роберт Лугг

Відповіді:


123

Ось трюк, щоб змусити imdb.load_dataдозволити соління, замінивши цей рядок у своєму блокноті:

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

цим:

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

Я пропоную додати "імпортувати numpy як np" на початку. Numpy може бути імпортований під іншою назвою, або взагалі не імпортуватися ...
Kristóf

Мені це дуже допомагає
staticor

7
ПомилкаTypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
Hayat

1
Проблема кілька значень для ключового слова аргумент був розглянутий в stackoverflow.com/a/58586450/5214998
Саяд Norouzi

91

Це питання все ще стоїть на keras git. Я сподіваюся, що це буде вирішено якнайшвидше. До цього часу спробуйте зменшити нумеровану версію до 1.16.2. Здається, вирішує проблему.

!pip install numpy==1.16.1
import numpy as np

Ця версія numpy має значення за замовчуванням allow_pickleяк True.


4
Я б скористався рішенням від MappaGnosis, а не пониженням нумерованої версії: для мене ф'ючерс з версією танцю - крайній захід!
eric

2
1.16.4 має питання, а
Kensai

Дякую @kensai Хтось знає, чи вирішили це в нуме 1,17?
nsheff

У numpy 1.18 все ще існує ця проблема. Я повинен був перейти на numpy 1.16.1 і це вирішено зараз. спасибі.
BC Smith

55

Після цієї проблеми на GitHub офіційним рішенням є редагування файлу imdb.py. Це виправлення спрацювало добре для мене, не потребуючи зменшення нумету. Знайдіть файл imdb.py за адресою tensorflow/python/keras/datasets/imdb.py(повний шлях для мене був: C:\Anaconda\Lib\site-packages\tensorflow\python\keras\datasets\imdb.py- інші установки будуть різними) та змініть рядок 85 відповідно до diff:

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

Причиною змін є безпека для запобігання еквіваленту Python ін'єкції SQL у маринований файл. Зміни, наведені вище, ТОЛЬКО вплинуть на дані imdb, і тому ви збережете безпеку в іншому місці (не зменшуючи нумеру).


1
Як я вже говорив, я використовую Colab, як я можу внести зміни у файл imdb.py?
Канад

Це не проблема Колаба, оскільки IMDB завантажується локально при першому посиланні на нього. Отже, десь на вашому комп’ютері буде локальна копія (спробуйте запропоновані шляхи вище - або, якщо ви встановите каталог для Colab, спробуйте спочатку) та просто відкрийте файл imdb.py у будь-якому IDE або навіть текстовому редакторі, щоб Внесіть зміни (я використовував Notepad ++ для редагування файлу imdb.py, який було завантажено під час роботи в Jupyter - так що середовище дуже схоже на Colab!).
MappaGnosis

рішення, яке для мене працює, -> np.load (data_path, encoding = 'latin1', enable_pickle = True)
Хорхе Сантос Ніл,

Це рішення, яке я використовую, як возитися з версіями (особливо з nummy), як у прийнятій відповіді, - це я намагаюся уникати. Це також більш пітонічно, оскільки явно просто вирішує проблему. (Зауважте також, що новіші версії Keras, в github, насправді містять це виправлення)
eric

35

Я просто використовував enable_pickle = True як аргумент до np.load (), і він працював на мене.


Я зауважую, що дозволяючи соління змінює масив. Масив .npy перед збереженням і після завантаження ніг виняток при спробі стверджувати про рівність, використовуючи np.array_equal
yasht

18

У моєму випадку працював із:

np.load(path, allow_pickle=True)

12

Я думаю, що відповідь від cheez ( https://stackoverflow.com/users/122933/cheez ) є найпростішим та найефективнішим. Я хотів би трохи детальніше розглянути його, щоб він не міняв функцію numpy протягом усього періоду сеансу.

Моя пропозиція нижче. Я використовую його для завантаження набору даних Reuters з keras, який показує такий самий вид помилок:

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)

Чи можете ви пояснити більше того, що відбувається тут?
Канад

1
Мені не вдалося завантажити набори даних Keras. Я здійснив пошук в Інтернеті і знайшов рішення, в якому сказано, що я повинен редагувати файл de imdb.py, інші вказували на зміни в установці numpy (як тут) або на зміну Tensorflow на версію розробки. Я натрапив на сирний розчин. ІМХО було найпростішим та найефективнішим.
Густаво Мірапальхета

1
@Kanad - лямбда - це анонімна функція. Густаво створив функцію-розширення до np.load, використав доповнену версію, а потім повернув до значення за замовчуванням.
EngrStudent


4

жодне з перерахованих вище рішень не працювало для мене: я запускаю анаконду з python 3.7.3. Що для мене працювало

  • запустіть "conda install numpy == 1.16.1" з оболонки Anaconda

  • закрийте та знову відкрийте зошит


Дякую, саме це я шукав. До речі, схоже, що 1.16.2 - це найновіша версія, де allow_pickle=Trueзначення за замовчуванням.
Matěj Račinský

3

на ноутбуці юпітера за допомогою

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)

добре працював, але проблема з’являється, коли ви використовуєте цей метод у шпидері (вам доведеться кожного разу перезавантажувати ядро, або ви отримаєте помилку типу:

TypeError: () отримав кілька значень для аргументу ключового слова "enable_pickle"

Я вирішив це питання, використовуючи рішення тут :


3

Я приземлився тут, випробував твої шляхи і не міг розібратися.

Я фактично працював над заданим кодом де

pickle.load(path)

був використаний, тому я замінив його

np.load(path, allow_pickle=True)

2

Так, встановлення попередньої версії numpy вирішило проблему.

Для тих, хто використовує PyCharm IDE:

у моєму IDE (Pycharm), File-> Settings-> Interpreter Project: я виявив, що мій номер був 1.16.3, тому я повернувся до 1.16.1. Клацніть + та введіть numpy у пошуку, поставте галочку "вказати версію": 1.16.1 та виберіть -> встановити пакет.


2

знайти шлях до imdb.py, а потім просто додати прапор до np.load (шлях, ... прапор ...)

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

1

Його робота для мене

        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
І деякий контекст, який пояснює, чому працює ваше рішення. (З огляду).
ZF007

1

Я знайшов, що TensorFlow 2.0 (я використовую 2.0.0-alpha0) не сумісний з останньою версією Numpy, тобто v1.17.0 (і, можливо, v1.16.5 +). Як тільки TF2 імпортується, він видає величезний список FutureWarning, який виглядає приблизно так:

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

Це також призвело до помилки enable_pickle при спробі завантаження набору даних imdb з керас

Я намагався використати наступне рішення, яке спрацювало чудово, але мені довелося це робити кожен окремий проект, де я імпортував TF2 або tf.keras.

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

Найпростішим рішенням, який я знайшов, було або встановити numpy 1.16.1 у всьому світі, або використовувати сумісні версії tensorflow і numpy у віртуальному середовищі.

Моя мета з цією відповіддю - зазначити, що це не просто проблема з imdb.load_data, а більша проблема, що виникає через несумісність версій TF2 та Numpy і може спричинити за собою багато інших прихованих помилок або проблем.


0

Tensorflow має виправлення в tf-нічній версії.

!pip install tf-nightly

Поточна версія - 2.0.0-dev20190511.


0

Відповідь @cheez коли - то не працює і рекурсивно викликати функцію знову і знову. Щоб вирішити цю проблему, слід скопіювати функцію глибоко. Це можна зробити за допомогою функції partial, тож кінцевим кодом є:

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

Я зазвичай не публікую ці речі, але це було дуже дратує. Плутанина пов'язана з тим, що деякі imdb.pyфайли Keras вже оновлені:

with np.load(path) as f:

до версії с allow_pickle=True. Переконайтесь, що перевірте файл imdb.py, щоб побачити, чи ця зміна вже була здійснена. Якщо вона була відрегульована, працює нормально:

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.