Как исправить ошибку «Массивы объектов не загружаются, когда allow_pickle = False» для функции imdb.load_data ()?

114

Я пытаюсь реализовать пример двоичной классификации, используя набор данных IMDb в Google Colab . Я уже реализовал эту модель раньше. Но когда я попытался сделать это снова через несколько дней, он вернул ошибку значения: «Массивы объектов не могут быть загружены, когда allow_pickle = False» для функции load_data ().

Я уже пробовал решить эту проблему, ссылаясь на существующий ответ для аналогичной проблемы: Как исправить «Массивы объектов не могут быть загружены, когда allow_pickle = False» в алгоритме sketch_rnn. Но оказалось, что простого добавления аргумента allow_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)умолчанию логическое значение (allow_pickle) равно false
Kanad
Спасибо! но означает ли это, что numpy теперь солит для меня вещи без моего разрешения при сохранении ?! странно! Я просмотрел np.savezдокументы, но там не было упоминания о мариновании, поэтому я понятия не имею, как он вообще знал, что вещи, которые я сохранял, были материалом Pytorch, а не только numpy ... странно! Если вы знаете, что происходит, поделитесь с нами :)
Чарли Паркер
После того , как я столкнулся с той же проблемой, я считаю, что это полностью зависит от того, что вы сохраняете в .npz. Если вы экономите встроенные типы, то без травления. Однако, если вы напишете объект, python / numpy обработает его (то есть сериализует). Я полагаю, это создает угрозу безопасности, поэтому более поздние версии numpy перестали разрешать его по умолчанию ... хотя это просто догадка.
Роберт Лагг

Ответы:

124

Вот трюк, 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
чиз
источник
Предлагаю вначале добавить "import numpy as np". Numpy может быть импортирован под другим именем или не импортирован вообще ...
Кристоф
Мне это очень помогает
staticor 02
7
Получение ошибкиTypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
Hayat
1
Проблема с несколькими значениями для аргумента ключевого слова была решена в stackoverflow.com/a/58586450/5214998
Саджад Норузи
91

Эта проблема все еще актуальна для keras git. Я надеюсь, что проблема будет решена как можно скорее. А пока попробуйте понизить свою версию numpy до 1.16.2. Вроде решает проблему.

!pip install numpy==1.16.1
import numpy as np

Эта версия numpy имеет значение по умолчанию allow_pickleas True.

Тирт Патель
источник
4
Я бы использовал решение от MappaGnosis, а не понижал версию numpy: для меня игра с версией dance - последнее средство!
eric
2
1.16.4 также имеет проблему
кенсай
Спасибо @kensai. Кто-нибудь знает, решено ли это в numpy 1.17?
nsheff
В numpy 1.18 эта проблема все еще присутствует. Мне пришлось перейти на numpy 1.16.1, и теперь это решено. Спасибо.
BC Smith
55

После этой проблемы на GitHub официальное решение - отредактировать файл imdb.py. Это исправление сработало для меня без необходимости понижать версию numpy. Найдите файл 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, и поэтому вы сохраните безопасность в другом месте (не понижая numpy).

MappaGnosis
источник
1
Как я уже сказал, я использую Colab, как мне внести изменения в файл imdb.py?
Канад
Это не проблема Colab, поскольку IMDB загружается локально при первой ссылке на него. Итак, где-то на вашем компьютере будет локальная копия (попробуйте предложенные выше пути - или, если вы установили каталог для Colab, попробуйте сначала) и просто откройте файл imdb.py в любой среде IDE или даже в текстовом редакторе, чтобы внесите изменения (я использовал Notepad ++ для редактирования файла imdb.py, который был загружен при работе в Jupyter - так что среда очень похожа на Colab!).
MappaGnosis
решение, которое работает для меня, -> np.load (data_path, encoding = 'latin1', allow_pickle = True)
Хорхе Сантос Нил
Это решение, которое я использую, так как возиться с версиями (особенно numpy), как в принятом ответе, - это то, чего я стараюсь избегать. Это также более питонично, поскольку явно устраняет проблему. (Обратите внимание, что последние версии Keras на github фактически включают это исправление)
eric
35

Я просто использовал allow_pickle = True в качестве аргумента для np.load (), и у меня это сработало.

Мадхупарна Бховмик
источник
Я наблюдаю, что разрешение pickle изменяет массив. .Npy массива перед сохранением и после загрузки thows исключения при попытке утверждает равенство с использованием np.array_equal
Yasht
18

В моем случае работал с:

np.load(path, allow_pickle=True)
травки15
источник
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
9

Вы можете попробовать изменить значение флага

np.load(training_image_names_array,allow_pickle=True)
Брайан Армандо Якиан Гонсале
источник
Отлично. Это работает. Это должен быть принятый ответ.
Биранчи,
4

Ни одно из перечисленных выше решений у меня не помогло: я запускаю anaconda с python 3.7.3. Для меня сработало

  • запустите "conda install numpy == 1.16.1" из Anaconda powershell

  • закройте и снова откройте блокнот

фарид хафизов
источник
Спасибо, это то, что я искал. Кстати, похоже, что 1.16.2 - новейшая версия, где allow_pickle=Trueзначение по умолчанию.
Матей Рачинский,
3

на ноутбуке jupyter с использованием

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)

работал нормально, но проблема возникает, когда вы используете этот метод в spyder (вам нужно перезапускать ядро ​​каждый раз, иначе вы получите ошибку вроде:

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

Я решил эту проблему, используя решение здесь :

Ясир Албарбай
источник
3

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

На самом деле я работал над заранее заданным кодом, в котором

pickle.load(path)

был использован, поэтому я заменил его на

np.load(path, allow_pickle=True)
Шристи Гупта
источник
2

Да, установка предыдущей версии numpy решила проблему.

Для тех, кто использует PyCharm IDE:

в моей IDE (Pycharm), File-> Settings-> Project Interpreter: я обнаружил, что мой numpy равен 1.16.3, поэтому я вернулся к 1.16.1. Нажмите + и введите numpy в поиске, отметьте «указать версию»: 1.16.1 и выберите -> установить пакет.

Wissam
источник
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'.

Это также привело к ошибке allow_pickle при попытке загрузить набор данных imdb из keras

Я попытался использовать следующее решение, которое отлично работало, но мне приходилось делать это в каждом отдельном проекте, в котором я импортировал 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-nightly.

!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)
Джеймс
источник
0

Самый простой способ изменить imdb.pyнастройки , allow_pickle=Trueчтобы np.loadв строке , где imdb.pyкидает ошибку.

Насиф Имтиаз Охи
источник