2009-04-30 19 views
25

Me gustaría calcular un hash de una clase de Python que contiene un conjunto de datos para Machine Learning. El hash está destinado a ser utilizado para el almacenamiento en caché, por lo que estaba pensando en md5 o sha1. El problema es que la mayoría de los datos se almacenan en matrices NumPy; estos no proporcionan un miembro __hash__(). Actualmente hago un pickle.dumps() para cada miembro y calculo un hash basado en estas cadenas. Sin embargo, he encontrado los siguientes enlaces que indica que el mismo objeto podría dar lugar a diferentes cadenas de serialización:Cómo hash un objeto grande (conjunto de datos) en Python?

¿Cuál sería el mejor método para calcular un hash para una clase de Python que contiene matrices Numpy?

+0

No mucho de un programador experto en python pero, ¿sería serializar el objeto y el hash que funciona? – Louis

Respuesta

3

¿Cuál es el formato de los datos en las matrices? ¿No podría simplemente iterar a través de las matrices, convertirlas en una cadena (a través de algún medio reproducible) y luego alimentar eso en su hash a través de la actualización?

p. Ej.

import hashlib 
m = hashlib.md5() # or sha1 etc 
for value in array: # array contains the data 
    m.update(str(value)) 

No se olvide sin embargo que las matrices numpy no proporcionarán __hash__() porque son mutables. Así que tenga cuidado de no modificar las matrices después de calcular su hash (ya que ya no será el mismo).

+0

Gracias, su publicación me ayudó a resolver este problema. Consulte a continuación ... –

27

Gracias a John Montgomery creo que he encontrado una solución, y creo que tiene menos sobrecarga que convertir cada número en posiblemente enormes matrices de cadenas:

puedo crear un byte-vista de las matrices y utilízalos para actualizar el hash. Y de alguna manera esto parece dar el mismo implícita como la actualización directamente a través de la matriz:

>>> import hashlib 
>>> import numpy 
>>> a = numpy.random.rand(10, 100) 
>>> b = a.view(numpy.uint8) 
>>> print a.dtype, b.dtype # a and b have a different data type 
float64 uint8 
>>> hashlib.sha1(a).hexdigest() # byte view sha1 
'794de7b1316b38d989a9040e6e26b9256ca3b5eb' 
>>> hashlib.sha1(b).hexdigest() # array sha1 
'794de7b1316b38d989a9040e6e26b9256ca3b5eb' 
+0

¿Podrá volver a crear el objeto de la memoria caché con esta técnica? Parece que solo podrás recuperar una matriz de tipo uint8 (sacrificando la precisión de tu matriz). – tgray

+0

Usando la solución de John Montgomery, parece que obtendrías una matriz float64. – tgray

+0

@tgray: a veces no importa tanto la precisión. Los datos experimentales, especialmente los más grandes, tienden a tener grandes incertidumbres de todos modos. Obviamente, esto está sujeto al contexto, pero la regla general es que la precisión doble es importante para el cálculo, no para almacenar los datos o la respuesta final. –

1

array.data es siempre hashable, porque es un objeto de memoria intermedia. fácil :) (a menos que te importe la diferencia entre matrices de formas diferentes con los mismos datos exactos, etc. (esto es adecuado a menos que la forma, el byteorizador y otros "parámetros" de la matriz también figuren en el hash)

+1

array.data no es hashable como numpy 1.6.2 y python 2.7 – yoavram

2

Así es como lo hago en jug (CABEZA git en el momento de esta respuesta):.

e = some_array_object 
M = hashlib.md5() 
M.update('np.ndarray') 
M.update(pickle.dumps(e.dtype)) 
M.update(pickle.dumps(e.shape)) 
try: 
    buffer = e.data 
    M.update(buffer) 
except: 
    M.update(e.copy().data) 

la razón es que e.data sólo está disponible para algunos arreglos (arrays contiguos) lo mismo con a.view(np.uint8) (que falla con un error de tipo no descriptivo si la matriz no es contigua).

3

Allí i s un paquete para memorizar funciones que usan matrices numpy como entradas joblib. Se encontró a partir de la pregunta this.

1

más rápido por cierto margen parece ser:

almohadilla (iter (a))

a es un ndarray numpy.

Obviamente no hash seguro, pero debe ser bueno para el almacenamiento en caché, etc.

+0

En Python 3.3+ no obtendrás los mismos valores hash en diferentes ejecuciones de python, debido a mejoras de seguridad. – xioxox

1

Usando Numpy 1.10.1 y Python 2.7.6, ahora puede simplemente hash de matrices usando numpy hashlib si la matriz es C-contigua (use numpy.ascontiguousarray() si no), por ejemplo

>>> h = hashlib.md5() 
>>> arr = numpy.arange(101) 
>>> h.update(arr) 
>>> print(h.hexdigest()) 
e62b430ff0f714181a18ea1a821b0918 
Cuestiones relacionadas