如何修复imdb.load_data()函数的“ allow_pickle = False时无法加载对象数组”?


113

我正在尝试使用Google Colab中的IMDb数据集实现二进制分类示例。我以前已经实现了此模型。但是,几天后我再次尝试执行此操作时,它返回一个值错误:对于load_data()函数,当allow_pickle = False时无法加载对象数组。

我已经尝试解决此问题,请参考一个类似问题的现有答案:如何修复sketch_rnn算法中的“当allow_pickle = False时无法加载对象数组”, 但事实证明,仅添加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
Kanad19'7

谢谢!但这是否意味着numpy现在在保存时未经我的允许就为我腌制东西?奇怪的!我看了看np.savez文档,但是没有提到酸洗,所以我不知道它最初是怎么知道我保存的东西是Pytorch的东西,而不仅仅是numpy ...很奇怪!如果您知道与我们分享了什么:)
查理·帕克

运行到同样的问题后,我的信念是,它完全取决于什么你都保存到一个.npz。如果要保存内置类型,则不进行酸洗。但是,如果您编写一个对象,则python / numpy会将其腌制(即序列化)。我想这会带来安全风险,因此更高版本的numpy已停止允许其为默认值……不过这只是预感。
罗伯特·拉格

Answers:


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的可以根据不同的名称进口,或者根本没有进口...
克里斯托夫

这对我有很大帮助
-staticor

7
遇到错误TypeError: <lambda>() got multiple values for keyword argument 'allow_pickle'
-Hayat

1
为关键字参数多个值一直是问题解决stackoverflow.com/a/58586450/5214998
萨贾德Norouzi

91

这个问题仍然存在于keras git上。我希望它能尽快解决。在此之前,请尝试将numpy版本降级为1.16.2。看来解决了问题。

!pip install numpy==1.16.1
import numpy as np

此版本的numpy的默认值为allow_pickleas True


4
我将使用MappaGnosis的解决方案,而不是降级numpy版本:对我而言,纠缠于版本舞蹈是不得已的方法!
eric

2
1.16.4有问题,以及
剑圣

谢谢@kensai。有谁知道这是否在numpy 1.17中解决了?
nsheff

在numpy 1.18中仍然存在此问题。我不得不切换到numpy 1.16.1,现在解决了。谢谢。
BC史密斯,

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行:

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

进行更改的原因是为了防止在腌制文件中使用与SQL注入等效的Python。上面的更改仅会影响imdb数据,因此您将安全性保留在其他位置(不降低numpy的级别)。


1
就像我说的那样,我正在使用Colab,如何在imdb.py文件中进行更改?
卡纳德

这不是Colab问题,因为IMDB是在您首次引用它时在本地下载的。因此,您的计算机上将有一个本地副本(尝试上面建议的路径-或者,如果您为Colab设置了目录,请首先尝试在那里),然后只需在任何IDE甚至文本编辑器中打开imdb.py文件即可。进行更改(我使用记事本++编辑了在Jupyter中工作时下载的imdb.py文件-这与Colab非常相似!)。
MappaGnosis

对我有用的解决方案是> np.load(data_path,encoding ='latin1',allow_pickle = True)
豪尔赫·桑托斯·尼尔

这是我使用的解决方案,因为在版本中(尤其是numpy),就像在已接受的答案中那样,是我要避免的事情。这也更具Pythonic性,因为它明确地解决了问题。(请注意github上的Keras的最新版本实际上包含了此修复程序)
eric

35

我只是使用allow_pickle = True作为np.load()的参数,它对我有用。


我观察到允许泡菜更改数组。尝试使用np.array_equal进行相等性声明时,保存前和加载后的.npy数组引发异常
。yasht


12

我认为cheez的答案(https://stackoverflow.com/users/122933/cheez)是最简单,最有效。我将对其进行详细说明,以便在整个会话期间都不会修改numpy函数。

我的建议如下。我正在使用它从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更改为开发版本。我遇到过cheez解决方案。恕我直言,这是最简单,最有效的方法。
Gustavo Mirapalheta,

1
@Kanad-lambda是一个匿名函数。Gustavo为np.load创建了功能增强,使用了增强版本,然后将其设置回默认值。
EngrStudent


4

上面列出的解决方案都不对我有用:我使用python 3.7.3运行anaconda。对我有用的是

  • 从Anaconda powershell运行“ conda install numpy == 1.16.1”

  • 关闭并重新打开笔记本


谢谢,这就是我所寻找的。顺便说一句,看起来1.16.2是最新版本,其中allow_pickle=True是默认值。
马捷Račinský

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并选择->安装软件包。


2

找到imdb.py的路径,然后将标志添加到np.load(path,... flag ...)

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

尝试从keras加载imdb数据集时,这还会导致allow_pickle错误

我尝试使用以下效果很好的解决方案,但是我必须在导入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

我通常不发布这些东西,但这太烦人了。混淆来自某些Keras imdb.py文件已经更新的事实:

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.