Pickle không tương thích của mảng numpy giữa Python 2 và 3


163

Tôi đang cố tải tập dữ liệu MNIST được liên kết ở đây trong Python 3.2 bằng chương trình này:

import pickle
import gzip
import numpy


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

Thật không may, nó cho tôi lỗi:

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)

Sau đó, tôi đã cố gắng giải mã tập tin ngâm trong Python 2.7 và mã hóa lại nó. Vì vậy, tôi đã chạy chương trình này trong 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.

Nó chạy không có lỗi, vì vậy tôi chạy lại chương trình này trong 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)

Tuy nhiên, nó đã cho tôi lỗi tương tự như trước đây. Làm thế nào để tôi có được điều này để làm việc?


Đây là một cách tiếp cận tốt hơn để tải tập dữ liệu MNIST.


có các ngắt tương thích giữa 2.7 và 3.x. đặc biệt là chuỗi vs unicode. Và chọn một đối tượng numpy yêu cầu cả hai hệ thống tải mô-đun numpy nhưng các mô-đun đó là khác nhau. Xin lỗi tôi không có câu trả lời nhưng điều này có thể không thực hiện được và có lẽ là không nên. Nếu đây là những thứ lớn (gzip), có thể là hdf5 với pytables ??
Phil Cooper

@PhilCooper: Cảm ơn, nhận xét của bạn (đăng bài này dưới dạng câu trả lời?) Đã đưa tôi đến câu trả lời đúng. Tôi có thể đã sử dụng hdf5, nhưng nó có vẻ phức tạp để tìm hiểu, vì vậy tôi đã sử dụng numpy.save/load và điều này đã hoạt động.
Neil G

h5py rất đơn giản để sử dụng, gần như chắc chắn dễ dàng hơn nhiều sau đó giải quyết các vấn đề tương thích khó hiểu với các mảng khó khăn.
DaveP

Bạn nói rằng bạn "đã chạy chương trình này trong Python 2.7". OK nhưng bạn đã chạy gì dưới 3.2? :-) Giống nhau?
Lennart Regebro

@LennartRegebro: Sau khi chạy chương trình thứ hai chọn mảng, tôi đã chạy chương trình đầu tiên (thay thế tên tệp mnistx.pkl.gz) trong Python 3.2. Nó không hoạt động, mà tôi nghĩ minh họa một số loại không tương thích.
Neil G

Câu trả lời:


141

Điều này có vẻ như một số loại không tương thích. Đó là cố gắng tải một đối tượng "chuỗi", được coi là ASCII, trong trường hợp này là dữ liệu nhị phân. Nếu đây là một lỗi trong trình giải nén Python 3 hoặc "lạm dụng" trình chọn bởi numpy, tôi không biết.

Đây là một cái gì đó của một cách giải quyết, nhưng tôi không biết dữ liệu có ý nghĩa như thế nào tại thời điểm này:

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)

Giải nén nó trong Python 2 và sau đó lặp lại nó sẽ chỉ tạo ra cùng một vấn đề, vì vậy bạn cần lưu nó ở định dạng khác.


211
Bạn có thể sử dụng pickle.load(file_obj, encoding='latin1')(ít nhất là trong Python 3.3). Điều này dường như làm việc.
Tom Aldcroft

7
Đối với những người sử dụng tải numpy và đối mặt với vấn đề tương tự: cũng có thể chuyển mã hóa ở đó:np.load('./bvlc_alexnet.npy', encoding='latin1')
Serj Zaharchenko

Điều này làm việc cho tôi khi thêm encoding='latin1'thất bại. Cảm ơn!
Guillem Cucurull

130

Nếu bạn gặp lỗi này trong python3, thì đó có thể là sự cố không tương thích giữa python 2 và python 3, đối với tôi, giải pháp là loadvới latin1mã hóa:

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

16

Có vẻ như đây là sự cố không tương thích giữa Python 2 và Python 3. Tôi đã thử tải tập dữ liệu MNIST với

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

và nó đã làm việc cho Python 3.5.2


7

Có vẻ như có một số vấn đề tương thích trong dưa chua giữa 2.x và 3.x do việc chuyển sang unicode. Tập tin của bạn dường như được xử lý bằng python 2.x và giải mã nó trong 3.x có thể gây rắc rối.

Tôi khuyên bạn nên giải nén nó bằng python 2.x và lưu thành định dạng chơi độc đáo hơn trên hai phiên bản bạn đang sử dụng.


2
Đó là những gì tôi đã cố gắng làm. Bạn đề nghị định dạng nào?
Neil G

5
Tôi nghĩ rằng vấn đề có thể đã được mã hóa dtype numpy, có thể là một chuỗi. Trong mọi trường hợp, tôi đã kết thúc bằng cách sử dụng numpy.save/load để thu hẹp khoảng cách giữa python 2 và 3, và điều này đã hoạt động.
Neil G

7

Tôi chỉ vấp phải đoạn trích này. Hy vọng điều này sẽ giúp làm rõ vấn đề tương thích.

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)

Xem xét thêm thông tin khuếch đại. Làm thế nào để giải quyết vấn đề này?
Tom Aranda

@serge đã giúp, vui lòng giải thích cho câu trả lời
Sarath Sadasivan Pillai

6

Thử:

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

Từ tài liệu của pickle.loadphương pháp:

Các đối số từ khóa tùy chọn là fix_imports, mã hóa và lỗi, được sử dụng để kiểm soát hỗ trợ tương thích cho luồng dưa chua được tạo bởi Python 2.

Nếu fix_imports là True, Pickle sẽ cố gắng ánh xạ các tên Python 2 cũ sang các tên mới được sử dụng trong Python 3.

Việc mã hóa và lỗi cho Pickle biết cách giải mã các trường hợp chuỗi 8 bit được chọn bởi Python 2; những cái này mặc định là 'ASCII' và 'nghiêm ngặt', tương ứng. Mã hóa có thể là 'byte' để đọc các thể hiện chuỗi 8 bit này dưới dạng các đối tượng byte.


0

Có tiếng lạch cạch nhanh hơn dưa chua và dễ dàng hơn. Tôi đã cố lưu và đọc nó trong thùng rác nhưng trong khi đọc có rất nhiều vấn đề và lãng phí một giờ và vẫn không tìm ra giải pháp mặc dù tôi đang làm việc trên dữ liệu của riêng mình để tạo một chatbot.

vec_xvec_ylà mảng numpy:

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

Sau đó, bạn chỉ cần đọc nó và thực hiện các hoạt động:

data2 = hkl.load( 'new_data_file.hkl' )
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.