📜  Java的最小计数草图和示例

📅  最后修改于: 2021-04-23 21:24:54             🧑  作者: Mango

最小计数草图是一种概率数据结构。最小计数草图是一种汇总大量频率数据的简单技术。最小计数草图算法讨论有关跟踪事物计数的问题。即元素在集合中存在多少次。使用HashTable或Map在Java可以很容易地找到项目的数量。

尝试使用MultiSet替代Count-min草图
让我们尝试使用带有以下源代码的MultiSet来实现此数据结构,并尝试找出这种方法的问题。

// Java program to try MultiSet as an
// alternative to Count-min sketch
  
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
  
public class MultiSetDemo {
    public static void main(String[] args)
    {
        Multiset blackListedIPs
            = HashMultiset.create();
        blackListedIPs.add("192.170.0.1");
        blackListedIPs.add("75.245.10.1");
        blackListedIPs.add("10.125.22.20");
        blackListedIPs.add("192.170.0.1");
  
        System.out.println(blackListedIPs
                               .count("192.170.0.1"));
        System.out.println(blackListedIPs
                               .count("10.125.22.20"));
    }
}

输出:

了解使用MultiSet的问题
现在,让我们看一下这种方法消耗的时间和空间。

----------------------------------------------
|Number of UUIDs          Insertion Time(ms)  |
----------------------------------------------
|10                         <25               |   
|100                        <25               |
|1, 000                      30               |
|10, 000                     257              |
|100, 000                    1200             |
|1, 000, 000                 4244             |
----------------------------------------------

让我们看一下所消耗的内存(空间):

----------------------------------------------
|Number of UUIDs            JVM heap used(MB) |
----------------------------------------------
|10                         <2                |   
|100                        <2                |
|1, 000                      3                |
|10, 000                     9                |
|100, 000                    39               |
|1, 000, 000                 234              |
-----------------------------------------------

我们可以很容易地理解,随着数据的增长,上述方法正在消耗大量内存和时间来处理数据。如果我们使用最小计数草图算法,可以对此进行优化。

什么是最小计数草图,它是如何工作的?
Count-min草图方法由Graham CormodeS.Muthukrishnan提出2011/12年发布的最小计数草图近似数据。最小计数草图用于计数流数据上事件的频率。像Bloom过滤器一样,Count-min草绘算法也可以与哈希码一起使用。它使用多个哈希函数将这些频率映射到矩阵(此处为二维数组或矩阵的草图)。

让我们逐步看下面的示例。

  1. 考虑下面具有4行16列的2D数组,行数也等于哈希函数的数量。这意味着我们将以四个哈希函数为例。用零初始化/标记矩阵中的每个单元。
    注意:所需的结果越准确,使用的哈希函数越多。
  2. 现在让我们添加一些元素。为此,我们必须将该元素与所有四个哈希函数一起传递,这可能会导致如下结果。
    Input : 192.170.0.1 
    
    hashFunction1(192.170.0.1): 1
    hashFunction2(192.170.0.1): 6
    hashFunction3(192.170.0.1): 3
    hashFunction4(192.170.0.1): 1
    

    现在访问由所有四个哈希函数检索到的索引,并将它们标记为1。

  3. 类似地,通过将第二个输入传递给所有四个哈希函数来处理第二个输入。
    Input : 75.245.10.1 
    
    hashFunction1(75.245.10.1): 1
    hashFunction2(75.245.10.1): 2
    hashFunction3(75.245.10.1): 4
    hashFunction4(75.245.10.1): 6
    

    现在,如果已将给定索引标记为1,则获取这些索引并访问矩阵。这称为碰撞,这意味着该行的索引已被先前的某些输入标记,在这种情况下,索引值没有影响在本例中,由于我们已经将第1行的索引1(即hashFunction1())由先前的输入标记为1,所以这次它将被减1,现在此单元格条目将为2,但对于其余部分其余行的索引将为0,因为没有冲突。

  4. 让我们处理下一个输入
    Input : 10.125.22.20 
    
    hashFunction1(10.125.22.20): 3
    hashFunction2(10.125.22.20): 4
    hashFunction3(10.125.22.20): 1
    hashFunction4(10.125.22.20): 6
    

    让我们将其表示在矩阵上,如果已经存在某些条目,请记住将计数加1。

  5. 类似地处理下一个输入。
    Input : 192.170.0.1 
    
    hashFunction1(192.170.0.1): 1
    hashFunction2(192.170.0.1): 6
    hashFunction3(192.170.0.1): 3
    hashFunction4(192.170.0.1): 1
    

    让我们看一下矩阵表示。

