在 Python2和3之间 numpy 数组的 Pickle 不兼容性

我尝试用这个程序在 Python 3.2中加载 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中解码 pickle 文件,并重新编码它。因此,我在 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)

但是,它给我的错误和以前一样。我如何让这个工作?


这是加载 MNIST 数据集的更好方法。

106506 次浏览

由于移动到 unicode,它看起来像是处于2.x 和3.x 之间的 pickle 中的 存在一些兼容性问题。您的文件似乎是用 python 2.x 腌制的,在3.x 中解码可能很麻烦。

我建议使用 python 2.x 将其解压缩,并保存为一种格式,以便在所使用的两个版本中都能更好地使用。

这看起来像是某种不相容。它试图加载一个“ binding”对象,假定它是 ASCII,而在本例中它是二进制数据。如果这是 Python3 unpickler 中的一个 bug,或者 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)

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

如果在 python3中遇到这个错误,那么,这可能是 python2和 python3之间的不兼容性问题,对我来说,解决方案是使用 latin1编码的 load:

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

这似乎是 Python2和 Python3之间的不兼容性问题。我试过加载 MNIST 数据集

    train_set, valid_set, test_set = pickle.load(file, encoding='iso-8859-1')

而且它在 Python 3.5.2中是可行的

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

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)

有比腌菜更快更容易的泡菜。 我试图在 pickle dump 中保存和读取它,但是在读取的过程中出现了很多问题,浪费了一个小时,而且仍然没有找到解决方案,尽管我正在使用自己的数据创建一个聊天机器人。

vec_xvec_y是数字数组:

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

然后您只需读取它并执行操作:

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

试试:

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 _ import、编码和错误,用于控制对 Python 2生成的 pickle 流的兼容性支持。

如果 fix _ import 为 True,pickle 将尝试将旧的 Python2名称映射到 Python3中使用的新名称。

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