我想计算包含Machine Learning数据集的Python类的哈希值。该哈希值用于缓存,因此我考虑的是md5
或sha1
。
问题是大多数数据都存储在NumPy数组中;这些不提供__hash__()
成员。目前,我为每个成员执行pickle.dumps()
并根据这些字符串计算哈希值。但是,我发现以下链接指示同一对象可能导致不同的序列化字符串:
为包含Numpy数组的Python类计算哈希值的最佳方法是什么?
答案 0 :(得分:27)
感谢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'
答案 1 :(得分:3)
数组中的数据格式是什么?难道你不能只是遍历数组,将它们转换成一个字符串(通过一些可重现的方法),然后通过更新将其提供给你的哈希?
e.g。
import hashlib
m = hashlib.md5() # or sha1 etc
for value in array: # array contains the data
m.update(str(value))
不要忘记,numpy数组不会提供__hash__()
,因为它们是可变的。因此,请注意在计算哈希值后不要修改数组(因为它将不再相同)。
答案 2 :(得分:3)
答案 3 :(得分:2)
以下是我在jug中的表达方式(本回答时的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)
相同(如果数组不连续,则会因非描述性类型错误而失败)。
答案 4 :(得分:2)
使用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
答案 5 :(得分:1)
array.data始终是可散列的,因为它是一个缓冲对象。容易:)(除非你关心具有完全相同数据的不同形状的数组之间的差异等等。(即除非形状,字节顺序和其他数组'参数'也必须计入哈希值,否则这是合适的)
答案 6 :(得分:1)
最快的差距似乎是:
散列(ITER(a))的
a是一个numpy ndarray。
显然不是安全散列,但它应该适合缓存等。