现在让我们测试一些元素并检查它们存在多少时间。

  1. Test Input #1: 192.170.0.1 
    

    将上面的输入传递给所有四个哈希函数,并获取由哈希函数生成的索引号。

    hashFunction1(192.170.0.1): 1
    hashFunction2(192.170.0.1): 6
    hashFunction3(192.170.0.1): 3
    hashFunction4(192.170.0.1): 1
    

    现在访问每个索引并记下该索引上存在的条目

    因此,每个索引的最终条目是3,2,2,2 。现在,将这些条目中的最小数量作为结果。所以min(3,2,2,2)为2,这意味着上面的测试输入在上面的列表中被处理了两次。

  2. Test Input #1: 10.125.22.20 
    

    将上面的输入传递给所有四个哈希函数,并获取由哈希函数生成的索引号。

    hashFunction1(10.125.22.20): 3
    hashFunction2(10.125.22.20): 4
    hashFunction3(10.125.22.20): 1
    hashFunction4(10.125.22.20): 6
    

    现在访问每个索引并记下该索引上存在的条目

    因此,每个索引的最终条目是1,1,1,2 。现在,将这些条目中的最小数量作为结果。所以min(1,1,1,2)为1,这意味着上面的测试输入仅在上面的列表中处理一次。

Count-min草图及其解决方案的问题:
如果一个或多个元素具有相同的哈希值,然后它们都增加,该怎么办?因此,在那种情况下,该值将由于哈希冲突而增加。因此,有时(在极少数情况下)由于哈希函数的原因,最小计数草图会高估频率。因此,我们采用的哈希函数越多,冲突就越少。我们采用的哈希函数越少,发生冲突的可能性就越大。因此,它总是建议采用更多数量的哈希函数。

数分钟草图的应用:

  • 压缩感测
  • 联网
  • 自然语言处理
  • 流处理
  • 频率追踪
  • 扩展:重击者
  • 扩展:范围查询

使用Java的Guava库实现Count-min草图的实现:
我们可以使用Guava提供的Java库来实现Count-min草图。以下是分步实施:

  1. 使用以下Maven依赖项。
    
        com.clearspring.analytics
        stream
        2.9.5
    
    
  2. 详细的Java代码如下:
    import com.clearspring.analytics
        .stream.frequency.CountMinSketch;
      
    public class CountMinSketchDemo {
        public static void main(String[] args)
        {
            CountMinSketch countMinSketch
                = new CountMinSketch(
                    // epsilon
                    0.001,
                    // delta
                    0.99,
                    // seed
                    1);
      
            countMinSketch.add("75.245.10.1", 1);
            countMinSketch.add("10.125.22.20", 1);
            countMinSketch.add("192.170.0.1", 2);
      
            System.out.println(
                countMinSketch
                    .estimateCount(
                        "192.170.0.1"));
            System.out.println(
                countMinSketch
                    .estimateCount(
                        "999.999.99.99"));
        }
    }
    

  3. 上面的示例在构造函数中使用了三个参数,分别是
    - 0.001 = the epsilon i.e., error rate
    - 0.99 = the delta i.e., confidence or accuracy rate
    - 1 = the seed
    
  4. 现在,让我们看一下这种方法消耗的时间和空间。
    -----------------------------------------------------------------------------
    |Number of UUIDs | Multiset Insertion Time(ms)  | CMS Insertion Time(ms)    |
    -----------------------------------------------------------------------------
    |10                         <25                   35                        |   
    |100                        <25                   30                        |
    |1, 000                      30                   69                        |
    |10, 000                     257                  246                       |
    |100, 000                    1200                 970                       |
    |1, 000, 000                 4244                 4419                      |
    -----------------------------------------------------------------------------
    
  5. 现在,让我们看一下所消耗的内存:
    --------------------------------------------------------------------------
    |Number of UUIDs | Multiset JVM heap used(MB) | CMS JVM heap used(MB)    | 
    --------------------------------------------------------------------------
    |10                         <2                   N/A                     |   
    |100                        <2                   N/A                     |
    |1, 000                      3                   N/A                     |
    |10, 000                     9                   N/A                     |
    |100, 000                    39                  N/A                     |
    |1, 000, 000                 234                 N/A                     |
    ---------------------------------------------------------------------------
    
  6. 意见建议:
    -------------------------------------------------------------------------------------
    |Epsilon  | Delta  | width/Row (hash functions)| Depth/column| CMS JVM heap used(MB) |
    -------------------------------------------------------------------------------------
    |0.1      |0.99    |         7                 | 20          |   0.009               |
    |0.01     |0.999   |         10                | 100         |   0.02                |
    |0.001    |0.9999  |         14                | 2000        |   0.2                 |
    |0.0001   |0.99999 |         17                | 20000       |   2                   | 
    --------------------------------------------------------------------------------------
    

结论:

我们已经观察到,在必须以低内存消耗处理大量数据的情况下,Count-min草图是一个不错的选择。我们还看到,更精确的结果是我们需要增加哈希函数(行/宽度)的数量。