蓄水池采樣算法-Lua版本

由于業(yè)務(wù)需要,所以搜索了一些相關(guān)的隨機算法
代碼是參考維基百科進行編寫的:https://en.wikipedia.org/wiki/Reservoir_sampling

注意點:
Chao算法會有缺陷,因為它一開始就把所需要的數(shù)據(jù)全部扔池子里了。 如果權(quán)重存在0的的數(shù)據(jù),且數(shù)據(jù)量較少,可能會出現(xiàn)在最終結(jié)果里。(實驗中,Chao算法結(jié)果不正確
Res算法,我使用了遍歷求最小值,所以在處理大量數(shù)據(jù)時,可能會存在性能瓶頸。

代碼:
-- 蓄水池采樣算法
function reserviorSampling(tbSequence, dNeed, dSequenceSize, funcRandom)
    dSequenceSize = dSequenceSize or #tbSequence
    funcRandom = funcRandom or math.random
    
    if dNeed > dSequenceSize then
        return tbSequence
    end
    
    local tbSample = {}
    
    for i=1, dNeed do
        table.insert(tbSample, tbSequence[i])
    end
    
    for i=dNeed+1, dSequenceSize do
        local j = funcRandom(1,i)
        if dNeed >= j then
            tbSample[j] = tbSequence[i]
        end
    end
    
    return tbSample
end

-- 加權(quán)蓄水池采樣算法: Algorithm A-Chao
function weightedReserviorSampling_Chao(tbSequence, dNeed, dSequenceSize, funcRandom)
    dSequenceSize = dSequenceSize or #tbSequence
    funcRandom = funcRandom or math.random
    
    if dNeed > dSequenceSize then
        return tbSequence
    end

    local dWeightSum = 0
    local tbSample = {}
    
    for i=1, dNeed do
        table.insert(tbSample, tbSequence[i])
        dWeightSum = dWeightSum + tbSequence[i].weight
    end
    
    for i=dNeed+1, dSequenceSize do
        dWeightSum = dWeightSum + tbSequence[i].weight
        local p = tbSequence[i].weight / dWeightSum
        local j = funcRandom()
        if j <= p then
            tbSample[funcRandom(1, dNeed)] = tbSequence[i]
        end
    end
    
    return tbSample
end

-- 加權(quán)蓄水池采樣算法: Algorithm A-Res
function weightedReserviorSampling_Res(tbSequence, dNeed, dSequenceSize, funcRandom)
    dSequenceSize = dSequenceSize or #tbSequence
    funcRandom = funcRandom or math.random
    
    if dNeed > dSequenceSize then
        return tbSequence
    end

    local dWeightSum = 0
    local tbSample = {}
    
    local dMinIndex = nil
    
    for i=1, dSequenceSize do
        local r = funcRandom()^(1/tbSequence[i].weight)
        tbSequence[i].__reservior_r = r
        if i <= dNeed then
            table.insert(tbSample, tbSequence[i])
        else
            if not dMinIndex then
                local dMin = 9999
                for i,v in ipairs(tbSample) do
                    if v.__reservior_r < dMin then
                        dMin = v.__reservior_r
                        dMinIndex = i
                    end
                end
            end
            assert(dMinIndex)
            if r > tbSample[dMinIndex].__reservior_r then
                table.remove(tbSample,dMinIndex)
                dMinIndex = nil
                table.insert(tbSample, tbSequence[i])
            end
        end
    end
    
    return tbSample
end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 最近有個需求,需要從不固定大小的數(shù)據(jù)集中取固定數(shù)量的數(shù)據(jù)作為樣本,有個同學(xué)提到了蓄水池算法,于是了解了一下。 蓄水...
    hatlonely閱讀 1,624評論 0 0
  • --- layout: post title: "如果有人問你關(guān)系型數(shù)據(jù)庫的原理,叫他看這篇文章(轉(zhuǎn))" date...
    藍墜星閱讀 919評論 0 3
  • 0. 導(dǎo)語 推薦系統(tǒng)里面有兩個經(jīng)典問題:EE 問題和冷啟動問題。前者涉及到平衡準確和多樣,后者涉及到產(chǎn)品算法運營等...
    Liam_ml閱讀 1,852評論 0 4
  • 一、基礎(chǔ)篇 1.1 JVM 1.1.1. Java內(nèi)存模型,Java內(nèi)存管理,Java堆和棧,垃圾回收 http:...
    勿以浮沙筑高臺閱讀 983評論 0 9
  • 從博厄斯(Franz Boas)對北美西北海岸印第安人的夸富宴(potlach)的介紹開始,人類學(xué)家不斷地從不同視...
    萍兒100081閱讀 10,049評論 1 8

友情鏈接更多精彩內(nèi)容