Массив NumPy не является сериализуемым JSON
После создания массива NumPy и сохранения его как переменной контекста Django, я получаю следующую ошибку при загрузке веб-страницы:
array([ 0, 239, 479, 717, 952, 1192, 1432, 1667], dtype=int64) is not JSON serializable
Что это значит?
Ответы
Ответ 1
Я регулярно "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)
Ответ 2
Сохраните как 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)
Ответ 3
Вы можете использовать Pandas:
import pandas as pd
pd.Series(your_array).to_json(orient='values')
Ответ 4
Я нашел лучшее решение, если у вас вложенные массивы 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)
Спасибо этому парню.
Ответ 5
Некоторые из других кодировщиков 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)
Ответ 6
Это не поддерживается по умолчанию, но вы можете сделать это довольно легко! Есть несколько вещей, которые вы захотите закодировать, если хотите вернуть те же самые данные:
- Сами данные, которые вы можете получить с помощью
obj.tolist()
, как упомянуто @travelingbones. Иногда это может быть достаточно хорошо.
- Тип данных. Я чувствую, что это важно в некоторых случаях.
- Измерение (не обязательно 2D), которое может быть получено из вышеприведенного, если вы предполагаете, что входные данные действительно всегда являются "прямоangularьной" сеткой.
- Порядок памяти (row- или основной столбец). Это не часто имеет значение, но иногда это имеет значение (например, производительность), так почему бы не сохранить все?
Кроме того, ваш массив может быть частью вашей структуры данных, например, у вас есть список с некоторыми матрицами внутри. Для этого вы можете использовать пользовательский кодировщик, который в основном делает выше.
Этого должно быть достаточно для реализации решения. Или вы можете использовать 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))
Ответ 7
У меня была аналогичная проблема с вложенным словарем с некоторыми 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
Ответ 8
Вы также можете использовать аргумент по default
например:
def myconverter(o):
if isinstance(o, np.float32):
return float(o)
json.dump(data, default=myconverter)
Ответ 9
Кроме того, некоторая очень интересная информация по спискам против массивов в 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')
Надеюсь, это поможет!
Ответ 10
Вот реализация, которая работает для меня и удаляет все 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
Ответ 11
Это другой ответ, но это может помочь людям, которые пытаются сохранить данные, а затем читать их снова.
Существует 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' )
Ответ 12
Может сделать простой цикл с проверкой типов:
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()
Ответ 13
Ошибка типа: массив ([[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! наконец-то получил ожидаемый результат, ![enter image description here]()