После создания массива NumPy и сохранения его как переменной контекста Django, я получаю следующую ошибку при загрузке веб-страницы:
array([ 0, 239, 479, 717, 952, 1192, 1432, 1667], dtype=int64) is not JSON serializable
Что это значит?
Я регулярно "jsonify" np.arrays. Сначала попробуйте использовать метод ".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)
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])
print (json.dumps({'aa': [2, (2, 3, 4), a], 'bb': [2]}, ЦБС = NumpyEncoder))
{ "aa": [2, [2, 3, 4], [1, 2, 3]], "bb": [2]}
Вы можете использовать Pandas:
import pandas as pd
pd.Series(your_array).to_json(orient='values')
pd.DataFrame(your_array).to_json('data.json', orient='split')
.
Я нашел лучшее решение, если у вас вложенные массивы 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)
Спасибо этому парню.
json
обратно, вы можете использовать это: with open(path, 'r') as f:
data = json.load(f)
, который возвращает словарь с вашими данными.
Это не поддерживается по умолчанию, но вы можете заставить его работать довольно легко! Есть несколько вещей, которые вы хотите закодировать, если хотите получить точные данные:
obj.tolist()
в качестве упоминаемых @travelingbones. Иногда это может быть достаточно хорошим.Кроме того, ваш массив numpy может быть частью вашей структуры данных, например. у вас есть список с некоторыми матрицами внутри. Для этого вы можете использовать собственный кодировщик, который в основном делает это.
Этого должно быть достаточно для реализации решения. Или вы можете использовать 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))
Вы также можете использовать аргумент по default
например:
def myconverter(o):
if isinstance(o, np.float32):
return float(o)
json.dump(data, default=myconverter)
У меня была аналогичная проблема с вложенным словарем с некоторыми 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
Ошибка типа: массив ([[0.46872085, 0.67374235, 1.0218339, 0.13210179, 0.5440686, 0.9140083, 0.58720225, 0.2199381]], dtype = float32) не поддерживает сериализацию JSON
Вышеупомянутая ошибка возникла, когда я попытался передать список данных в model.predict(), когда я ожидал ответа в формате 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)
Но, к счастью, нашла подсказку, чтобы разрешить возникшую ошибку. Сериализация объектов применима только для следующего преобразования. Отображение должно выполняться следующим образом: объект - dict массив - список строк - строка целое число - целое число
Если вы прокрутите вверх, чтобы увидеть строку с номером 10pretion =loaded_model.predict(d), где эта строка кода генерировала выходные данные типа массива данных типа, при попытке преобразовать массив в формат json это невозможно
Наконец, я нашел решение, просто преобразовав полученный вывод в список типов с помощью следующих строк кода
предсказание = загруженная_модель .predict(d)
listtype =вестиция .tolist() вернуть jsonify (listtype)
Bhoom! наконец-то получил ожидаемый результат,
Может сделать простой цикл с проверкой типов:
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()
Все остальные кодировщики кажутся слишком сложными. проверьте, если объект из модуля numpy использует numpy.item
, он работает для любого конкретного типа numpy.
import numpy as np
import json
class NumpyEncoder(json.JSONEncoder):
def default(self, obj):
if type(obj).__module__ == np.__name__:
if isinstance(obj, np.ndarray):
return obj.tolist()
else:
return obj.item()
return json.JSONEncoder.default(self, obj)
dumped = json.dumps(data, cls=NumpyEncoder)
Это другой ответ, но это может помочь людям, которые пытаются сохранить данные, а затем читать их снова.
Существует hickle, которая быстрее, чем рассол и легче.
Я попытался сохранить и прочитать его в дампе соски, но, читая, было много проблем и потрачено впустую на час, но до сих пор не нашел решения, хотя я работал над своими данными, чтобы создать чат-бот.
vec_x
и vec_y
- массивы numpy:
data=[vec_x,vec_y]
hkl.dump( data, 'new_data_file.hkl' )
Затем вы просто прочитали его и выполните операции:
data2 = hkl.load( 'new_data_file.hkl' )
Вот реализация, которая работает для меня и удаляет все nans (предполагая, что это простой объект (список или 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
Кроме того, некоторая очень интересная информация по спискам против массивов в Python ~ > Python List vs. Array - когда использовать?
Можно заметить, что как только я конвертирую свои массивы в список, прежде чем сохранять его в JSON файле, в моем развертывании сейчас все равно, как только я прочитаю этот файл JSON для использования позже, я могу продолжать использовать его в списке (в отличие от преобразования его в массив).
И на самом деле выглядит лучше (на мой взгляд) на экране как список (разделенный запятой) по сравнению с массивом (без запятой) таким образом.
Используя метод @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')
Надеюсь, это поможет!
json
. Ноnumpy.ndarray
- это не тот тип, с которымjson
знает, как обращаться. Вам нужно будет либо написать свой собственный сериализатор, либо (проще) передатьlist(your_array)
тому, что пишет json.list(your_array)
не всегда будет работать, так как он возвращает целые числа, а не нативные.your_array.to_list()
этого используйтеyour_array.to_list()
.