Python 2和3之间numpy数组的pickle不兼容

Posted

技术标签:

【中文标题】Python 2和3之间numpy数组的pickle不兼容【英文标题】:Pickle incompatibility of numpy arrays between Python 2 and 3 【发布时间】:2012-07-03 13:58:57 【问题描述】:

我正在尝试使用此程序在 Python 3.2 中加载链接 here 的 MNIST 数据集:

import pickle
import gzip
import numpy


with gzip.open('mnist.pkl.gz', 'rb') as f:
    l = list(pickle.load(f))
    print(l)

不幸的是,它给了我错误:

Traceback (most recent call last):
   File "mnist.py", line 7, in <module>
     train_set, valid_set, test_set = pickle.load(f)
UnicodeDecodeError: 'ascii' codec can't decode byte 0x90 in position 614: ordinal not in range(128)

然后我尝试在 Python 2.7 中解码腌制文件,然后重新编码。所以,我在 Python 2.7 中运行了这个程序:

import pickle
import gzip
import numpy


with gzip.open('mnist.pkl.gz', 'rb') as f:
    train_set, valid_set, test_set = pickle.load(f)

    # Printing out the three objects reveals that they are
    # all pairs containing numpy arrays.

    with gzip.open('mnistx.pkl.gz', 'wb') as g:
        pickle.dump(
            (train_set, valid_set, test_set),
            g,
            protocol=2)  # I also tried protocol 0.

它运行没有错误,所以我在 Python 3.2 中重新运行了这个程序:

import pickle
import gzip
import numpy

# note the filename change
with gzip.open('mnistx.pkl.gz', 'rb') as f:
    l = list(pickle.load(f))
    print(l)

但是,它给了我和以前一样的错误。我该如何让它发挥作用?


This is a better approach for loading the MNIST dataset.

【问题讨论】:

2.7 和 3.x 之间存在兼容性中断。特别是字符串与 unicode。并且选择一个 numpy 对象需要两个系统都加载 numpy 模块,但这些模块是不同的。抱歉,我没有答案,但这可能是不可行的,也可能是不可取的。如果这是大事(gzip),也许 hdf5 和 pytables?? @PhilCooper:谢谢,您的评论(将其作为答案发布?)让我找到了正确的答案。我本可以使用 hdf5,但学习起来似乎很复杂,所以我使用了 numpy.save/load 并且这很有效。 h5py 使用起来非常简单,几乎可以肯定比使用酸洗 numpy 数组解决模糊的兼容性问题要容易得多。 你说你“在 Python 2.7 下运行这个程序”。好的,但是你在 3.2 下运行了什么? :-) 一样吗? @LennartRegebro:在运行第二个处理数组的程序后,我在 Python 3.2 中运行了第一个程序(替换文件名 mnistx.pkl.gz)。它不起作用,我认为这说明了某种不兼容。 【参考方案1】:

这似乎是某种不兼容。它试图加载一个“binstring”对象,该对象被假定为 ASCII,而在这种情况下它是二进制数据。如果这是 Python 3 unpickler 中的错误,或者是 numpy 对pickler 的“滥用”,我不知道。

这是一种解决方法,但我不知道此时数据有多大意义:

import pickle
import gzip
import numpy

with open('mnist.pkl', 'rb') as f:
    u = pickle._Unpickler(f)
    u.encoding = 'latin1'
    p = u.load()
    print(p)

在 Python 2 中取消腌制然后重新腌制只会再次产生相同的问题,因此您需要将其保存为另一种格式。

【讨论】:

你可以使用pickle.load(file_obj, encoding='latin1')(至少在 Python 3.3 中)。这似乎有效。 对于那些使用 numpy load 并面临类似问题的人:也可以在那里传递编码:np.load('./bvlc_alexnet.npy', encoding='latin1') 添加 encoding='latin1' 失败时,这对我有用。谢谢! 就我而言,只有pickle.load(open(file_path, "rb"), encoding="latin1") 有效。【参考方案2】:

如果您在 python3 中遇到此错误,则可能是 python 2 和 python 3 之间的不兼容问题,对我来说,解决方案是 loadlatin1 编码:

pickle.load(file, encoding='latin1')

【讨论】:

【参考方案3】:

这似乎是 Python 2 和 Python 3 之间的不兼容问题。我尝试用

加载 MNIST 数据集
    train_set, valid_set, test_set = pickle.load(file, encoding='iso-8859-1')

它适用于 Python 3.5.2

【讨论】:

【参考方案4】:

由于迁移到 unicode,在 2.x 和 3.x 之间的 pickle 中看起来像 there are some compatablility issues。你的文件似乎是用 python 2.x 腌制的,在 3.x 中解码它可能很麻烦。

我建议用 python 2.x 解开它并保存为在您使用的两个版本中播放得更好的格式。

【讨论】:

这就是我想要做的。您推荐哪种格式? 我认为问题可能是编码 numpy dtype,它可能是一个字符串。无论如何,我最终使用 numpy.save/load 来弥补 python 2 和 3 之间的差距,这很有效。【参考方案5】:

我只是偶然发现了这个 sn-p。希望这有助于澄清兼容性问题。

import sys

with gzip.open('mnist.pkl.gz', 'rb') as f:
    if sys.version_info.major > 2:
        train_set, valid_set, test_set = pickle.load(f, encoding='latin1')
    else:
        train_set, valid_set, test_set = pickle.load(f)

【讨论】:

考虑添加更多放大信息。这如何解决问题? @serge 有帮助,请解释答案【参考方案6】:

试试:

l = list(pickle.load(f, encoding='bytes')) #if you are loading image data or 
l = list(pickle.load(f, encoding='latin1')) #if you are loading text data

来自pickle.load方法的文档:

可选的关键字参数是fix_imports、encoding和errors,用于控制对Python 2生成的pickle流的兼容性支持。

如果 fix_imports 为 True,pickle 将尝试将旧的 Python 2 名称映射到 Python 3 中使用的新名称。

编码和错误告诉 pickle 如何解码 Python 2 腌制的 8 位字符串实例;这些默认分别为“ASCII”和“严格”。编码可以是“字节”,以将这些 8 位字符串实例读取为字节对象。

【讨论】:

【参考方案7】:

hickle 比 pickle 更快更容易。 我试图在泡菜转储中保存和阅读它,但是在阅读时出现了很多问题并浪费了一个小时,尽管我正在处理自己的数据以创建聊天机器人,但仍然没有找到解决方案。

vec_xvec_y 是 numpy 数组:

data=[vec_x,vec_y]
hkl.dump( data, 'new_data_file.hkl' )

然后你只需阅读它并执行操作:

data2 = hkl.load( 'new_data_file.hkl' )

【讨论】:

以上是关于Python 2和3之间numpy数组的pickle不兼容的主要内容,如果未能解决你的问题,请参考以下文章

python数据分析 python numpy--数组--运算,切片和索引

将字典保存到文件(numpy 和 Python 2/3 友好)

NumPy 数组和 python 列表有啥区别? [复制]

Python:如何以通道,行,cols格式保存图像?

NumPy基础-数组与向量化计算

numpy中数组之间的区别