我一直在使用一些非常大型的數據集,通常是數十億個元素,這些數據都保存在一個memcached雲中並定期轉儲到文件中,對於我的其中一項任務,我試圖計數這套的基數。如何在Python中有效地計算超大型數據集的基數?
對於某些情況下,每個項目包含一個IP和一些其他屬性標識一個人,並在base64中編碼,項目大小爲20個字節。通過刪除一些字段來減少項目的大小是不可能的。
這裏的東西,模仿我的數據集作爲一個內存版本(感謝this post字符串代):
import base64, os
dataset_size = 10000000000 # that's 10 billion, be careful if you run it !
big_dataset = [base64.b64encode(os.urandom(10)) for i in range(dataset_size)]
我的第一個方法是使用這樣一個HashSet:
uniques = set(big_dataset)
print "Cardinality: %d" % len(uniques)
雖然這在理論上可以在小數據集上正常工作,但您可以猜到這是一個呃逆:
- 我無法對數據的唯一性做任何假設。我可以擁有50%的獨特數據集,或者我也可以擁有100%的數據集。這是以固定的時間間隔動態生成的,並且取決於許多因素(例如,一天中的時間)而變化。
- 數據集大小在100億。以64爲基數編碼的每個項目是20個字節,時間100億是平均數百兆字節。不幸的是,我沒有機會獲得那麼多的RAM!
我已經完成了我的作業,發現至多一些研究論文,或者一些不起眼的圖書館,但是其目標的一部分是瞭解什麼方法可行,爲什麼。
所以我打電話給你Python用戶,你知道任何算法,可以幫助我有效地估計基數嗎?就複雜性而言,我的意思是我並不在乎運行時間的複雜性,但我更關注空間複雜性。我不介意犧牲一點準確性,如果它能夠極大地提高性能(所以我不一定需要知道確切的唯一身份數,即使這是理想的,但可能不是一個可行的方法)。我會說高達5%是可以接受的。我正在爲這個項目尋找專門針對Python的東西。
感謝您提供任何幫助!如有人指出,我可以使用Hadoop/MR,但是對於這個特定的項目,我們不想採用MR方式,並且希望能夠在單臺機器上有效地探索算法,因爲這可能會適用於其他幾個不同的項目。
只是一個建議,但這聽起來像是一些可能對Map-Reduce框架有好處的東西 - 將數據中的元素映射到字典中的計數或某物。爲此,您可以使用由Yelp創建的Python Map-Reduce框架[MRJob](https://github.com/Yelp/mrjob)。使用MRJob在Amazon EC2上運行它也可能是一個好主意。我以前曾經用它來處理大型文字的頻率計數。我想這完全取決於你如何解析單個數據元素。 – ely 2012-04-15 18:05:58
感謝您的建議,是的,我已經考慮過MR(實際上我在其他項目中使用過它),但對於這個特定問題,MR/Hadoop不是一種選擇,我們希望研究算法作爲概念證明的一部分,在一臺機器上做這件事。 – 2012-04-15 18:08:22
如果100%的準確性不重要,也許一個布隆過濾器會給你5%的錯誤將適合內存?如果沒有,並且需要一臺計算機,則可以簡單地使用一些簡單的nosql數據庫和唯一的密鑰,這些密鑰存儲在磁盤上並刪除重複項。它會很慢,但它可以適用於你擁有的任何數量的內存。您仍然可以並行實際插入工作。 – 2012-04-15 18:52:56