【问题标题】:How to fix 'Object arrays cannot be loaded when allow_pickle=False' for imdb.load_data() function?如何修复 imdb.load_data() 函数的“allow_pickle=False 时无法加载对象数组”?
【发布时间】:2019-09-17 08:05:54
【问题描述】:

我正在尝试使用 Google Colab 中的 IMDb 数据集来实现二进制分类示例。我以前实现过这个模型。但是几天后我再次尝试执行此操作时,它为 load_data() 函数返回了 value error: 'Object arrays cannot be loaded when allow_pickle=False'

我已经尝试解决这个问题,参考了类似问题的现有答案:How to fix 'Object arrays cannot be loaded when allow_pickle=False' in the sketch_rnn algorithm。 但事实证明,仅仅添加一个 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

【问题讨论】:

  • 这个错误是什么意思?
  • @CharlieParker 显然在 numpy.load() 函数中添加了一个参数。以前是 np.load(path) ,现在是 np.load(path, boolean) 默认情况下,布尔值 (allow_pickle) 为 false
  • 谢谢!但这是否意味着 numpy 现在在保存时未经我的许可为我腌制东西?!诡异的!我查看了np.savez 文档,但没有提到酸洗,所以我不知道它是如何一开始就知道我保存的东西是 Pytorch 的东西,而不仅仅是 numpy ......奇怪!如果您知道发生了什么,请与我们分享 :)
  • 在遇到同样的问题后,我认为这完全取决于您要保存到 .npz 的 什么。如果您要保存内置类型,则无需酸洗。但是,如果您编写一个对象,python/numpy 将腌制它(即序列化它)。我想这会带来安全风险,因此后来的 numpy 版本不再允许它成为默认值......不过只是一种预感。

标签: python numpy keras


【解决方案1】:

这是强制imdb.load_data 允许pickle 的技巧,在您的笔记本中替换此行:

