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


163

このプログラムを使用して、ここにリンクされているMNISTデータセットを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データセットをロードするためのより良いアプローチです。


2.7と3.xの間には互換性の問題があります。特に文字列とユニコード。また、numpyオブジェクトを選択するには、両方のシステムでnumpyモジュールをロードする必要がありますが、これらのモジュールは異なります。申し訳ありませんが答えはありませんが、これは実行できない可能性があり、おそらくお勧めできません。これが大きなもの(gzip)の場合、pytablesを使用したhdf5?
Phil Cooper

@PhilCooper:ありがとう、あなたのコメント(これを回答として投稿しますか?)が正しい答えを教えてくれました。hdf5を使用することもできましたが、学ぶのは複雑に思えたので、numpy.save / loadを使用してこれでうまくいきました。
ニールG

h5pyの使い方は非常に簡単で、numpy配列のピクル化に関するあいまいな互換性の問題を解決するよりもはるかに簡単です。
DaveP

「このプログラムをPython 2.7で実行した」と言います。わかりましたが、3.2では何を実行しましたか?:-) 同じ?
Lennart Regebro 2012

@LennartRegebro:配列をピクルする2番目のプログラムを実行した後、最初のプログラム(ファイル名mnistx.pkl.gzに置き換えて)をPython 3.2で実行しました。それはうまくいきませんでした。それはある種の非互換性を示していると思います。
Neil G

回答:


141

これはある種の非互換性のようです。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してからrepickleしても同じ問題が再び発生するだけなので、別の形式で保存する必要があります。


211
使用できますpickle.load(file_obj, encoding='latin1')(少なくともPython 3.3では)。これは動作するようです。
トムアルドクロフト2014年

7
:そこにもエンコード合格することが可能である:numpyの負荷を使用して、同様の問題に直面しています人のためにnp.load('./bvlc_alexnet.npy', encoding='latin1')
Serj Zaharchenko

これは、追加にencoding='latin1'失敗したときに私にとってはうまくいきました。ありがとう!
Guillem Cucurull

130

あなたがのpython3でこのエラーを取得している場合、それは、Python 2とPython 3の間の非互換性の問題である可能性があり、私のために解決策をしたことloadlatin1エンコードします。

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

16

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

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

そしてそれはPython 3.5.2のために働きました


7

Unicodeへの移行により、2.xと3.xの間のpickleに互換性の問題があるようです。あなたのファイルはpython 2.xでピクルされているようで、3.xでそれをデコードするのは面倒かもしれません。

私はそれをpython 2.xでunpickleし、使用している2つのバージョン間でよりうまく再生できるフォーマットに保存することをお勧めします。


2
それが私がやろうとしていたことです。どのフォーマットをお勧めしますか?
ニールG

5
問題は、文字列である可能性があるnumpy dtypeをエンコードしていた可能性があります。いずれにしても、私はnumpy.save/loadを使用してpython 2と3の間のギャップを埋めることになり、これはうまくいきました。
ニールG

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)

増幅情報をさらに追加することを検討してください。これはどのように問題を解決しますか?
トム・アランダ

@serge助けてくれました、答えを説明してください
Sarath Sadasivan Pillai

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メソッドのドキュメントから:

オプションのキーワード引数は、Python 2によって生成されたピクルストリームの互換性サポートを制御するために使用されるfix_imports、エンコーディング、およびエラーです。

fix_importsがTrueの場合、pickleは古いPython 2の名前をPython 3で使用されている新しい名前にマッピングしようとします。

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


0

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

vec_xそしてvec_y、numpy配列です:

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

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

data2 = hkl.load( 'new_data_file.hkl' )
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.