180 votes

Incompatibilité Pickle des tableaux numpy entre Python 2 et 3

J'essaie de charger l'ensemble de données MNIST lié aquí en Python 3.2 à l'aide de ce programme :

import pickle
import gzip
import numpy

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

Malheureusement, j'obtiens l'erreur suivante :

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)

J'ai ensuite essayé de décoder le fichier décapé en Python 2.7, et de le recoder. J'ai donc exécuté ce programme en 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.

Il s'est exécuté sans erreur, j'ai donc réexécuté ce programme en 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)

Cependant, j'ai obtenu la même erreur qu'auparavant. Comment faire pour que cela fonctionne ?


Il s'agit d'une meilleure approche pour le chargement de l'ensemble de données MNIST.

162voto

Tshilidzi Mudau Points 103

Si vous obtenez cette erreur avec python3, il peut s'agir d'un problème d'incompatibilité entre python 2 et python 3, pour moi la solution a été de load con latin1 encodage :

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

157voto

Lennart Regebro Points 52510

Il semble qu'il s'agisse d'une sorte d'incompatibilité. Il essaie de charger un objet "binstring", qui est supposé être ASCII, alors que dans ce cas il s'agit de données binaires. Je ne sais pas s'il s'agit d'un bogue dans le décodeur de Python 3, ou d'une "mauvaise utilisation" du décodeur par numpy.

Voici une sorte de solution de contournement, mais je ne sais pas si les données sont significatives à ce stade :

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)

Le découper en Python 2 et le recouper ensuite ne fera que créer à nouveau le même problème, vous devez donc l'enregistrer dans un autre format.

16voto

Steve Points 161

Il semble qu'il s'agisse d'un problème d'incompatibilité entre Python 2 et Python 3. J'ai essayé de charger le jeu de données MNIST avec

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

et cela a fonctionné pour Python 3.5.2

8voto

jozzas Points 3408

On dirait que il y a des problèmes de compatibilité dans Pickle entre la version 2.x et la version 3.x en raison du passage à l'unicode. Votre fichier semble avoir été décodé avec python 2.x et son décodage en 3.x pourrait être problématique.

Je suggérerais de le décompiler avec python 2.x et de le sauvegarder dans un format qui fonctionne mieux entre les deux versions que vous utilisez.

7voto

serge Points 71

Je viens de tomber sur cet extrait. J'espère que cela aidera à clarifier le problème de 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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X