176

I am trying to load the MNIST dataset linked here in Python 3.2 using this program:

import pickle
import gzip
import numpy


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

Unfortunately, it gives me the error:

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)

I then tried to decode the pickled file in Python 2.7, and re-encode it. So, I ran this program in 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.

It ran without error, so I reran this program in 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)

However, it gave me the same error as before. How do I get this to work?


This is a better approach for loading the MNIST dataset.

4

7 回答 7

153

这似乎是某种不兼容。它试图加载一个“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 中将其取消腌制然后重新腌制只会再次产生相同的问题,因此您需要将其保存为另一种格式。

于 2012-07-03T15:48:53.900 回答
150

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

pickle.load(file, encoding='latin1')
于 2016-12-28T17:17:30.340 回答
16

这似乎是 Python 2 和 Python 3 之间的不兼容问题。我尝试加载 MNIST 数据集

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

它适用于 Python 3.5.2

于 2017-02-03T03:49:37.137 回答
7

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

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

于 2012-07-03T06:57:55.663 回答
7

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

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)
于 2017-10-28T17:12:29.747 回答
7

尝试:

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 位字符串实例读取为字节对象。

于 2018-11-28T21:28:20.717 回答
0

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

vec_x并且vec_y是 numpy 数组:

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

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

data2 = hkl.load( 'new_data_file.hkl' )
于 2018-07-13T20:18:23.127 回答