Après avoir créé un tableau NumPy et l'avoir enregistré en tant que variable de contexte Django, le message d'erreur suivant s'affiche lors du chargement de la page Web:
array([ 0, 239, 479, 717, 952, 1192, 1432, 1667], dtype=int64) is not JSON serializable
Qu'est-ce que ça veut dire?
Je "jsonify" régulièrement np.arrays. Essayez d’abord d’utiliser la méthode ".tolist ()" sur les tableaux, comme ceci:
import numpy as np
import codecs, json
a = np.arange(10).reshape(2,5) # a 2 by 5 array
b = a.tolist() # nested lists with same data, indices
file_path = "/path.json" ## your path variable
json.dump(b, codecs.open(file_path, 'w', encoding='utf-8'), separators=(',', ':'), sort_keys=True, indent=4) ### this saves the array in .json format
Pour "désélectionner" le tableau, utilisez:
obj_text = codecs.open(file_path, 'r', encoding='utf-8').read()
b_new = json.loads(obj_text)
a_new = np.array(b_new)
Stocker en JSON un numpy.ndarray ou toute composition à liste imbriquée.
class NumpyEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, np.ndarray):
return obj.tolist()
return json.JSONEncoder.default(self, obj)
a = np.array([[1, 2, 3], [4, 5, 6]])
print(a.shape)
json_dump = json.dumps({'a': a, 'aa': [2, (2, 3, 4), a], 'bb': [2]}, cls=NumpyEncoder)
print(json_dump)
Est-ce que la sortie:
(2, 3)
{"a": [[1, 2, 3], [4, 5, 6]], "aa": [2, [2, 3, 4], [[1, 2, 3], [4, 5, 6]]], "bb": [2]}
Pour restaurer à partir de JSON:
json_load = json.loads(json_dump)
a_restored = np.asarray(json_load["a"])
print(a_restored)
print(a_restored.shape)
Est-ce que la sortie:
[[1 2 3]
[4 5 6]]
(2, 3)
Vous pouvez utiliser Pandas :
import pandas as pd
pd.Series(your_array).to_json(orient='values')
J'ai trouvé la meilleure solution si vous avez imbriqué des tableaux numpy dans un dictionnaire:
import json
import numpy as np
class NumpyEncoder(json.JSONEncoder):
""" Special json encoder for numpy types """
def default(self, obj):
if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
np.int16, np.int32, np.int64, np.uint8,
np.uint16, np.uint32, np.uint64)):
return int(obj)
Elif isinstance(obj, (np.float_, np.float16, np.float32,
np.float64)):
return float(obj)
Elif isinstance(obj,(np.ndarray,)): #### This is the fix
return obj.tolist()
return json.JSONEncoder.default(self, obj)
dumped = json.dumps(data, cls=NumpyEncoder)
with open(path, 'w') as f:
json.dump(dumped, f)
Merci à ce gars .
Certains des autres encodeurs numpy semblent un peu trop verbeux.
vérifie si l'objet provient du module numpy, si c'est le cas, utilisez ndarray.tolist
pour un ndarray
ou utilisez _.item
_ pour tout autre type spécifique à numpy.
Utilisez le _json.dumps
_ default
kwarg:
default doit être une fonction appelée pour les objets ne pouvant pas être sérialisés autrement.
_import numpy as np
def default(obj):
if type(obj).__module__ == np.__name__:
if isinstance(obj, np.ndarray):
return obj.tolist()
else:
return obj.item()
raise TypeError('Unknown type:', type(obj))
dumped = json.dumps(data, default=default)
_
Ce n'est pas supporté par défaut, mais vous pouvez le faire fonctionner assez facilement! Il y a plusieurs choses que vous voudrez encoder si vous voulez récupérer exactement les mêmes données:
obj.tolist()
comme @travelingbones mentionné. Parfois, cela peut suffire.De plus, votre tableau numpy pourrait faire partie de votre structure de données, par exemple. vous avez une liste avec quelques matrices à l'intérieur. Pour cela, vous pouvez utiliser un encodeur personnalisé qui effectue les opérations ci-dessus.
Cela devrait suffire à mettre en œuvre une solution. Ou vous pouvez utiliser json-tricks qui ne fait que cela (et supporte divers autres types) (disclaimer: je l'ai fait).
pip install json-tricks
Ensuite
data = [
arange(0, 10, 1, dtype=int).reshape((2, 5)),
datetime(year=2017, month=1, day=19, hour=23, minute=00, second=00),
1 + 2j,
Decimal(42),
Fraction(1, 3),
MyTestCls(s='ub', dct={'7': 7}), # see later
set(range(7)),
]
# Encode with metadata to preserve types when decoding
print(dumps(data))
J'ai eu un problème similaire avec un dictionnaire imbriqué contenant quelques numpy.ndarrays.
def jsonify(data):
json_data = dict()
for key, value in data.iteritems():
if isinstance(value, list): # for lists
value = [ jsonify(item) if isinstance(item, dict) else item for item in value ]
if isinstance(value, dict): # for nested lists
value = jsonify(value)
if isinstance(key, int): # if key is integer: > to string
key = str(key)
if type(value).__module__=='numpy': # if value is numpy.*: > to python list
value = value.tolist()
json_data[key] = value
return json_data
Vous pouvez également utiliser l'argument default
, par exemple:
def myconverter(o):
if isinstance(o, np.float32):
return float(o)
json.dump(data, default=myconverter)
Peut faire simple pour boucle avec les types de contrôle:
with open("jsondontdoit.json", 'w') as fp:
for key in bests.keys():
if type(bests[key]) == np.ndarray:
bests[key] = bests[key].tolist()
continue
for idx in bests[key]:
if type(bests[key][idx]) == np.ndarray:
bests[key][idx] = bests[key][idx].tolist()
json.dump(bests, fp)
fp.close()
TypeError: array ([[0.46872085, 0.67374235, 1.0218339, 0.13210179, 0.5440686, 0.9140083, 0.58720225, 0.2199381]], dtype = float32) n'est pas JSON sérialisable
L'erreur susmentionnée a été émise lorsque j'ai essayé de transmettre une liste de données à model.predict () alors que j'attendais une réponse au format JSON.
> 1 json_file = open('model.json','r')
> 2 loaded_model_json = json_file.read()
> 3 json_file.close()
> 4 loaded_model = model_from_json(loaded_model_json)
> 5 #load weights into new model
> 6 loaded_model.load_weights("model.h5")
> 7 loaded_model.compile(optimizer='adam', loss='mean_squared_error')
> 8 X = [[874,12450,678,0.922500,0.113569]]
> 9 d = pd.DataFrame(X)
> 10 prediction = loaded_model.predict(d)
> 11 return jsonify(prediction)
Heureusement, nous avons trouvé un indice pour résoudre l’erreur générée. La sérialisation des objets ne s’applique que pour la conversion suivante. Le mappage doit correspondre à la méthode suivante: objet - dict tableau - liste. Chaîne - chaîne entier - entier
Si vous faites défiler vers le haut pour voir le numéro de ligne 10 prediction = chargé_modèle.predict (d) où cette ligne de code générait la sortie du type de données type array, lorsque vous essayez de convertir un tableau au format json, cela n'est pas possible.
Enfin, j'ai trouvé la solution en convertissant simplement la sortie obtenue en liste de types en suivant les lignes de code.
prédiction = chargé_modèle.predict (d)
listtype = prediction.tolist () retourne jsonify (listtype)
C'est une réponse différente, mais cela pourrait aider les personnes qui tentent de sauvegarder des données puis de les relire.
Il y a un hickle qui est plus rapide que cornichon et plus facile.
J'ai essayé de le sauvegarder et de le lire dans Pickle Dump, mais en lisant, il y avait beaucoup de problèmes et une perte d'une heure et je ne trouvais toujours pas de solution alors que je travaillais sur mes propres données pour créer un bot bot.
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' )
Voici une implémentation qui fonctionne pour moi et qui supprime tous les nans (en supposant qu'il s'agisse d'objets simples (list ou dict)):
from numpy import isnan
def remove_nans(my_obj, val=None):
if isinstance(my_obj, list):
for i, item in enumerate(my_obj):
if isinstance(item, list) or isinstance(item, dict):
my_obj[i] = remove_nans(my_obj[i], val=val)
else:
try:
if isnan(item):
my_obj[i] = val
except Exception:
pass
Elif isinstance(my_obj, dict):
for key, item in my_obj.iteritems():
if isinstance(item, list) or isinstance(item, dict):
my_obj[key] = remove_nans(my_obj[key], val=val)
else:
try:
if isnan(item):
my_obj[key] = val
except Exception:
pass
return my_obj
En outre, des informations très intéressantes sur les listes et les tableaux dans Python ~> Liste Python ou Tableau - quand utiliser?
Il est à noter qu’une fois que j’ai converti mes tableaux en liste avant de les enregistrer dans un fichier JSON, dès lors que je suis dans mon déploiement, une fois que j'ai lu ce fichier JSON pour une utilisation ultérieure, je peux continuer à l’utiliser sous forme de liste opposé à la reconvertir en tableau).
ET semble en fait plus joli (à mon avis) à l'écran sous forme de liste (séparée par des virgules) par rapport à un tableau (séparé par des virgules) de cette façon.
En utilisant la méthode .tolist () de @ travelingbones ci-dessus, je l'utilise en tant que telle (en détectant quelques erreurs que j'ai trouvées aussi):
ENREGISTRER DICTIONNAIRE
def writeDict(values, name):
writeName = DIR+name+'.json'
with open(writeName, "w") as outfile:
json.dump(values, outfile)
LIRE LE DICTIONNAIRE
def readDict(name):
readName = DIR+name+'.json'
try:
with open(readName, "r") as infile:
dictValues = json.load(infile)
return(dictValues)
except IOError as e:
print(e)
return('None')
except ValueError as e:
print(e)
return('None')
J'espère que cela t'aides!