После создания массива NumPy и сохранения его как переменной контекста Django, я получаю следующую ошибку при загрузке веб-страницы:
array([ 0, 239, 479, 717, 952, 1192, 1432, 1667], dtype=int64) is not JSON serializable
Что это значит?
После создания массива 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)
Сохраните как 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)
Спасибо этому парню.
Некоторые из других кодировщиков NumPy кажутся слишком многословными.
Используйте json.dumps
default
kwarg:
default должна быть функция, которая вызывается для объектов, которые иначе не могут быть сериализованы.
В функции default
проверьте, является ли объект из модуля numpy, если это так, либо используйте ndarray.tolist
для ndarray
, либо используйте .item
для любого другого конкретного типа numpy.
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()
, как упомянуто @travelingbones. Иногда это может быть достаточно хорошо.Кроме того, ваш массив может быть частью вашей структуры данных, например, у вас есть список с некоторыми матрицами внутри. Для этого вы можете использовать пользовательский кодировщик, который в основном делает выше.
Этого должно быть достаточно для реализации решения. Или вы можете использовать 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)
Кроме того, некоторая очень интересная информация по спискам против массивов в 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')
Надеюсь, это поможет!
Вот реализация, которая работает для меня и удаляет все 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
Это другой ответ, но это может помочь людям, которые пытаются сохранить данные, а затем читать их снова.
Существует 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' )
Может сделать простой цикл с проверкой типов:
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()
Ошибка типа: массив ([[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)