我想计算一个包含机器学习数据集的 Python 类的哈希值。哈希是用来缓存的,所以我在想md5
or sha1
。问题是大部分数据都存储在 NumPy 数组中;这些不提供__hash__()
成员。目前我pickle.dumps()
为每个成员做一个并根据这些字符串计算一个哈希值。但是,我发现以下链接表明同一个对象可能导致不同的序列化字符串:
为包含 Numpy 数组的 Python 类计算哈希的最佳方法是什么?
感谢 John Montgomery,我想我找到了一个解决方案,而且我认为它比将可能巨大的数组中的每个数字转换为字符串的开销更少:
我可以创建数组的字节视图并使用它们来更新哈希。不知何故,这似乎给出了与使用数组直接更新相同的摘要:
>>> 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'
数组中数据的格式是什么?您不能只遍历数组,将它们转换为字符串(通过一些可重现的方式),然后通过更新将其输入您的散列吗?
例如
import hashlib
m = hashlib.md5() # or sha1 etc
for value in array: # array contains the data
m.update(str(value))
不要忘记尽管 numpy 数组不会提供__hash__()
,因为它们是可变的。因此,请注意不要在计算哈希后修改数组(因为它将不再相同)。
使用 Numpy 1.10.1 和 python 2.7.6,如果数组是 C 连续的(如果不是,则使用),您现在可以使用 hashlib 简单地散列 numpy 数组numpy.ascontiguousarray()
,例如
>>> h = hashlib.md5()
>>> arr = numpy.arange(101)
>>> h.update(arr)
>>> print(h.hexdigest())
e62b430ff0f714181a18ea1a821b0918
这是我在水罐中的做法(回答时为 git HEAD):
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)
原因是它e.data
仅适用于某些数组(连续数组)。同样的事情a.view(np.uint8)
(如果数组不连续,则会失败并出现非描述性类型错误)。
最快的似乎是:
哈希(迭代(a))
a 是一个 numpy ndarray。
显然不安全散列,但它应该有利于缓存等。
array.data 始终是可散列的,因为它是一个缓冲区对象。容易:)(除非您关心具有完全相同数据的不同形状数组之间的差异等。(即这是合适的,除非形状、字节顺序和其他数组“参数”也必须计入散列)