(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 可能以不同的名称导入,或者根本不导入...
  • 对我帮助很大
  • 收到错误TypeError: &lt;lambda&gt;() got multiple values for keyword argument 'allow_pickle'
  • 关键字参数多值问题已在stackoverflow.com/a/58586450/5214998中解决
【解决方案2】:

这个问题仍然存在于 keras git 上。我希望它尽快得到解决。 在此之前,请尝试将您的 numpy 版本降级到 1.16.2。这似乎解决了问题。

!pip install numpy==1.16.1
import numpy as np

这个版本的numpy默认值allow_pickleTrue

【讨论】:

  • 我会使用 MappaGnosis 的解决方案,而不是降级 numpy 版本:对我来说,使用版本 dance 是最后的手段!
  • 1.16.4 也有问题
  • 谢谢@kensai。有谁知道这是否在 numpy 1.17 中得到解决?
  • 在 numpy 1.18 中仍然存在这个问题。我不得不切换到 numpy 1.16.1,现在它解决了。谢谢。
  • 从 1.16 到 1.17 没有太大变化。这是最有帮助的答案。
【解决方案3】:

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

np.load(path, allow_pickle=True)

【讨论】:

  • 我观察到允许 pickle 更改数组。保存之前和加载之后的 .npy 数组在尝试使用 np.array_equal 断言相等时抛出异常
【解决方案4】:

按照 GitHub 上的这个issue,官方的解决方案是编辑 imdb.py 文件。这个修复对我来说效果很好,不需要降级 numpy。在tensorflow/python/keras/datasets/imdb.py 找到 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:

更改的原因是为了防止 Python 等价于腌制文件中的 SQL 注入。上面的更改只会影响 imdb 数据,因此您可以在其他地方保留安全性(通过不降级 numpy)。

【讨论】:

  • 如我所说,我使用的是 Colab,如何更改 imdb.py 文件?
  • 这不是 Colab 问题,因为 IMDB 是在您第一次引用它时在本地下载的。因此,您的计算机上的某处将有一个本地副本(尝试上面建议的路径 - 或者,如果您为 Colab 设置目录,请先尝试那里),然后只需在任何 IDE 甚至文本编辑器中打开 imdb.py 文件即可进行更改(我使用 Notepad ++ 编辑了在 Jupyter 中工作时下载的 imdb.py 文件 - 所以环境与 ​​Colab 非常相似!)。
  • 适合我的解决方案是 > np.load(data_path, encoding='latin1',allow_pickle=True)
  • 这是我使用的解决方案,因为在接受的答案中弄乱版本(尤其是 numpy)是我尽量避免的。这也更加pythonic,因为它明确地解决了问题。 (还要注意最新版本的 Keras,在 github,实际上包含了这个修复)
【解决方案5】:

在我的情况下与:

np.load(path, allow_pickle=True)

【讨论】:

    【解决方案6】:

    我认为 cheez (https://stackoverflow.com/users/122933/cheez) 的回答是最简单有效的。我会详细说明一下,这样它就不会在整个会话期间修改 numpy 函数。

    我的建议如下。我正在使用它从 keras 下载 reuters 数据集,该数据集显示相同类型的错误:

    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)
    

    【讨论】:

    • 你能解释一下这里发生了什么吗?
    • 我无法加载 Keras 数据集。我在互联网上搜索并找到了一个解决方案,说我应该编辑 de imdb.py 文件,其他人指出 numpy 安装的更改(如这里)或将 Tensorflow 更改为开发版本。我遇到了奶酪解决方案。恕我直言,这是最简单、最有效的方法。
    • @Kanad - lambda 是一个匿名函数。 Gustavo 为 np.load 创建了一个函数增强,使用增强版本,然后设置回默认值。
    【解决方案7】:

    您可以尝试更改标志的值

    np.load(training_image_names_array,allow_pickle=True)
    

    【讨论】:

    • 太棒了。它的工作。这应该是公认的答案。
    【解决方案8】:

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

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

    • 关闭并重新打开笔记本

    【讨论】:

    • 谢谢,这就是我搜索的内容。顺便说一句,看起来 1.16.2 是最新版本,allow_pickle=True 是默认值。
    【解决方案9】:

    在 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”获得了多个值

    我使用解决方案here解决了这个问题:

    【讨论】:

      【解决方案10】:

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

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

      【讨论】:

        【解决方案11】:

        对我有用

                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
        

        【讨论】:

        • 一些上下文解释了为什么您的解决方案有效。 (来自评论)。
        【解决方案12】:

        我发现 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 版本的不兼容造成的更大问题,并且可能导致许多其他隐藏的错误或问题。

        【讨论】:

          【解决方案13】:

          answer of @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
          

          【讨论】:

            【解决方案14】:

            我降落在这里,尝试了你的方法,但无法弄清楚。

            我实际上是在编写一个预先给定的代码

            pickle.load(path)
            

            被使用了,所以我将其替换为

            np.load(path, allow_pickle=True)
            

            【讨论】:

              【解决方案15】:

              使用这个

               from tensorflow.keras.datasets import imdb
              

              而不是这个

               from keras.datasets import imdb
              

              【讨论】:

                【解决方案16】:

                如果您尝试使用 np.save 保存 numpy 数组的 python 列表并使用 np.load 加载,也会发生错误。我只是为了让 googler 看看这不是问题所在。如果列表确实是您要保存和加载的内容,也可以使用 allow_pickle=True 解决问题。

                【讨论】:

                  【解决方案17】:

                  当您使用 Torchvision==0.7.0 的以前版本的 Torch(如 1.6.0)时会出现此错误, 您可以通过以下命令检查您的手电筒版本:

                  import tensorflow
                  print(tensorflow.__version__)
                  

                  此错误已在较新版本的 Torch 中得到解决。

                  您可以通过在 np.load() 中进行以下更改来消除此错误

                  np.load(somepath, allow_pickle=True)
                  

                  allow_pickle=True 会解决它

                  【讨论】:

                    【解决方案18】:

                    [快速解决方案]我通过在调用 np.load 时修改“allow_pickle”来实现它:

                    labels = np.load("标签",allow_pickle=True)

                    【讨论】:

                      【解决方案19】:

                      有很多答案,但要真正理解这个问题,我建议您接下来尝试简单的示例:

                      a=np.array([[1, 2, 3], [4, 5, 6]])
                      # Object array
                      b={'data':'somet',
                         'data_2':'defin'}
                      #Save arrays into file
                      np.savez('/content/123.npz', a=a, b=b)
                      #Load file into data variable
                      data = np.load('/content/123.npz')
                      print(data['b'])
                      

                      这个简单的例子已经重现了错误。问题是你已经在 npz 中序列化了字典,

                      现在只需尝试将带有 np.load 的行替换为:

                      data = np.load('/content/123.npz',allow_pickle=True)
                      

                      而且它有效!示例来源:fix object arrays cannot be loaded when allow_pickle=False

                      【讨论】:

                        【解决方案20】:

                        是的,安装以前版本的 numpy 解决了这个问题。

                        对于那些使用 PyCharm IDE 的人:

                        在我的 IDE (Pycharm) 中,File->Settings->Project Interpreter:我发现我的 numpy 是 1.16.3,所以我恢复到 1.16.1。 单击 + 并在搜索中键入 numpy,勾选“指定版本”:1.16.1 并选择--> 安装包。

                        【讨论】:

                          【解决方案21】:

                          我通常不发布这些东西,但这非常烦人。混淆来自于一些 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)
                          

                          【讨论】:

                            【解决方案22】:

                            最简单的方法是将imdb.py 设置allow_pickle=True 更改为np.loadimdb.py 引发错误的行。

                            【讨论】:

                              【解决方案23】:

                              我遇到了同样的问题,这里是错误行

                              File "/usr/lib/python3/dist-packages/numpy/lib/npyio.py", line 260, in __getitem__
                              

                              所以我通过更新“npyio.py”文件来解决这个问题。 在 npyio.py 第 196 行为 allow_pickle 赋值,所以我将此行更新为

                              self.allow_pickle = True
                              

                              【讨论】:

                                【解决方案24】:

                                代替

                                from keras.datasets import imdb
                                

                                使用

                                from tensorflow.keras.datasets import imdb
                                
                                top_words = 10000
                                ((x_train, y_train), (x_test, y_test)) = imdb.load_data(num_words=top_words, seed=21)
                                

                                【讨论】:

                                  【解决方案25】:

                                  Tensorflow 在 tf-nightly 版本中有一个修复。

                                  !pip install tf-nightly
                                  

                                  当前版本是“2.0.0-dev20190511”。

                                  【讨论】:

                                    【解决方案26】:

                                    如果您正在加载像 npz 格式这样的压缩存储文件,那么下面的代码会很好

                                    np.load(path, allow_pickle=True)
                                    

                                    确保在指定路径时,用单引号括起来,allow_pickle = True 不应出现在任何引号中。

                                    【讨论】:

                                      猜你喜欢
                                      • 2022-01-24
                                      • 2019-09-13
                                      • 2020-05-12
                                      • 1970-01-01
                                      • 2021-07-30
                                      • 1970-01-01
                                      • 2020-08-13
                                      • 1970-01-01
                                      • 1970-01-01
                                      相关资源
                                      最近更新 更多