【问题标题】:Are overlapping sub-arrays of a byte array independent enough to use as hash function(s) for Bloom Filter?字节数组的重叠子数组是否足够独立以用作布隆过滤器的哈希函数?
【发布时间】:2011-07-11 20:30:32
【问题描述】:

在 BloomFilter 的上下文中,我有以下问题。 BloomFilters 需要有k 独立的哈希函数。我们称这些函数为h1, h2, ... hk。在这种情况下,独立意味着当应用于同一集合时,它们的值几乎没有相关性(希望为零)。请参阅 http://en.wikipedia.org/wiki/Bloom_filter 的算法说明(当然,您已经完全了解该页面了 :)。

现在,假设我想使用一些 n 位(如果您必须知道,来自加密函数,但它与问题无关)来定义我的哈希函数,它们彼此独立。如果你想要更多的上下文,你可以阅读http://bitworking.org/news/380/bloom-filter-resources,它正在做类似的事情。

例如,假设我想将每个 h 定义为(请原谅我的伪代码):

bytes = MD5(value)
h1 = bytes[0-3] as Integer
h2 = bytes[4-7] as Integer
h3 = bytes[8-11] as Integer
...

当然,我们很快就会用完散列函数。在这个 MD5 示例中,我们只得到了四个。

一种可能性是让散列函数相互重叠,而不要求四个字节是连续的。这样我们就有了许多哈希函数作为字节数组允许的排列。为简单起见,如果我们按以下方式定义哈希函数会怎样:

bytes = MD5(value)
h1 = bytes[0-3] as Integer
h2 = bytes[1-4] as Integer
h3 = bytes[2-5] as Integer
...

很容易看出,在 MD5 的情况下,现在我们有 12 个散列函数而不是 4 个。

最后,我们来到THE问题。这些散列函数是独立的吗?谢谢!

更新:我决定尝试从实际的角度来回答这个问题,所以我创建了一个小程序来测试这个假设。见下文。

【问题讨论】:

    标签: statistics correlation bloom-filter


    【解决方案1】:

    就像聪明的问题经常出现的情况一样,答案是肯定的,也不是。

    是的,从某种意义上说,h1 和 h2 之间没有共享 16 位。不,在对你来说很重要的意义上(除非你实际上只使用了八位散列函数,我认为你不是)。

    这里的问题在于应用于被插入的同一个项目的两个函数之间的依赖性较少,而更多的是(在我看来,在这种情况下)函数应用于多个项目。

    这样想。假设您的第一个示例使用 g1-g4,第二个示例使用 h1-h4。如果仅使用 h1 和 h2、h2 和 h3,MD5sum(或任何其他散列函数)仅在 5 个连续字节中重叠的两个项目(不太可能,但统计上可行,尤其是如果您正在尝试)将有可能发生碰撞,或 h3 和 h4。同时 g1-g4 对这种可能性是稳健的。

    现在与布隆过滤器的冲突并不像散列函数的其他应用那么重要,但您应该记住,重叠字节确实会降低散列函数的实用性。老实说,您需要四个以上的独立哈希函数,这让我有点惊讶。

    另外,如果您只使用每个数字的最后 8 位(256 位布隆过滤器)或最后 16 位(2^16 位布隆过滤器),或者其他什么,那么您可以“重叠”那些你不是在鲁莽放弃并且没有风险的情况下使用。

    免责声明: 我非常了解密码学和布隆过滤器,因为它们非常棒,但是我对布隆过滤器的实际知识是有限的;您所描述的内容可能非常适合您的用例。

    【讨论】:

    • 感谢您的回答。我想我理解你所描述的权衡。但是,我不确定我是否理解您关于哈希冲突的观点。在我给出的示例中,字节来自 MD5,但它们也可以来自 Java 的 Random.nextBytes 函数。在这种情况下,问题是:当我们生成一个序列字节数组b1, b2, b3 ...并将子链解释为整数(例如b2[3-7])时,两个子链的相关系数是高还是低?
    【解决方案2】:

    运行下面的程序将使用随机数生成器测试假设。

    public static void main(String[] args) {
        int R = 100, N = 10000, W = 8;
        double[] totals = new double[33];
        Random r = new Random();
    
        for (int k = 0; k < R; k++) {
            // Generate 10,000 random byte arrays
            byte[][] bytes = new byte[N][W];
            for (int i = 0; i < N; i++) r.nextBytes(bytes[i]);
    
            double[] a1 = new double[N], a2 = new double[N];
            for (int i = 0; i <= 32; i++) {
    
                // Extract arrays
                for (int j = 0; j < N; j++) {
                    a1[j] = readInt(bytes[j], 0, 31);
                    a2[j] = readInt(bytes[j], 32 - i, 31);
                }
    
                double c = (new PearsonsCorrelation()).correlation(a1, a2);
                totals[i] += c;
            }
        }
    }
    

    有趣的位是只有当只有一个重叠位时,相关性才开始显着。下面是每个重叠位数的 pearson 相关系数。我们从很低(意味着接近0 重叠的情况)开始,并在它们完全重叠时得到1

    0   -0.001883705757299319
    1   -0.0019261826793995395
    2   -0.0018466135577488883
    3   -0.001499114477250019
    4   -0.0010874727770462341
    5   -1.1219111699336884E-5
    6   -0.001760700583842139
    7   3.6545455908216937E-4
    8   0.0014823972050436482
    9   0.0014809963180788554
    10  0.0015226692114697182
    11  0.00199027499920776
    12  0.001720451344380218
    13  -2.0219121772336676E-4
    14  6.880004078769847E-4
    15  8.605949344202965E-4
    16  -0.0025640320027890645
    17  -0.002552269654230886
    18  -0.002550425130285998
    19  -0.002522446787072504
    20  -0.00320337678141518
    21  -7.554573868921899E-4
    22  -6.463448718890875E-4
    23  -3.4709181348336335E-4
    24  0.0038077518094915912
    25  0.0037865326140343815
    26  0.0038728464390708982
    27  0.0035091958914765407
    28  0.005099109955591643
    29  0.016993434043779915
    30  0.06120260114179265
    31  0.25159073855202346
    32  1.0
    

    底线:对于散列函数的生成,似乎移位一个字节(即上面的 24 值)应该是相当安全的。

    【讨论】:

      猜你喜欢
      • 2017-02-11
      • 1970-01-01
      • 2014-11-10
      • 2018-07-21
      • 2012-03-03
      • 2012-08-10
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多