浅谈流处理算法 (1) – 蓄水池采样
轉載自??淺談流處理算法 (1) – 蓄水池采樣
前言 現如今,“大數據 ”已經不是什么新概念,“一千個人眼中有一千個大數據”。社交網絡,智能穿戴設備,智能家居,傳感器,機器人等每一個熱門的詞匯背后都是大量的數據。拋開各種噱頭和概念,相信每個人都能看到數據的價值,且能感受到數據規模的爆炸式增長。大規模的數據本身并不產生什么價值,只有通過理解數據,發現知識,避免“Garbage In Garbage Out” 才能發揮數據的價值。
在形式多樣的大數據問題中,有一類問題輸入以數據流的方式提供。我們需要在有限空間內通過若干遍訪問數據流(很多時候可能僅僅允許訪問一遍)完成數據處理并提取有價值的信息。我們稱處理這類問題的算法為“流處理算法”(Streaming Algorithm)
Wikipedia定義: In computer science, streaming algorithms are algorithms for processing data streams in which the input is presented as a sequence of items and can be examined in only a few passes (typically just one). These algorithms have limited memory available to them (much less than the input size) and also limited processing time per item.
一些典型的例子:
- 根據用戶訪問日志,統計用戶來源分布?
- 根據用戶訪問日志,統計新增用戶數目?
- 根據用戶訪問日志,統計Unique User數目?
- 根據用戶訪問日志,統計某個頁面訪問次數?
- ……
這些問題在數據規模并不大且事先確定的情況下,采取直接的統計方案并不難實現。但,在數據流場景下,直接的方案并不能滿足實際需求。
數據流問題有以下特點:
- 數據規模大
- 存儲空間有限。保存完整的數據集合并不現實。
- 分發速度快。如果處理不及時,沒有足夠資源保存數據。
- 允許數據遍歷極少次數,一般僅支持遍歷一次。
- 空間復雜度sub-linear
- 時間復雜度linear
- 可以接受近似解
曾幾何時,拜摩爾定律和硬件技術所賜,軟件開發脫離在64k內存中扣扣索索的日子,進入沒事開個大數組的印度模式時代(道聽途說,如有雷同,概不負責)。軟件體量一個比一個嚇人。然而,面對上述特點的數據流問題時,我們再一次深刻地體會到日新月異的計算機技術背后總有一個背景音 - “New Wine In Old Bottles”。
數據庫大牛Jim Gray多年前就指示我們:Tape is Dead, Disk is Tape, Flash is Disk, RAM locality is King. TalkingData的Bitmap引擎這不又在扣扣索索了嘛
這個小系列,就是跟大家一起品嘗一下“新酒”, 以酒會友:-)
言歸正傳,針對上述數據流問題特點,流處理算法的一般模式有:
- 采樣/過濾 – 減少規模
- 如:蓄水池采樣 Reservoir Sampling
- 隨機映射(Random Projection) – 降維
- Hash/SimHash
- 概要 (Sketch)
- 統計直方圖(Histogram)
- 滑動窗口
這些算法模式都是希望通過樣本采樣或者特征采樣,使用有限數據保持原整體數據的某些特性。
后續我們計劃聊聊蓄水池采樣, 存在性查詢,基數估計,頻率估計,頻繁項估計等問題的流處理方法。
蓄水池采樣
蓄水池采樣是一類采樣算法的總稱,廣泛使用在從數據流中按一定需求抽樣出部分樣本的場景中。蓄水池,可以看作小段緩存,協助存儲數據流的部分信息。
下面我們從三個具體例子看看什么是蓄水池采樣。
問題1. 年度大獎將從參加年會的同事中隨機選擇,如何維護一個獲獎者名字,不管何時老大宣布獲獎者,所有參會者獲獎概率一致?
假如老大宣布獲獎者時,參會同事人數為N,我們需要保證每個參會者獲獎概率為1/N。
蓄水池采樣算法是這樣的:
- 記錄第一個到達的同學到獲獎者名單上 (早起的鳥兒有蟲吃 :-) )
- 當第i位同學到達年會會場的時候(i>1):
- 以1/i的概率使用第i位同學替換獲獎者名單上的同學
- 以1-1/i的概率保持獲獎者名單不變 (Yeah!守擂成功!)
看起來很簡單,我們來看看是否能滿足問題的需求
- 第一個同學P_1到達時,獲獎者必定是P_1。(獲獎概率?1?1?= 100%,滿足)
- 第二個同學P_2到達時,1/2概率獲獎者替換為P_2, 也1/2概率保持為P_1 (滿足)
- 當第i位同學到達時,1/i的概率獲獎者替換為P_i。而的1-1/i概率保持獲獎者不變,也就是P_1, P2, …, P(i-1)獲獎的概率為 1/(i-1) * (1-1/i) = 1/i (滿足)
綜上所述,根據歸納法,蓄水池采樣搞掂了。
問題2. 項目進展很好,老大很高興,決定年度大獎有k名,如何維護一個k個獲獎者名單,保證不管何時老大宣布獲獎者,所有參會者獲獎概率一致?
假如老大宣布獲獎者時,參會同事人數為N,我們需要保證每個參會者獲獎概率為k/N。
蓄水池采樣算法是這樣的: + 記錄前k位到達的同學到獲獎者名單上 (早起總沒錯的) + 當第i位同學到達年會會場的時候(i>k): - 以k/i的概率使用第i位同學替換獲獎者名單上的隨機一位同學(某位同學杯具了) - 以1-k/i的概率保持獲獎者名單不變 (集體守擂成功!)
看起來跟上一個問題差不多,應該是正確的吧
- 前k位同學到達時,獲獎者必定是P_1, P_2, …, P_k。(獲獎概率 k/k = 100%,滿足)
- 當第i位同學到達時( i > k)
- [Condition 1] k/i概率獲獎者替換為P_i (滿足)
- [Condition 2] 1 - k/i的概率保持獲獎者名單不變
- 對于P_x (x < i), 在第i位同學尚未到達時獲獎概率為k/(i-1)。她能保留在獲獎名單中的概率由兩部分組成 k/(i-1) * [k/i * (1 - 1/k) + 1 - k/i] = k/i(滿足)
- [Condition 1]沒有被P_i踢掉 k/i * (1 - 1/k)
- [Condition 2]P_i直接出局了1 - k/i
綜上所述,根據歸納法,蓄水池采樣又搞掂了。
問題3.為了激勵績效好的同學,每個參會同學都有一個權重,如何維護一個k個獲獎者名單,保證不管何時老大宣布獲獎者,所有參會者獲獎概率與權重成比例?
假如老大宣布獲獎者時,參會同事人數為N,我們需要保證參會者(P, 績效權重W)獲獎概率為W_i/(W_1 + W_2 + … + W_N)。
蓄水池采樣算法是這樣的:
- 記錄前k位到達的同學到獲獎者名單上 (嗯,早起永遠沒錯的)
- 每位同學的分值S_i = random(0, 1) ^ (1/W_i)
- 當第i位同學到達年會會場的時候(i>k):
- 計算第位同學的分值 S_i = random(0, 1) ^ (1/W_i)
- 如果獲獎者名單中分值最小的同學P_x的分值S_x比S_i小,P_x被S_i替換了
- 否則,獲獎者名單不變 (集體守擂成功!)
怎么證明這樣可以滿足要求呢?額,“這里空白太小,我寫不下了” (自己看論文去吧)
年會一年也就一次,很快來了又走了。各種各樣的數據流每天都在產生,這些蓄水池采樣方法可以幫忙我們獲得數據流的一個樣本。對于小規模樣本可以保持大規模數據信息的場景,蓄水池采樣幫忙我們把“大數據”的“大”給去掉了。
參考文獻
總結
以上是生活随笔為你收集整理的浅谈流处理算法 (1) – 蓄水池采样的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库 - 事务管理(ACID)隔离级别
- 下一篇: 二级路由器该怎么设置联网如何设置第二级路