ความไม่ลงรอยกันของดองของอาร์เรย์ numpy ระหว่าง Python 2 และ 3


163

ฉันพยายามที่จะโหลดชุด MNIST ที่เชื่อมโยงที่นี่ในหลาม 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 โดยเฉพาะอย่างยิ่งสตริง vs Unicode และการเลือกวัตถุ numpy ต้องการให้ทั้งสองระบบโหลดโมดูล numpy แต่โมดูลเหล่านั้นแตกต่างกัน ขออภัยฉันไม่มีคำตอบ แต่สิ่งนี้อาจไม่สามารถทำได้และอาจไม่แนะนำให้เลือก หากนี่คือสิ่งที่ยิ่งใหญ่ (gzip) อาจเป็น hdf5 กับ pytables
Phil Cooper

@PhilCooper: ขอบคุณความคิดเห็นของคุณ (โพสต์นี้เป็นคำตอบ?) clued ฉันในคำตอบที่ถูกต้อง ฉันสามารถใช้ hdf5 ได้ แต่ดูเหมือนว่ามันซับซ้อนในการเรียนรู้ดังนั้นฉันจึงไปกับ numpy.save/load และสิ่งนี้ใช้ได้
Neil G

h5py นั้นใช้ง่ายมากแน่นอนว่าง่ายกว่ามากแล้วก็แก้ปัญหาความเข้ากันได้แบบคลุมเครือกับอาร์เรย์ numpy ดอง
DaveP

คุณบอกว่าคุณ "รันโปรแกรมนี้ภายใต้ Python 2.7" ตกลง แต่คุณทำงานภายใต้ 3.2 อะไร :-) เหมือน?
Lennart Regebro

@LennartRegebro: หลังจากเรียกใช้โปรแกรมที่สองที่เลือกอาร์เรย์ฉันรันโปรแกรมแรก (แทนที่ชื่อไฟล์ mnistx.pkl.gz) ใน Python 3.2 มันใช้งานไม่ได้ซึ่งฉันคิดว่ามันแสดงถึงความไม่ลงรอยกันบางอย่าง
Neil G

คำตอบ:


141

ดูเหมือนว่าบางสิ่งที่เข้ากันไม่ได้ กำลังพยายามโหลดวัตถุ "binstring" ซึ่งสันนิษฐานว่าเป็น ASCII ในขณะที่ในกรณีนี้เป็นข้อมูลไบนารี หากนี่เป็นข้อผิดพลาดใน Python 3 unpickler หรือ "การใช้ผิดวัตถุประสงค์" ของตัวเลือกโดยผู้ใช้จำนวนมากฉันไม่รู้

นี่เป็นวิธีแก้ปัญหา แต่ฉันไม่รู้ว่าข้อมูลมีความหมายในจุดนี้:

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 แล้วทำการเลือกใหม่เพียงเพื่อสร้างปัญหาเดียวกันอีกครั้งดังนั้นคุณต้องบันทึกในรูปแบบอื่น


211
คุณสามารถใช้pickle.load(file_obj, encoding='latin1')(อย่างน้อยใน Python 3.3) นี้ดูเหมือนว่าการทำงาน
Tom Aldcroft

7
สำหรับผู้ที่ใช้โหลด numpy และเผชิญกับปัญหาที่คล้ายกัน: มันเป็นไปได้ที่จะผ่านการเข้ารหัสเช่นกัน:np.load('./bvlc_alexnet.npy', encoding='latin1')
Serj Zaharchenko

สิ่งนี้ใช้ได้สำหรับฉันเมื่อการเพิ่มencoding='latin1'ล้มเหลว ขอบคุณ!
Guillem Cucurull

130

หากคุณได้รับข้อผิดพลาดใน python3 แล้วก็อาจจะมีปัญหาความไม่ลงรอยกันระหว่างหลามที่ 2 และ 3 หลามสำหรับฉันการแก้ปัญหาคือการloadที่มีlatin1การเข้ารหัส:

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

ดูเหมือนว่ามีปัญหาความเข้ากันได้บางอย่างในดองระหว่าง 2.x และ 3.x เนื่องจากการย้ายไปยัง Unicode ดูเหมือนว่าไฟล์ของคุณจะถูกดองด้วย python 2.x และการถอดรหัสใน 3.x อาจเป็นปัญหาได้

ฉันขอแนะนำให้ถอนการติดตั้งด้วย python 2.x และบันทึกเป็นรูปแบบที่เล่นได้ดีกว่าทั้งสองเวอร์ชันที่คุณใช้


2
นั่นคือสิ่งที่ฉันพยายามทำ คุณแนะนำรูปแบบใด
Neil G

5
ฉันคิดว่าปัญหาอาจเกิดจากการเข้ารหัส numpy dtype ซึ่งอาจเป็นสตริง ไม่ว่าในกรณีใดฉันลงเอยด้วยการใช้ numpy.save/load เพื่อเชื่อมช่องว่างระหว่าง python 2 และ 3 และสิ่งนี้ใช้ได้
Neil 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)

พิจารณาเพิ่มข้อมูลที่ขยายเพิ่มเติม วิธีนี้แก้ปัญหาได้อย่างไร
Tom Aranda

@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วิธีการ:

อาร์กิวเมนต์คำหลักที่เป็นตัวเลือกคือ fix_imports, การเข้ารหัสและข้อผิดพลาดซึ่งใช้เพื่อควบคุมการรองรับความเข้ากันได้สำหรับกระแส pickle ที่สร้างโดย Python 2

หาก fix_imports เป็น True pickle จะพยายามแมปชื่อ Python 2 เก่ากับชื่อใหม่ที่ใช้ใน Python 3

การเข้ารหัสและข้อผิดพลาดจะบอกวิธีการถอดรหัสอินสแตนซ์สตริงแบบ 8 บิตที่เลือกโดย Python 2 ค่าเริ่มต้นเหล่านี้เป็น 'ASCII' และ 'เข้มงวด' ตามลำดับ การเข้ารหัสสามารถเป็น 'ไบต์' เพื่ออ่านอินสแตนซ์สตริง 8 บิตเหล่านี้เป็นวัตถุไบต์


0

มี hickle ซึ่งเร็วกว่าดองและง่ายขึ้น ฉันพยายามที่จะบันทึกและอ่านมันใน pickle dump แต่ในขณะที่อ่านมีปัญหามากมายและเสียเวลาหนึ่งชั่วโมงและยังไม่พบวิธีแก้ปัญหาแม้ว่าฉันกำลังทำงานกับข้อมูลของตัวเองเพื่อสร้าง chatbot

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.