HyperLogLog algoritması nasıl çalışır?


172

Son zamanlarda boş zamanlarımda farklı algoritmalar hakkında bilgi edindim ve karşılaştığım çok ilginç görünen HyperLogLog algoritması deniyor - bu da bir listede kaç benzersiz öğenin olduğunu tahmin ediyor.

Bu benim için özellikle ilginçti çünkü beni "Kardinalite" değerini gördüğümde MySQL günlerime geri getirdi (ki her zaman yakın zamana kadar tahmin edilmediği hesaplandı).

Bu yüzden bir dizide kaç benzersiz öğe olduğunu hesaplayacak O ( n ) bir algoritma yazma biliyorum . Bunu JavaScript ile yazdım:

function countUniqueAlgo1(arr) {
    var Table = {};
    var numUnique = 0;
    var numDataPoints = arr.length;
    for (var j = 0; j < numDataPoints; j++) {
        var val = arr[j];
        if (Table[val] != null) {
            continue;
        }
        Table[val] = 1;
        numUnique++;
    }
    return numUnique;
}

Ama sorun şu ki, algoritmam O ( n ) iken çok fazla bellek kullanıyor (değerleri depolamak Table).

O ( n ) zamanında bir listede kopyaları saymak ve en az bellek kullanarak bu makaleyi okudum .

Bitleri ya da bir şeyi hash ve sayarak belirli bir olasılık içinde (listenin eşit olarak dağıtıldığı varsayılarak) bir listedeki benzersiz öğelerin sayısını tahmin edebileceğini açıklar.

Makaleyi okudum ama anlayamıyorum. Birisi daha katliamın açıklamasını verebilir mi? Karmaların ne olduğunu biliyorum, ancak bu HyperLogLog algoritmasında nasıl kullanıldıklarını anlamıyorum.


4
Bu makale ( Research.google.com/pubs/pub40671.html ) HyperLogLog algoritmasını ve bazı geliştirmeleri de özetlemektedir. Anlamak orijinal kağıttan daha kolay.
zhanxw

11
İsimlendirmeye ilişkin bir ipucu: Bazı insanlar, benzersiz öğelerden oluşan bir koleksiyonu tanımlamak için set kelimesini kullanır . Onlar için, liste veya dizi terimini kullandıysanız, sorunuz daha anlamlı olabilir.
Paddy3118

Yanıtlar:


153

Bu algoritmanın arkasındaki ana hile, rastgele tamsayıların bir akışını gözlemlerseniz, bilinen bir önekle ikili gösterimin başladığı bir tamsayıyı görürseniz, akışın kardinalitesinin 2 ^ (önekin boyutu) olma olasılığı daha yüksektir. .

Yani, rastgele bir tamsayı akışında, sayıların ~% 50'si (ikili olarak) "1" ile başlar,% 25'i "01" ile başlar,% 12,5'i "001" ile başlar. Bu, rastgele bir akış gözlemlerseniz ve bir "001" görürseniz, bu akışın 8'lik bir kardinaliteye sahip olma şansının daha yüksek olduğu anlamına gelir.

("00..1" önekinin özel bir anlamı yoktur. Bunun nedeni, çoğu işlemcideki ikili sayıdaki en önemli biti bulmak kolay olmasıdır.)

Tabii ki, sadece bir tamsayıyı gözlemlerseniz, bu değerin yanlış olma olasılığı yüksektir. Bu nedenle algoritma akışı "m" bağımsız alt akışlara böler ve her alt akışın görünen "00 ... 1" önekinin maksimum uzunluğunu korur. Daha sonra, her bir alt akışın ortalama değerini alarak nihai değeri tahmin eder.

Bu algoritmanın ana fikri budur. Bazı eksik ayrıntılar vardır (örneğin, düşük tahmin değerlerinin düzeltilmesi), ancak bunların hepsi kağıda iyi yazılmıştır. Korkunç ingilizce için üzgünüm.


"Bu akışın 8 tane kardinaliteye sahip olma şansı daha yüksek" Lütfen 000'in neden beklenen deneme sayısı 2 ^ 3 anlamına geldiğini açıklayabilir misiniz? Ben 3 sıfır ile en az bir çalışma var ve 4 sıfır ile hiçbir çalışma var varsayalım deneme sayısı matematik beklentisi hesaplamak için çalıştı ...
yura

5
Bunu okuyana kadar gazeteyi tam olarak anlamadım. Şimdi bir anlam kazandı.
josiah

5
@yura Çok eski bir yorum olduğunu biliyorum, ama diğer insanlar için yararlı olabilir. "Rastgele bir tamsayılar akışında (...)% 12,5" 001 "ile başlar. Muhtemel kardinalite 8'dir, çünkü% 12,5 tüm akışın sekizde birini temsil eder.
braunmagrin

111

HyperLogLog olasılıklı bir veri yapısıdır . Listedeki farklı öğelerin sayısını sayar. Ancak bunu yapmanın basit bir yoluna kıyasla (bir kümeye sahip olmak ve kümeye öğeler eklemek) bunu yaklaşık olarak yapar.

HyperLogLog algoritmasının bunu nasıl yaptığını görmeden önce, neden ona ihtiyacınız olduğunu anlamak gerekir. Basit bir şekilde sorun O(distinct elements), yer tüketmesidir . Neden burada sadece farklı unsurlar yerine büyük bir O notasyonu var? Bunun nedeni elemanların farklı boyutlarda olabilmesidir. Bir öğe 1başka bir öğe olabilir "is this big string". Bu nedenle, büyük bir listeniz (veya büyük bir öğe akışı) varsa, çok fazla bellek alır.


Olasılıksal Sayım

