web-dev-qa-db-fra.com

Incompatibilité de pickle des tableaux numpy entre Python 2 et 3

J'essaye de charger le jeu de données MNIST lié ici dans Python 3.2 en utilisant 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, cela me donne l'erreur:

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 mariné en Python 2.7 et de le recodifier. Donc, j'ai 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 a fonctionné sans erreur, alors j'ai relancé ce programme dans 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, cela m'a donné la même erreur qu'avant. Comment puis-je obtenir que cela fonctionne?


C'est une meilleure approche pour charger le jeu de données MNIST.

143
Neil G

Cela ressemble à une sorte d'incompatibilité. Il essaie de charger un objet "binstring", qui est supposé être ASCII, alors que dans ce cas, ce sont des données binaires. S'il s'agit d'un bogue dans le dépileur Python 3, ou d'une "utilisation abusive" du préparateur par numpy, je ne le sais pas.

Voici une solution de contournement, mais je ne sais pas à quel point 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épickler dans Python 2 puis le repicker ne fera que créer le même problème à nouveau. Vous devez donc l'enregistrer dans un autre format.

120
Lennart Regebro

Si vous obtenez cette erreur dans python3, il pourrait alors s'agir d'un problème d'incompatibilité entre python 2 et python 3, pour moi la solution consistait à load avec lattin1 encodage:

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

Il semble s'agir 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

10
Steve

Cela ressemble à il y a quelques problèmes de compatibilité dans les cornichons entre 2.x et 3.x en raison du passage à l'unicode. Votre fichier semble être décapé avec python 2.x et le décodage en 3.x pourrait être gênant.

Je suggérerais de le décoiffer avec python 2.x et de le sauvegarder dans un format plus lisible dans les deux versions que vous utilisez.

7
jozzas

Je suis juste tombé sur cet extrait. J'espère que cela aide à 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)
6
serge

Essayer:

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

De la documentation de pickle.load méthode:

Les arguments de mot-clé facultatifs sont fix_imports, encoding et errors, utilisés pour contrôler la compatibilité du flux de pickle généré par Python 2.

Si fix_imports a la valeur True, pickle essaiera de mapper les anciens noms Python 2) aux nouveaux noms utilisés dans Python 3.

Le codage et les erreurs indiquent à pickle comment décoder des instances de chaîne de 8 bits sélectionnées par Python 2; ces valeurs par défaut sont respectivement "ASCII" et "strict". Le codage peut être "octets" à lire ces instances de chaîne de 8 bits en tant qu'objets octets.

2
Manish Kumbhare

Il y a un hickle qui est plus rapide que pickle et plus facile. J'ai essayé de sauvegarder et de le lire dans pickle dump, mais lors de la lecture, il y avait beaucoup de problèmes et une perte de temps d'une heure et je n'ai toujours pas trouvé de solution bien que je travaille sur mes propres données pour créer un chatbot.

vec_x et vec_y sont des tableaux numpy:

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

Ensuite, il vous suffit de le lire et d’effectuer les opérations suivantes:

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