web-dev-qa-db-ja.com

Python 2と3の間のnumpy配列のピクルの非互換性

このプログラムを使用して、リンクされたMNISTデータセットをロードしようとしています here in Python 3.2:

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)

ただし、以前と同じエラーが発生しました。これを機能させるにはどうすればよいですか?


これはMNISTデータセットをロードするためのより良いアプローチです。

143
Neil G

これはある種の非互換性のようです。 ASCIIと想定される「binstring」オブジェクトをロードしようとしていますが、この場合はバイナリデータです。これが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でそれをunpickleしてから再びickickすると同じ問題が再び発生するだけなので、別の形式で保存する必要があります。

120
Lennart Regebro

Python3でこのエラーが発生した場合、python 2とpython 3の間の非互換性の問題である可能性があります。私にとっては、loadlattin1エンコード:

pickle.load(file, encoding='latin1')
97
Tshilidzi Mudau

Python 2とPython 3の間の非互換性の問題のようです。MNISTデータセットを

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

Python 3.5.2で機能しました

10
Steve

互換性の問題がある のように見えます。Unicodeへの移行により、2.xと3.xの間にピクルスがあります。ファイルはpython 2.xで漬けられているように見え、3.xでデコードするのは面倒です。

python 2.xでそれを選択解除し、使用している2つのバージョンでより適切に再生される形式に保存することをお勧めします。

7
jozzas

このスニペットを見つけました。これが互換性の問題を明らかにするのに役立つことを願っています。

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)
6
serge

試してください:

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で使用されている新しい名前にマッピングしようとします。

エンコードとエラーは、Python 2によってピクルされた8ビット文字列インスタンスをデコードする方法をpickleに指示します。これらはそれぞれ「ASCII」と「strict」にデフォルト設定されています。これらの8ビット文字列インスタンスをバイトオブジェクトとして読み取るために、エンコーディングを「バイト」にすることができます。

2
Manish Kumbhare

ピクルスよりも速くて簡単なヒクルがあります。私はそれをピクルスダンプに保存して読んでみましたが、読んでいる間に多くの問題があり、1時間を無駄にし、チャットボットを作成するために自分のデータに取り組んでいたにもかかわらず解決策が見つかりませんでした。

vec_xvec_yはnumpy配列です:

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

次に、それを読んで操作を実行します。

data2 = hkl.load( 'new_data_file.hkl' )
0
KS HARSHA