Incompatibilità del pickle di array intorpiditi tra Python 2 e 3


163

Sto cercando di caricare il set di dati MNIST collegato qui in Python 3.2 utilizzando questo programma:

import pickle
import gzip
import numpy


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

Sfortunatamente, mi dà l'errore:

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)

Ho quindi provato a decodificare il file decapato in Python 2.7 e ricodificarlo. Quindi, ho eseguito questo programma in 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.

Funzionava senza errori, quindi ho eseguito nuovamente questo programma in 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)

Tuttavia, mi ha dato lo stesso errore di prima. Come faccio a farlo funzionare?


Questo è un approccio migliore per il caricamento del set di dati MNIST.


ci sono interruzioni di compatibilità tra 2.7 e 3.x. soprattutto stringa vs unicode. E la scelta di un oggetto numpy richiede che entrambi i sistemi caricino il modulo numpy ma quei moduli sono diversi. Mi dispiace non ho una risposta, ma potrebbe non essere fattibile e probabilmente non è consigliabile. Se queste sono cose grandi (gzip), forse hdf5 con pytables ??
Phil Cooper,

@PhilCooper: Grazie, il tuo commento (pubblicare questo come risposta?) Mi ha indicato la risposta giusta. Avrei potuto usare hdf5, ma sembrava complicato da imparare, quindi sono andato con numpy.save/load e questo ha funzionato.
Neil G,

h5py è molto semplice da usare, quasi sicuramente molto più semplice della risoluzione di problemi di compatibilità nebulosa con decapaggio di array intorpiditi.
DaveP,

Dici di "aver eseguito questo programma con Python 2.7". OK ma cosa hai eseguito sotto 3.2? :-) Lo stesso?
Lennart Regebro,

@LennartRegebro: Dopo aver eseguito il secondo programma che esegue il decaping degli array, ho eseguito il primo programma (sostituendo il nome file mnistx.pkl.gz) in Python 3.2. Non ha funzionato, il che penso illustra una sorta di incompatibilità.
Neil G

Risposte:


141

Sembra una sorta di incompatibilità. Sta cercando di caricare un oggetto "binstring", che si presume sia ASCII, mentre in questo caso si tratta di dati binari. Se questo è un bug nel disordinatore di Python 3, o un "uso improprio" del pickler da parte di Numpy, non lo so.

Ecco una soluzione alternativa, ma non so quanto siano significativi i dati a questo punto:

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)

Disimballarlo in Python 2 e ripeterlo creerà nuovamente lo stesso problema, quindi è necessario salvarlo in un altro formato.


211
Puoi usare pickle.load(file_obj, encoding='latin1')(almeno in Python 3.3). Questo sembra funzionare.
Tom Aldcroft,

7
Per coloro che usano un carico intorpidito e affrontano il problema simile: è possibile passare anche la codifica lì:np.load('./bvlc_alexnet.npy', encoding='latin1')
Serj Zaharchenko,

Questo ha funzionato per me quando l'aggiunta encoding='latin1'non è riuscita. Grazie!
Guillem Cucurull,

130

Se hai trovato questo errore in python3, quindi, potrebbe essere un problema di incompatibilità tra Python 2 e Python 3, per me la soluzione è stata quella loadcon latin1la codifica:

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

16

Sembra essere un problema di incompatibilità tra Python 2 e Python 3. Ho provato a caricare il set di dati MNIST con

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

e ha funzionato per Python 3.5.2


7

Sembra che ci siano alcuni problemi di compatibilità tra 2.x e 3.x dovuti al passaggio all'unicode. Il tuo file sembra essere decapato con Python 2.xe decodificarlo in 3.x potrebbe essere problematico.

Suggerirei di decomprimerlo con Python 2.xe di salvarlo in un formato che riproduca meglio le due versioni in uso.


2
Questo è quello che stavo cercando di fare. Quale formato mi consigliate?
Neil G,

5
Penso che il problema potrebbe essere stato la codifica del dtype numpy, che potrebbe essere una stringa. In ogni caso, ho finito per usare numpy.save/load per colmare il divario tra python 2 e 3, e questo ha funzionato.
Neil G,

7

Mi sono appena imbattuto in questo frammento. Spero che questo aiuti a chiarire il problema della compatibilità.

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)

Valuta di aggiungere ulteriori informazioni di amplificazione. In che modo questo risolve il problema?
Tom Aranda,

@serge che ha aiutato, per favore spiegazione alla risposta
Sarath Sadasivan Pillai

6

Provare:

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

Dalla documentazione del pickle.loadmetodo:

Gli argomenti di parole chiave opzionali sono fix_imports, codifica ed errori, che vengono utilizzati per controllare il supporto di compatibilità per il flusso di pickle generato da Python 2.

Se fix_imports è True, pickle proverà a mappare i vecchi nomi di Python 2 ai nuovi nomi usati in Python 3.

La codifica e gli errori indicano a pickle come decodificare le istanze di stringa a 8 bit decapate da Python 2; questi sono impostati rispettivamente su "ASCII" e "rigoroso". La codifica può essere "byte" per leggere queste istanze di stringa a 8 bit come oggetti byte.


0

C'è il grillo che è più veloce del sottaceto e più facile. Ho provato a salvarlo e leggerlo in una discarica, ma durante la lettura ci sono stati molti problemi e ho perso un'ora e ancora non ho trovato una soluzione anche se stavo lavorando sui miei dati per creare un chatbot.

vec_xe vec_ysono matrici intorpidite:

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

Quindi basta leggerlo ed eseguire le operazioni:

data2 = hkl.load( 'new_data_file.hkl' )
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.