¿Cómo hash un objeto grande (conjunto de datos) en Python?

Me gustaría calcular un hash de una clase de Python que contiene un conjunto de datos para el aprendizaje automático. El hash está destinado a ser utilizado para el almacenamiento en caché, así 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 __hash__() . Actualmente hago un pickle.dumps() para cada miembro y calculo un hash basado en estas cadenas. Sin embargo, encontré los siguientes enlaces que indican que el mismo objeto podría llevar a diferentes cadenas de serialización:

  • Hash of None varía según la máquina
  • Pickle.dumps no es adecuado para el hashing

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

Gracias a John Montgomery, creo que he encontrado una solución, y creo que tiene menos gastos generales que convertir todos los números en arreglos posiblemente enormes en cadenas:

Puedo crear una vista de bytes de los arreglos y usarlos para actualizar el hash. Y de alguna manera, esto parece dar el mismo resumen que la actualización directa utilizando 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' 

¿Cuál es el formato de los datos en las matrices? ¿No podría simplemente recorrer las matrices, convertirlas en una cadena (a través de algunos medios reproducibles) y luego introducirlas 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)) 

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

Hay un paquete para las funciones de memoria que utilizan matrices numpy como entradas de datos . Encontrado de esta pregunta.

Así es como lo hago en una jarra (git HEAD 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 solo está disponible para algunas matrices (matrices contiguas). Lo mismo a.view(np.uint8) con a.view(np.uint8) (que falla con un error de tipo no descriptivo si la matriz no es contigua).

Usando Numpy 1.10.1 y python 2.7.6, ahora puede simplemente hash numerar las matrices usando 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 

array.data siempre es hashable, porque es un objeto de búfer. fácil 🙂 (a menos que le importe la diferencia entre matrices de formas diferentes con los mismos datos, etc.) (es decir, esto es adecuado a menos que la forma, el byteorder y otros ‘parámetros’ de la matriz también deban figurar en el hash)

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

hash (iter (a))

a es un ndarray numpy.

Obviamente no es un hash seguro, pero debería ser bueno para el almacenamiento en caché, etc.