Ketidakcocokan acar array numpy antara Python 2 dan 3

163

Saya mencoba memuat dataset MNIST yang ditautkan di sini di Python 3.2 menggunakan program ini:

import pickle
import gzip
import numpy


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

Sayangnya, itu memberi saya kesalahan:

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)

Saya kemudian mencoba men-decode file acar dengan Python 2.7, dan menyandikannya kembali. Jadi, saya menjalankan program ini dengan 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.

Itu berjalan tanpa kesalahan, jadi saya memutar ulang program ini dengan 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)

Namun, itu memberi saya kesalahan yang sama seperti sebelumnya. Bagaimana saya membuatnya bekerja?


Ini adalah pendekatan yang lebih baik untuk memuat dataset MNIST.

Neil G
sumber
ada jeda kompatibilitas antara 2,7 dan 3.x. terutama string vs unicode. Dan memilih objek numpy mengharuskan kedua sistem memuat modul numpy tetapi modul-modul itu berbeda. Maaf saya tidak punya jawaban tetapi ini mungkin tidak bisa dilakukan dan mungkin tidak disarankan. Jika ini adalah hal besar (gzip), mungkin hdf5 dengan pytables ??
Phil Cooper
@ PhilCooper: Terima kasih, komentar Anda (posting ini sebagai jawaban?) Memberi saya petunjuk yang benar Saya bisa menggunakan hdf5, tetapi sepertinya sulit untuk dipelajari, jadi saya menggunakan numpy.save/load dan ini berhasil.
Neil G
H5py sangat mudah digunakan, hampir pasti jauh lebih mudah daripada memecahkan masalah kompatibilitas samar-samar dengan acar numpy array.
DaveP
Anda mengatakan Anda "menjalankan program ini di bawah Python 2.7". OK tapi apa yang Anda jalankan di bawah 3.2? :-) Sama?
Lennart Regebro
@LennartRegebro: Setelah menjalankan program kedua yang mengacaukan array, saya menjalankan program pertama (mengganti nama file mnistx.pkl.gz) dengan Python 3.2. Itu tidak berhasil, yang saya pikir menggambarkan semacam ketidakcocokan.
Neil G

Jawaban:

141

Ini sepertinya semacam ketidakcocokan. Ia mencoba memuat objek "binstring", yang dianggap ASCII, sedangkan dalam hal ini adalah data biner. Jika ini adalah bug di Python 3 unpickler, atau "penyalahgunaan" pickler oleh numpy, saya tidak tahu.

Ini adalah solusi untuk masalah ini, tetapi saya tidak tahu seberapa berartinya data saat ini:

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)

Melepas pemasangannya di Python 2 lalu repickling hanya akan membuat masalah yang sama lagi, jadi Anda perlu menyimpannya dalam format lain.

Lennart Regebro
sumber
211
Anda dapat menggunakan pickle.load(file_obj, encoding='latin1')(setidaknya dalam Python 3.3). Ini sepertinya berhasil.
Tom Aldcroft
7
Bagi mereka yang menggunakan load numpy dan menghadapi masalah yang sama: dimungkinkan untuk lulus encoding di sana juga:np.load('./bvlc_alexnet.npy', encoding='latin1')
Serj Zaharchenko
Ini bekerja untuk saya ketika menambahkan encoding='latin1'gagal. Terima kasih!
Guillem Cucurull
130

Jika Anda mendapatkan kesalahan ini di python3, maka, itu bisa menjadi masalah ketidakcocokan antara python 2 dan python 3, bagi saya solusinya adalah loaddengan latin1pengkodean:

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

Tampaknya menjadi masalah ketidakcocokan antara Python 2 dan Python 3. Saya mencoba memuat dataset MNIST

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

dan itu berhasil untuk Python 3.5.2

Steve
sumber
7

Sepertinya ada beberapa masalah kompatibilitas di acar antara 2.x dan 3.x karena pindah ke unicode. File Anda tampaknya acar dengan python 2.x dan mendekodekannya dalam 3.x bisa menyusahkan.

Saya sarankan untuk mengurungkannya dengan python 2.x dan menyimpan ke format yang memainkan lebih baik di dua versi yang Anda gunakan.

John Lyon
sumber
2
Itulah yang saya coba lakukan. Format mana yang Anda rekomendasikan?
Neil G
5
Saya pikir masalahnya mungkin encoding dtype numpy, yang mungkin berupa string. Bagaimanapun, saya akhirnya menggunakan numpy.save/load untuk menjembatani kesenjangan antara python 2 dan 3, dan ini berhasil.
Neil G
7

Saya baru saja menemukan potongan ini. Semoga ini bisa membantu memperjelas masalah kompatibilitas.

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
sumber
Pertimbangkan untuk menambahkan lebih banyak informasi yang menguatkan. Bagaimana cara mengatasi masalah ini?
Tom Aranda
@serge yang membantu, mohon penjelasan pada jawabannya
Sarath Sadasivan Pillai
6

Mencoba:

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

Dari dokumentasi pickle.loadmetode:

Argumen kata kunci opsional adalah fix_import, pengodean dan kesalahan, yang digunakan untuk mengontrol dukungan kompatibilitas untuk acar aliran yang dihasilkan oleh Python 2.

Jika fix_import Benar, acar akan mencoba memetakan nama Python 2 lama ke nama baru yang digunakan dalam Python 3.

Pengkodean dan kesalahan memberi tahu acar bagaimana cara mendekode instance string 8-bit yang dibuat oleh Python 2; default ini untuk 'ASCII' dan 'ketat', masing-masing. Pengkodean dapat berupa 'byte' untuk membaca instance string 8-bit ini sebagai objek byte.

Manish Kumbhare
sumber
0

Ada hickle yang lebih cepat dari pada acar dan lebih mudah. Saya mencoba menyimpan dan membacanya di acar dump tetapi ketika membaca ada banyak masalah dan membuang satu jam dan masih tidak menemukan solusi meskipun saya sedang mengerjakan data saya sendiri untuk membuat chatbot.

vec_xdan vec_yarray numpy:

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

Kemudian Anda baru saja membacanya dan melakukan operasi:

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