Cadinality Estimationアルゴリズム学習(一)
8679 ワード
最近は菜鳥教程でredisを独学しています.Redis HyperLogLogを見たとき、「基数」と他の接触したことのないもの(または忘れたもの)に好奇心を持ちました.
そこで「HyperLog Log」を検索して、Cadinality Estimationアルゴリズムとそれを学ぶ時に参考にする文章を引き出しました.
http://blog.codinglabs.org/articles/algorithms-for-cardinality-estimation-part-i.html
文章から見れば、基数とは、集合(ここの集合は重複要素の存在を許可し、集合論の厳密な定義とは少し違っています.特別な説明をしないと、ここで述べた集合は重複要素の存在を許可します.)の異なる要素の個数を指します.
これは「1つの配列の中で重複しない要素の個数を求める」というアルゴリズムと似ています.配列a[10]={1,2,3,4,1,2,3,4,5,6,7}のように、重複しない要素は{1,2,3,4,5,6,7}全部で7つです.その応用シーンについては、例えば、ウェブサイトで「一人」の訪問回数を統計する場合、例えば明ちゃんには「明ちゃん」にマークを付けて、今度訪問する時、総訪問回数はプラスできません.「明ちゃん」ではない人に限って、例えば「麗ちゃん」が訪問して、総訪問回数を増やす.
これは前にやったような計算方法の問題です.統計文字列「abcdaabceedia」の中で重複しない文字の個数です.もちろん、最も簡単な太い爆発の方法は、前のn-1文字を遍歴して比較することです.これは時間の無駄です.文字列はアルファベットだけで、長さ26のハッシュ表を作って、一度文字列を巡回して、読んだ文字をハッシュ表に記入して、最後にハッシュ表を巡回すればいいです.
hash.
bitmap.c
ウェブサイトの統計では、「小明」などのアクセス数の問題は、「小明」をハッシュ関数に導入し、該当するアドレスを見つけて、「訪問済み」と表記することに相当する.統計するときは、ハッシュテーブルのデータ構造に従って巡回したり、bitmapの中の1の個数を計算するなどの方法で統計します.以上は私の個人的な見解で、確率などの実現問題に関わりません.
そこで「HyperLog Log」を検索して、Cadinality Estimationアルゴリズムとそれを学ぶ時に参考にする文章を引き出しました.
http://blog.codinglabs.org/articles/algorithms-for-cardinality-estimation-part-i.html
文章から見れば、基数とは、集合(ここの集合は重複要素の存在を許可し、集合論の厳密な定義とは少し違っています.特別な説明をしないと、ここで述べた集合は重複要素の存在を許可します.)の異なる要素の個数を指します.
これは「1つの配列の中で重複しない要素の個数を求める」というアルゴリズムと似ています.配列a[10]={1,2,3,4,1,2,3,4,5,6,7}のように、重複しない要素は{1,2,3,4,5,6,7}全部で7つです.その応用シーンについては、例えば、ウェブサイトで「一人」の訪問回数を統計する場合、例えば明ちゃんには「明ちゃん」にマークを付けて、今度訪問する時、総訪問回数はプラスできません.「明ちゃん」ではない人に限って、例えば「麗ちゃん」が訪問して、総訪問回数を増やす.
これは前にやったような計算方法の問題です.統計文字列「abcdaabceedia」の中で重複しない文字の個数です.もちろん、最も簡単な太い爆発の方法は、前のn-1文字を遍歴して比較することです.これは時間の無駄です.文字列はアルファベットだけで、長さ26のハッシュ表を作って、一度文字列を巡回して、読んだ文字をハッシュ表に記入して、最後にハッシュ表を巡回すればいいです.
hash.
1 #include
2 #include <string.h>
3
4 int main()
5 {
6 char str[] = "abcdaaabceeda";
7 int hash[26] = {0};
8 int size = strlen(str);
9 int i;
10 for(i = 0; i < size; ++i)
11 {
12 int temp = str[i] - 'a';
13 ++hash[temp];
14 }
15 int num = 0;
16 for(i = 0; i < 26; ++i)
17 {
18 num += hash[i] > 0 ? 1 : 0;
19 }
20 printf("num = %d
", num);
21 }
26文字の小文字を統計するだけであれば、26個のint型のスペースが必要です.bitmapが空間を節約できると思い、それを使って書きました.bitmap.c
1 #include
2 #include <string.h>
3
4 int hamming_weight(unsigned int bitmap)
5 {
6 unsigned int temp = bitmap;
7 temp = (temp & 0x55555555) + ((temp & 0xaaaaaaaa) >> 1);
8 temp = (temp & 0x33333333) + ((temp & 0xcccccccc) >> 2);
9 temp = (temp & 0x0f0f0f0f) + ((temp & 0xf0f0f0f0) >> 4);
10 temp = (temp & 0x00ff00ff) + ((temp & 0xff00ff00) >> 8);
11 temp = (temp & 0x0000ffff) + ((temp & 0xffff0000) >> 16);
12 return temp;
13 }
14
15 int main()
16 {
17 char str[] = "abcdaaabceeda";
18 unsigned int bitmap = 0;
19 int size = strlen(str);
20 int i;
21 for(i = 0; i < size; ++i)
22 {
23 int loc = str[i] - 'a';
24 int temp = 1 << loc;
25 bitmap |= temp;
26 }
27 printf("num = %d
", hamming_weight(bitmap));
28 }
違いはhashでも単一文字の出現回数を統計することができます.bitmapはhamming weightを使って合計回数を統計することができます.ウェブサイトの統計では、「小明」などのアクセス数の問題は、「小明」をハッシュ関数に導入し、該当するアドレスを見つけて、「訪問済み」と表記することに相当する.統計するときは、ハッシュテーブルのデータ構造に従って巡回したり、bitmapの中の1の個数を計算するなどの方法で統計します.以上は私の個人的な見解で、確率などの実現問題に関わりません.