Bir dizi benzersiz element hakkında makul bir tahmin nasıl elde edilebilir? Eşit olasılıkla moluşan bir uzunluk dizeniz olduğunu varsayın {0, 1}. 0 ile, 2 sıfır ile, k sıfırlarla başlama olasılığı nedir? Öyle 1/2, 1/4ve 1/2^k. Bu, ksıfırlarla bir dizeyle karşılaşırsanız , yaklaşık olarak 2^köğelere baktığınız anlamına gelir . Yani bu iyi bir başlangıç ​​noktası. 0Ve arasında eşit olarak dağıtılan öğelerin bir listesine sahip olmak2^k - 1 ikili sunumdaki en büyük sıfır önekinin maksimum sayısını sayabilirsiniz ve bu size makul bir tahmin verecektir.

Sorun dan eşit olarak dağıtılmış sayılarına sahip olan varsayım olduğunu 0t 2^k-1karşılaştığımız veri çoğunlukla neredeyse eşit olarak dağıtılmış asla değil sayılardır (elde etmek çok zor olduğunu ve herhangi değerler arasında olabilir. Ama kullanarak iyi bir karma işlev size varsayabiliriz çıkış bitleri eşit olarak dağıtılır ve çoğu hash fonksiyonu 0ve 2^k - 1( SHA1 size 0ve arasında değerler verir) çıkışlarına sahiptir 2^160. Şimdiye kadar elde ettiğimiz şey, ksadece maksimum depolama ile benzersiz elemanların sayısını sadece maksimum depolama ile tahmin edebilmemizdir. boyut log(k)bitlerinin bir kısmı dezavantajı, tahminimizde büyük bir varyansımızın olması Neredeyse yarattığımız harika bir şey1984'ün olasılıksal sayım kağıdı (tahminle biraz daha akıllıdır, ancak yine de yakınız).

loglog

Daha ileriye gitmeden önce, ilk tahminimizin neden bu kadar büyük olmadığını anlamalıyız. Bunun nedeni, yüksek frekanslı 0-önek elemanının rastgele bir oluşumunun her şeyi bozabilmesidir. Bunu geliştirmenin bir yolu, birçok karma işlevini kullanmak, karma işlevlerinin her biri için maks. Saymak ve sonunda bunları ortalamaktır. Bu, tahmini artıracak mükemmel bir fikir, ancak LogLog kağıdı biraz farklı bir yaklaşım kullandı (muhtemelen hash biraz pahalı olduğu için).

Bir karma kullandılar ama iki parçaya ayırdılar. Birine kova denir (toplam kova sayısı 2^x) ve diğeri - temel olarak karmamızla aynıdır. Olanları elde etmek benim için zor oldu, bu yüzden bir örnek vereceğim. İki öğeniz olduğunu 0ve 2^10üretilen 2 değere değerler veren sağlama işlevinizin olduğunu varsayalım : 344ve 387. 16 kova almaya karar verdin. Yani:

0101 011000  bucket 5 will store 1
0110 000011  bucket 6 will store 4

Daha fazla kova ile varyansı azaltırsınız (biraz daha fazla alan kullanırsınız, ancak yine de küçüktür). Matematik becerilerini kullanarak hatayı (yani 1.3/sqrt(number of buckets)) ölçmeyi başardılar .

HyperLogLog

HyperLogLog herhangi bir yeni fikir sunmaz, ancak önceki tahmini iyileştirmek için çoğunlukla çok fazla matematik kullanır. Araştırmacılar, en büyük sayıların% 30'unu kovalardan kaldırırsanız, tahmini önemli ölçüde iyileştirdiğinizi bulmuşlardır. Ayrıca sayıların ortalaması için başka bir algoritma kullandılar. Kağıt matematik ağırlıklı.


Ve hyperLogLog algoritmasının geliştirilmiş bir versiyonunu gösteren yeni bir kağıtla bitirmek istiyorum (şimdiye kadar tam olarak anlayacak zamanım yoktu, ama belki de daha sonra bu cevabı geliştireceğim).


2
Teorik k zeroesolarak özel bir şey olmadığını varsayıyorum . bunun yerine arayabilir k onesve mantık aynı olabilir, hatta k lengthdizeyi arayabilir , {0,1}ancak böyle bir dizeyi alıp ona yapışabilir mi? çünkü bu ikili dizgilerin hepsinde eşit olasılıkla 1/2 ^ k olabilir?
user881300

3
HyperLogLog, en büyük sayıların% 30'unu kaldırmaz. Bu, LogLog belgesinde de açıklanan SuperLogLog algoritması fikridir. HyperLogLog algoritmasının ana fikri, SuperLogLog ve LogLog tarafından kullanılan geometrik ortalama yerine harmonik ortalamayı kullanarak ikililerin gücünü ortalamaktır.
otmar

21

Sezgi, girdiniz büyük bir rasgele sayı kümesi ise (örn. Karma değerler), bir aralıkta eşit olarak dağıtılması gerekir. Diyelim ki aralık 1024'e kadar değeri temsil etmek için 10 bit'e kadar. Diyelim ki minimum değer gözlendi. Diyelim ki 10'dur. O zaman kardinalitenin yaklaşık 100 (10 × 100 ≈ 1024) olduğu tahmin edilecektir.

Tabii ki gerçek mantık için makaleyi okuyun.

Örnek kodla ilgili başka bir iyi açıklama burada bulunabilir:
Lanet Soğuk Algoritmalar: Kardinalite Tahmini - Nick'in Blogu


3
lanet serin algoritmalar blog yazısı bağlantısı için oy verildi. algoritmayı kavramamı gerçekten sağladı.
Igor Serebryany
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.