📜  Java的Count-min 草图和示例

📅  最后修改于: 2021-09-06 11:24:11             🧑  作者: Mango

Count-min 草图是一种概率数据结构。 Count-Min 草图是一种汇总大量频率数据的简单技术。 Count-min 草图算法谈到跟踪事物的数量。即,元素在集合中出现的次数。使用 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 草图算法,这可以优化。

什么是 Count-min 草图,它是如何工作的?
Count-min 草图方法是由Graham CormodeS. Muthukrishnan提出的。在 2011/12 年发表的使用 count-min 草图近似数据的论文中。 Count-minsketch 用于计算流数据上事件的频率。与Bloom filter一样,Count-min 草图算法也适用于哈希码。它使用多个散列函数将这些频率映射到矩阵(考虑在此处绘制二维数组或矩阵)。

让我们一步一步地看下面的例子。

  1. 考虑下面有 4 行 16 列的二维数组,行数也等于散列函数的数量。这意味着我们在示例中采用了四个散列函数。用零初始化/标记矩阵中的每个单元格。
    注意:您想要的结果越准确,要使用的哈希函数的数量就越多。
  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 行的索引 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 草图的问题及其解决方案:
如果一个或多个元素获得相同的散列值,然后它们都增加了怎么办。因此,在这种情况下,由于哈希冲突,该值会增加。因此,有时(在极少数情况下)Count-min 草图由于散列函数而高估了频率。所以我们采用的哈希函数越多,冲突就越少。我们采用的哈希函数越少,碰撞的可能性就越大。因此它总是建议采用更多数量的哈希函数。

Count-min Sketch 的应用:

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

在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 草图是一个不错的选择。我们还看到,我们想要的更准确的结果必须增加哈希函数的数量(行数/宽度)。

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live