wake-up-neo.com

NumPy-Array ist nicht mit JSON serialisierbar

Nachdem ich ein NumPy-Array erstellt und als Django Kontextvariable gespeichert habe, wird beim Laden der Webseite die folgende Fehlermeldung angezeigt:

array([   0,  239,  479,  717,  952, 1192, 1432, 1667], dtype=int64) is not JSON serializable

Was bedeutet das?

176
Karnivaurus

Ich "jsonifiziere" regelmäßig np.arrays. Versuchen Sie zunächst, die Methode ".tolist ()" für die Arrays zu verwenden:

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

Um das Array zu "unjsonifizieren", verwenden Sie:

obj_text = codecs.open(file_path, 'r', encoding='utf-8').read()
b_new = json.loads(obj_text)
a_new = np.array(b_new)
222
travelingbones

Speichern Sie als JSON eine numpy.ndarray oder eine beliebige Komposition aus verschachtelten Listen.

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)

Wird ausgeben:

(2, 3)
{"a": [[1, 2, 3], [4, 5, 6]], "aa": [2, [2, 3, 4], [[1, 2, 3], [4, 5, 6]]], "bb": [2]}

So stellen Sie aus JSON wieder her:

json_load = json.loads(json_dump)
a_restored = np.asarray(json_load["a"])
print(a_restored)
print(a_restored.shape)

Wird ausgeben:

[[1 2 3]
 [4 5 6]]
(2, 3)
145
karlB

Sie können Pandas verwenden:

import pandas as pd
pd.Series(your_array).to_json(orient='values')
34
John Zwinck

Ich habe die beste Lösung gefunden, wenn Sie numpy Arrays in einem Wörterbuch verschachtelt haben:

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)

Danke an diesen Typen .

27
tsveti_iko

Einige der anderen Drehgeber wirken etwas zu ausführlich.

überprüfen Sie, ob das Objekt von der Modulnummer stammt. Verwenden Sie in diesem Fall ndarray.tolist für ein ndarray oder benutze .item für jeden anderen numpy-spezifischen Typ.

Verwenden Sie die json.dumpsdefault kwarg:

standard sollte eine Funktion sein, die für Objekte aufgerufen wird, die andernfalls nicht serialisiert werden können.

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)
13
moshevi

Dies wird standardmäßig nicht unterstützt, aber Sie können es ganz einfach zum Laufen bringen! Es gibt verschiedene Dinge, die Sie verschlüsseln möchten, wenn Sie exakt dieselben Daten zurückhaben möchten:

  • Die Daten selbst, die Sie mit obj.tolist() als @travelingbones beziehen können, werden erwähnt. Manchmal kann dies gut genug sein.
  • Der Datentyp. Ich halte das in einigen Fällen für wichtig.
  • Die Bemaßung (nicht unbedingt 2D), die sich aus den obigen Angaben ableiten lässt, wenn Sie davon ausgehen, dass die Eingabe tatsächlich immer ein "rechteckiges" Gitter ist.
  • Die Speicherreihenfolge (Zeilen- oder Spalten-Major). Dies ist nicht oft wichtig, aber manchmal (z. B. Leistung). Warum also nicht alles speichern?

Darüber hinaus könnte Ihr Numpy-Array Teil Ihrer Datenstruktur sein, z. Sie haben eine Liste mit einigen Matrizen im Inneren. Dafür könnten Sie einen benutzerdefinierten Encoder verwenden, der im Grunde das oben Genannte tut.

Dies sollte ausreichen, um eine Lösung zu implementieren. Oder Sie könnten json-Tricks verwenden, das genau dies tut (und verschiedene andere Typen unterstützt) (Haftungsausschluss: Ich habe es gemacht).

pip install json-tricks

Dann

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))
5
Mark

Ich hatte ein ähnliches Problem mit einem verschachtelten Wörterbuch mit einigen numpy.ndarrays darin.

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
3
JLT

Sie können auch das Argument default verwenden, zum Beispiel:

def myconverter(o):
    if isinstance(o, np.float32):
        return float(o)

json.dump(data, default=myconverter)
3
steco

Kann für Schleife mit überprüfenden Typen einfach tun:

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()
1
Robert GRZELKA

TypeError: Array ([[0.46872085, 0.67374235, 1.0218339, 0.13210179, 0.5440686, 0.9140083, 0.58720225, 0.2199381]], dtype = float32) ist nicht JSON-serialisierbar

Der oben erwähnte Fehler wurde ausgelöst, als ich versuchte, die Liste der Daten an model.predict () zu übergeben, als ich die Antwort im JSON-Format erwartete.

> 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)

Glücklicherweise wurde der Hinweis gefunden, den Fehler zu beheben. Die Serialisierung der Objekte gilt nur für die folgende Konvertierung. Die Zuordnung sollte wie folgt lauten: object - dict array - list string - string integer - integer

Wenn Sie nach oben scrollen, um die Zeile 10 prediction = loaded_model.predict (d) zu sehen, in der diese Codezeile die Ausgabe des Array-Datentyps generiert hat, ist es nicht möglich, das Array in das JSON-Format zu konvertieren

Schließlich fand ich die Lösung, indem ich die erhaltene Ausgabe in die Typenliste umwandelte, indem ich den Codezeilen folgte

prediction = loaded_model.predict (d)
listtype = prediction.tolist () return jsonify (listtype)

Bhoom! endlich die erwartete Ausgabe bekommen, enter image description here

Dies ist eine andere Antwort. Dies kann jedoch hilfreich sein, wenn Sie versuchen, Daten zu speichern und sie dann erneut zu lesen.
Es gibt Hickle, der schneller als Gurke und einfacher ist.
Ich habe versucht, es in Pickle Dump zu speichern und zu lesen, aber während des Lesens gab es viele Probleme und es wurde eine Stunde verschwendet und ich fand immer noch keine Lösung, obwohl ich an meinen eigenen Daten arbeitete, um einen Chat-Bot zu erstellen.

vec_x und vec_y sind numpy Arrays:

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

Dann lesen Sie es einfach und führen die Operationen durch:

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

Hier ist eine Implementierung, die für mich funktioniert und alle Nans entfernt hat (vorausgesetzt, dies sind einfache Objekte (Liste oder Dikt)):

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
1
Roei Bahumi

Außerdem einige sehr interessante Informationen zu Listen und Arrays in Python ~> Python List vs. Array - wann?

Wenn ich meine Arrays vor dem Speichern in einer JSON - Datei in eine Liste konvertiert habe, kann ich sie nach dem Lesen dieser JSON - Datei für die spätere Verwendung weiterhin in einer Listenform (als im Gegensatz dazu, es wieder in ein Array umzuwandeln).

AND sieht (meiner Meinung nach) auf dem Bildschirm tatsächlich besser aus als eine Liste (durch Kommas getrennt) im Vergleich zu einem Array (nicht durch Kommas getrennt).

Unter Verwendung der oben genannten .tolist () -Methode von @ travelingbones habe ich als solche verwendet (und dabei auch ein paar Fehler abgefangen, die ich gefunden habe):

WÖRTERBUCH SPEICHERN

def writeDict(values, name):
    writeName = DIR+name+'.json'
    with open(writeName, "w") as outfile:
        json.dump(values, outfile)

WÖRTERBUCH LESEN

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')

Hoffe das hilft!

1
ntk4