Python 如何散列numpy数组以检查重复项

Python 如何散列numpy数组以检查重复项,python,arrays,numpy,hash,Python,Arrays,Numpy,Hash,我已经搜索了一些教程等,以帮助解决这个问题,但似乎找不到任何东西 我有两个n维numpy数组列表(一些图像的3D数组形式),我想检查每个列表中的重叠图像。让我们说列表a是一个训练集,列表b是一个验证集。 一种解决方案是使用嵌套循环,并使用np.array(a[i],b[j])检查每对数组是否相等,但这很慢(每个列表中大约有200000个numpy数组),坦白说,这相当令人厌恶 我在想实现这一点的一种更优雅的方法是对每个列表中的每个numpy数组进行散列,然后使用这些散列表比较每个条目 首先,此解

我已经搜索了一些教程等,以帮助解决这个问题,但似乎找不到任何东西

我有两个n维numpy数组列表(一些图像的3D数组形式),我想检查每个列表中的重叠图像。让我们说列表a是一个训练集,列表b是一个验证集。 一种解决方案是使用嵌套循环,并使用
np.array(a[i],b[j])
检查每对数组是否相等,但这很慢(每个列表中大约有200000个numpy数组),坦白说,这相当令人厌恶

我在想实现这一点的一种更优雅的方法是对每个列表中的每个numpy数组进行散列,然后使用这些散列表比较每个条目

首先,此解决方案正确吗?其次,我将如何实现此目标?
下面是一些数据的示例

train_dataset[:3]
array([[[-0.5       , -0.49607843, -0.5       , ..., -0.5       ,
         -0.49215686, -0.5       ],
        [-0.49607843, -0.47647059, -0.5       , ..., -0.5       ,
         -0.47254902, -0.49607843],
        [-0.49607843, -0.49607843, -0.5       , ..., -0.5       ,
         -0.49607843, -0.49607843],
        ..., 
        [-0.49607843, -0.49215686, -0.5       , ..., -0.5       ,
         -0.49215686, -0.49607843],
        [-0.49607843, -0.47647059, -0.5       , ..., -0.5       ,
         -0.47254902, -0.49607843],
        [-0.5       , -0.49607843, -0.5       , ..., -0.5       ,
         -0.49607843, -0.5       ]],

       [[-0.5       , -0.5       , -0.5       , ...,  0.48823529,
          0.5       ,  0.1509804 ],
        [-0.5       , -0.5       , -0.5       , ...,  0.48431373,
          0.14705883, -0.32745099],
        [-0.5       , -0.5       , -0.5       , ..., -0.32745099,
         -0.5       , -0.49607843],
        ..., 
        [-0.5       , -0.44901961,  0.1509804 , ..., -0.5       ,
         -0.5       , -0.5       ],
        [-0.49607843, -0.49607843, -0.49215686, ..., -0.5       ,
         -0.5       , -0.5       ],
        [-0.5       , -0.49607843, -0.48823529, ..., -0.5       ,
         -0.5       , -0.5       ]],

       [[-0.5       , -0.5       , -0.5       , ..., -0.5       ,
         -0.5       , -0.5       ],
        [-0.5       , -0.5       , -0.5       , ..., -0.5       ,
         -0.5       , -0.5       ],
        [-0.5       , -0.5       , -0.49607843, ..., -0.5       ,
         -0.5       , -0.5       ],
        ..., 
        [-0.5       , -0.5       , -0.5       , ..., -0.48823529,
         -0.5       , -0.5       ],
        [-0.5       , -0.5       , -0.5       , ..., -0.5       ,
         -0.5       , -0.5       ],
        [-0.5       , -0.5       , -0.5       , ..., -0.5       ,
         -0.5       , -0.5       ]]], dtype=float32)

我提前感谢您的帮助。

您可以使用numpy(一维集相交)功能在阵列之间找到重复项

duplicate_images = np.intersect1d(train_dataset, test_dataset) 
我使用训练集和测试集(分别为55000和10000个数组)对此进行计时,我猜其中一个数组和您的数据类似。使用intersect1d,在我的机器上完成大约需要2.4秒(参数为
假设_unique=True
,只需要1.3秒)。像你描述的两两比较花了几分钟

编辑

正如@mbhall88在评论中指出的那样,这个答案(如上)并不比较每个“图像”数组,而是比较数组中的元素,而不是数组本身。为了确保它能够比较数组,您仍然可以使用
intersect1d
,但您必须首先按照说明处理数据类型。但是,该答案中的示例涉及二维阵列,因为您使用的是三维阵列,所以应该首先展平第二个二维。您应该能够执行以下操作:

def intersect3d(A,B, assume_unique=False):
    # get the original shape of your arrays
    a1d, a2d, a3d = A.shape
    # flatten the 2nd and 3rd dimensions in your arrays
    A = A.reshape((a1d,a2d*a3d))
    B = B.reshape((len(B),a2d*a3d))
    # define a structured dtype so you can treat your arrays as single "element"
    dtype=(', '.join([str(A.dtype)]*ncols))
    # find the duplicate elements
    C = np.intersect1d(A.view(dtype), B.view(dtype), assume_unique=assume_unique)
    # reshape the result and return
    return C.view(A.dtype).reshape(-1, ncols).reshape((len(C),a2d,a3d))
该软件包(diclaimer:我是它的作者)有一个高效的单行程序:

import numpy_indexed as npi
duplicate_images = npi.intersection(train_dataset, test_dataset) 

加上许多相关函数,您可能会发现这些函数在本文中很有用。

想出一些东西并不难:

但请注意:

  • 检查浮点相等性通常是个坏主意,因为精度和舍入误差有限。著名的例子:

    >>> 0.1 + 0.2 == 0.3
    False
    
  • NaN的不可与自己相比:

    >>> np.nan == np.nan
    False
    
  • 上面的简单散列函数考虑浮点数的位表示,但在存在负零和信号NaN的情况下,这是有问题的


另请参见此问题中的讨论:

向我们展示一下您在成对比较中所做的工作。我不知道在这种情况下你所说的恶心是什么意思。参见最近的。还可以看看关于唯一行或排序行的问题。基本上我是这样尝试的:
duplicates=[]在train_数据集中为i:在有效的_数据集中为j:duplicates.append(np.equal(i,j)
对于格式设置很抱歉,这些注释很奇怪。
np.equal
如何使用浮点数执行?通常我们建议在测试浮点数数组时使用
np.allclose
。(或
np.isclose
)显然不是很好,因为我让它运行了大约30分钟,但它还没有完成哈哈。我现在将尝试这两个选项。这种方法的问题是它会在数组中找到相同的元素。我感兴趣的是哪些数组是相同的,即数组中的所有元素都完全相同,而不仅仅是一个元素。哟你完全正确。我相信这说明了如何按你需要的方式使用intersect1d。我也会用链接更新答案。
>>> np.nan == np.nan
False