NumPy配列を作成し、それをDjangoコンテキスト変数として保存すると、Webページを読み込むときに次のエラーが表示されます。
array([ 0, 239, 479, 717, 952, 1192, 1432, 1667], dtype=int64) is not JSON serializable
これは何を意味するのでしょうか?
私は定期的にnp.arraysを "jsonify"します。このように、最初に配列に対して ".tolist()"メソッドを使用してみてください。
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
配列を "unjsonify"するには
obj_text = codecs.open(file_path, 'r', encoding='utf-8').read()
b_new = json.loads(obj_text)
a_new = np.array(b_new)
JSONとしてnumpy.ndarrayまたは任意のネストリストコンポジションを保存します。
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)
出力します:
(2, 3)
{"a": [[1, 2, 3], [4, 5, 6]], "aa": [2, [2, 3, 4], [[1, 2, 3], [4, 5, 6]]], "bb": [2]}
JSONから復元するには
json_load = json.loads(json_dump)
a_restored = np.asarray(json_load["a"])
print(a_restored)
print(a_restored.shape)
出力します:
[[1 2 3]
[4 5 6]]
(2, 3)
あなたは Pandas を使うことができます:
import pandas as pd
pd.Series(your_array).to_json(orient='values')
あなたが辞書にnumpy配列を入れ子にしているなら、私は最良の解決策を見つけました:
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)
ありがとう この男 。
他のぎこちないエンコーダのいくつかは少し過度に冗長に見えます。
もしオブジェクトがモジュールから派手であるかどうかを調べ、そうであれば、ndarray
に ndarray.tolist
を使うか、他の派手な特定の型に.item
を使ってください。
json.dumps
default
kwargを使用してください。
デフォルトは、他の方法ではシリアル化できないオブジェクトに対して呼び出される関数です。
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)
これはデフォルトではサポートされていませんが、簡単に機能させることができます。まったく同じデータを元に戻したい場合は、エンコードしたいことがいくつかあります。
obj.tolist()
で得ることができるデータ自体。時にはこれで十分かもしれません。さらに、あなたのでこぼこした配列はあなたのデータ構造の一部になる可能性があります。内部にいくつかの行列を含むリストがあります。そのためにあなたは基本的に上記をするカスタムエンコーダを使うことができます。
解決策を実装するにはこれで十分なはずです。あるいは、 json-tricks を使用することもできます(これは他のさまざまなタイプをサポートします)(免責事項:私が作成しました)。
pip install json-tricks
それから
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))
いくつかの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
例えばdefault
引数を使うこともできます。
def myconverter(o):
if isinstance(o, np.float32):
return float(o)
json.dump(data, default=myconverter)
型をチェックする単純なforループをすることができます:
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)はJSONシリアライズ可能ではありません
私はJSON形式で応答を期待していたときにmodel.predict()にデータのリストを渡そうとしたときに上記のエラーがスローされました。
> 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)
しかし幸運なことに、投げていたエラーを解決するためのヒントが見つかりました。オブジェクトのシリアライズは次の変換にのみ適用できます。マッピングは次のようになります。object-dict array - list string - string integer - integer
スクロールアップして行番号10を表示する場合、このコード行で配列datatype型の出力が生成されていた行を予測= load_model.predict(d)とします。配列をjson形式に変換しようとすると不可能になります。
最後に、得られた出力を次のコード行で型リストに変換することで解決策を見つけました。
予測= loaded_model.predict(d)
listtype = predict.tolist()return jsonify(listtype)
これは別の答えですが、これはデータを保存してからもう一度読み込もうとしている人々を助けるのに役立つかもしれません。
ピクルスより速くて簡単なヒックルがあります。
私はそれをピクルスダンプに保存して読み込もうとしましたが、読んでいる間に多くの問題があり、1時間浪費しました。
vec_x
とvec_y
は派手な配列です。
data=[vec_x,vec_y]
hkl.dump( data, 'new_data_file.hkl' )
それからあなたはそれを読んで、そして操作を実行するだけです:
data2 = hkl.load( 'new_data_file.hkl' )
これは私のために働き、すべてのナンを削除する実装です(これらが単純なオブジェクト(リストか辞書)であると仮定して):
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
また、Pythonのリストと配列に関するさらに興味深い情報がいくつかあります。〜> Python List vs. Array - いつ使用するか?
配列をJSONファイルに保存する前にリストに変換した後は、いずれにせよ今のところ私のデプロイメントでは、後でそのJSONファイルを使用するためにリスト形式で使用することができますそれを配列に戻すのではなく)。
AND(コンマ区切り)対アレイ(非コンマ区切り)のように、実際には(私の意見では)画面上ではANDのほうがきれいに見えます。
上記の@ travelingbonesの.tolist()メソッドを使用して、私はそのように使用してきました(私も見つけたいくつかのエラーをキャッチします)。
辞書を保存する
def writeDict(values, name):
writeName = DIR+name+'.json'
with open(writeName, "w") as outfile:
json.dump(values, outfile)
辞書を読む
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')
お役に立てれば!