python - transpuesta - numpy tutorial español pdf
¿Cómo puedo serializar una matriz numpy mientras preservo las dimensiones de la matriz? (7)
numpy.array.tostring
no parece conservar información sobre las dimensiones de la matriz (consulte esta pregunta ), lo que requiere que el usuario numpy.array.reshape
una llamada a numpy.array.reshape
.
¿Hay alguna manera de serializar una matriz numpy a formato JSON mientras se conserva esta información?
Nota: Las matrices pueden contener ints, flotadores o bools. Es razonable esperar una matriz transpuesta.
Nota 2: esto se está haciendo con la intención de pasar la matriz numpy a través de una topología Storm utilizando streamparse, en caso de que dicha información sea relevante.
Encontré el código en Msgpack-numpy útil. https://github.com/lebedov/msgpack-numpy/blob/master/msgpack_numpy.py
Modifiqué ligeramente el dictado serializado y agregué codificación base64 para reducir el tamaño serializado.
Al utilizar la misma interfaz que json (que proporciona carga (s), volcado (s)), puede proporcionar un reemplazo directo para la serialización de json.
Esta misma lógica se puede ampliar para agregar cualquier serialización no trivial automática, como los objetos de fecha y hora.
EDITAR He escrito un analizador genérico, modular, que hace esto y más. https://github.com/someones/jaweson
Mi código es el siguiente:
np_json.py
from json import *
import json
import numpy as np
import base64
def to_json(obj):
if isinstance(obj, (np.ndarray, np.generic)):
if isinstance(obj, np.ndarray):
return {
''__ndarray__'': base64.b64encode(obj.tostring()),
''dtype'': obj.dtype.str,
''shape'': obj.shape,
}
elif isinstance(obj, (np.bool_, np.number)):
return {
''__npgeneric__'': base64.b64encode(obj.tostring()),
''dtype'': obj.dtype.str,
}
if isinstance(obj, set):
return {''__set__'': list(obj)}
if isinstance(obj, tuple):
return {''__tuple__'': list(obj)}
if isinstance(obj, complex):
return {''__complex__'': obj.__repr__()}
# Let the base class default method raise the TypeError
raise TypeError(''Unable to serialise object of type {}''.format(type(obj)))
def from_json(obj):
# check for numpy
if isinstance(obj, dict):
if ''__ndarray__'' in obj:
return np.fromstring(
base64.b64decode(obj[''__ndarray__'']),
dtype=np.dtype(obj[''dtype''])
).reshape(obj[''shape''])
if ''__npgeneric__'' in obj:
return np.fromstring(
base64.b64decode(obj[''__npgeneric__'']),
dtype=np.dtype(obj[''dtype''])
)[0]
if ''__set__'' in obj:
return set(obj[''__set__''])
if ''__tuple__'' in obj:
return tuple(obj[''__tuple__''])
if ''__complex__'' in obj:
return complex(obj[''__complex__''])
return obj
# over-write the load(s)/dump(s) functions
def load(*args, **kwargs):
kwargs[''object_hook''] = from_json
return json.load(*args, **kwargs)
def loads(*args, **kwargs):
kwargs[''object_hook''] = from_json
return json.loads(*args, **kwargs)
def dump(*args, **kwargs):
kwargs[''default''] = to_json
return json.dump(*args, **kwargs)
def dumps(*args, **kwargs):
kwargs[''default''] = to_json
return json.dumps(*args, **kwargs)
Deberías poder hacer lo siguiente:
import numpy as np
import np_json as json
np_data = np.zeros((10,10), dtype=np.float32)
new_data = json.loads(json.dumps(np_data))
assert (np_data == new_data).all()
Intente usar numpy.array_repr
o numpy.array_str
.
Msgpack tiene el mejor rendimiento de serialización: http://www.benfrederickson.com/dont-pickle-your-data/
Utilice msgpack-numpy. Consulte https://github.com/lebedov/msgpack-numpy
Instalarlo:
pip install msgpack-numpy
Entonces:
import msgpack
import msgpack_numpy as m
import numpy as np
x = np.random.rand(5)
x_enc = msgpack.packb(x, default=m.encode)
x_rec = msgpack.unpackb(x_enc, object_hook=m.decode)
Pruebe traitschema
https://traitschema.readthedocs.io/en/latest/
"Cree un esquema serializable y con verificación de tipo usando rasgos y Numpy. Un caso de uso típico implica guardar varios arreglos Numpy de formas y tipos diferentes".
Si necesita ser legible para humanos y sabe que esta es una matriz numpy:
import numpy as np;
import json;
a = np.random.normal(size=(50,120,150))
a_reconstructed = np.asarray(json.loads(json.dumps(a.tolist())))
print np.allclose(a,a_reconstructed)
print (a==a_reconstructed).all()
Tal vez no sea el más eficiente, ya que los tamaños de las matrices aumentan de tamaño, pero funcionan para matrices más pequeñas.
pickle.dumps
o numpy.save
codifican toda la información necesaria para reconstruir una matriz NumPy arbitraria, incluso en presencia de problemas de endianidad, matrices no contiguas o tipos de tuplas extraños. Los problemas de endianness son probablemente los más importantes; no desea que la array([1])
se convierta repentinamente en array([16777216])
porque cargó su matriz en una máquina big-endian. pickle
es probablemente la opción más conveniente, aunque save
tiene sus propios beneficios, dados en el formato del formato npy
.
La opción de pickle
:
import pickle
a = # some NumPy array
serialized = pickle.dumps(a, protocol=0) # protocol 0 is printable ASCII
deserialized_a = pickle.loads(serialized)
numpy.save
usa un formato binario, y necesita escribir en un archivo, pero puede StringIO
con StringIO
:
a = # any NumPy array
memfile = StringIO.StringIO()
numpy.save(memfile, a)
memfile.seek(0)
serialized = json.dumps(memfile.read().decode(''latin-1''))
# latin-1 maps byte n to unicode code point n
Y para deserializar:
memfile = StringIO.StringIO()
memfile.write(json.loads(serialized).encode(''latin-1''))
memfile.seek(0)
a = numpy.load(memfile)
EDITAR: Como se puede leer en los comentarios de la pregunta, esta solución trata con matrices numpy "normales" (flotadores, ints, bools ...) y no con matrices estructuradas de tipo múltiple.
Solución para serializar una matriz numpy de cualquier dimensión y tipo de datos
Por lo que sé, no puede simplemente serializar una matriz numpy con cualquier tipo de datos y cualquier dimensión ... pero puede almacenar su tipo de datos, dimensión e información en una representación de lista y luego serializarlos utilizando JSON.
Importaciones necesarias :
import json
import base64
Para la codificación que podría usar ( nparray
es una matriz numpy de cualquier tipo de datos y cualquier dimensionalidad):
json.dumps([str(nparray.dtype), base64.b64encode(nparray), nparray.shape])
Después de esto, obtiene un volcado JSON (cadena) de sus datos, que contiene una representación de la lista de su tipo y forma de datos, así como los arreglos de datos / contenidos codificados en base64.
Y para decodificar esto funciona ( encStr
es la cadena JSON codificada, cargada desde algún lugar):
# get the encoded json dump
enc = json.loads(encStr)
# build the numpy data type
dataType = numpy.dtype(enc[0])
# decode the base64 encoded numpy array data and create a new numpy array with this data & type
dataArray = numpy.frombuffer(base64.decodestring(enc[1]), dataType)
# if the array had more than one data set it has to be reshaped
if len(enc) > 2:
dataArray.reshape(enc[2]) # return the reshaped numpy array containing several data sets
Los volcados JSON son eficientes y compatibles entre sí por muchas razones, pero solo tomar JSON conduce a resultados inesperados si desea almacenar y cargar matrices numpy de cualquier tipo y cualquier dimensión .
Esta solución almacena y carga numerosos arreglos independientemente del tipo o dimensión y también la restaura correctamente (tipo de datos, dimensión, ...)
Probé varias soluciones hace algunos meses y esta fue la única solución eficiente y versátil que encontré.