【王樹森推薦系統】召回12:曝光過濾 Bloom Filter

概述

  • 曝光過濾通常是在召回階段做,具體的方法就是用 Bloom Filter

曝光過濾問題

  • 如果用戶看過某個物品,則不再把該物品曝光給用戶。原因是同一個物品重復曝光給用戶會損害用戶體驗,但也不是所有推薦系統都有曝光過濾,像 youtube 這樣的長視頻就沒有曝光過濾,看過的也可以再次推薦
  • 對于每個用戶,記錄已經曝光給他的物品(小紅書只召回 1 個月以內的筆記,因此只需要記錄每個用戶最近 1 個月的曝光歷史)
  • 對于每個召回的物品,判斷它是否已經給該用戶曝光過,排除掉曾經曝光過的物品
  • 一位用戶看過 nnn 個物品,本次召回 rrr 個物品,如果爆力對比,需要 O(nr)O(nr)O(nr) 的時間。
  • 在小紅書一個月 nnn 的曝光量級大概是幾千,每次推薦召回量 rrr 的量級也是幾千,暴力對比的計算量太大了,所以實踐中不暴力對比,而是用 Bloom Fliter

Bloom Filter

  • Bloom Filter是一種數據結構,發表在 1970 年,以它的發明者命名
  • 推薦系統的曝光過濾基本上都是用 Bloom Fliter 做的
  • Bloom Fliter 判斷要給物品ID是否已經在已曝光的物品集合中
  • 如果判斷為 no,那么該物品一定不在集合中
  • 如果判斷為 yes,那么該物品很可能在集合中(可能誤傷,錯誤判斷未曝光物品為已曝光,將其過濾掉)
  • 如果用 Bloom Fliter 過濾,肯定能干掉所有已經曝光的物品,但是可能會誤傷
  • Bloom Fliter 把物品集合表征為一個 m 維二進制向量
  • 每個用戶有一個曝光物品的集合,表征為一個向量,需要 m bit 的存儲
  • Bloom fliter 有 k 個哈希函數,每個哈希函數把物品ID映射成介于 0 和 m-1 之間的整數

Bloom Filter (k=1)

  • 初始的時候向量是全 0 的
    在這里插入圖片描述
  • 我們知道用戶有哪些已經曝光過的物品,如下圖哈希函數把第一個物品 ID1ID_1ID1? 映射為 1,所以我們將二進制的第一位映射為 1
    在這里插入圖片描述
  • 第二個物品 ID2ID_2ID2? 映射為了 8,所以把位置 8 的二進制位改為 1
    在這里插入圖片描述
  • 哈希函數把第三個物品 ID3ID_3ID3? 映射為了位置 1,這個位置的元素已經是 1 了,不需要修改這個數值
    在這里插入圖片描述
  • 哈希函數把第四個物品 ID4ID_4ID4? 映射到了位置 5,我們也將其置為 1
    在這里插入圖片描述
  • 哈希函數把第五第六個物品都映射到了位置 5,這個位置已經是 1 了,不需要修改這個數值,到此為止我們已經把 6 個物品表征為一個向量
    在這里插入圖片描述
  • 用戶發起推薦請求后曝光很多物品,這里用一個之前未曝光給用戶的物品,他被映射到位置 2,這個位置是 0,所以 Bloom Filter 判斷這個物品之間沒有被曝光
  • 這個判斷是正確的。如果 Bloom Filter 認為它沒有被曝光,那么它肯定沒被曝光,Bloom Filter 不會把已曝光的物品錯判未未曝光
    在這里插入圖片描述
  • 而下面又一個新來的物品已經曝光了,那么它就會被映射到之前它標記過的位置
    在這里插入圖片描述
  • 對于又一個新的未曝光的物品,哈希函數把它映射到了位置 8,這個位置已經被標記為了 1,所以被認為已經曝光過了,此時錯判
    在這里插入圖片描述

Bloom Filter (k=3)

  • 初始全0,來了一個 ID1ID_1ID1? 物品,此時有 3 個哈希函數,我們把它映射到了 3 個位置上,我們把 3 個位置都置為 1
    在這里插入圖片描述
  • ID2ID_2ID2? 也是一個已曝光的物品,我們還用 3 個哈希函數把它映射到 3 個位置上,把 3 個位置的都置為 1
    在這里插入圖片描述
  • 現在有一個召回的物品 ID8ID_8ID8?,用 3 個哈希函數把它映射到了 3 個不同的位置。假如這個物品已經曝光,那么 3 個位置肯定都是 1 了,但其中 1 個位置是 0,說明這個物品還未曝光
    在這里插入圖片描述
  • 對于 ID4ID_4ID4? ,它已經被曝光,判斷是正確的
    在這里插入圖片描述
  • 對于未曝光的 ID9ID_9ID9? ,它映射的 3 個位置都為 1,被誤判了
    在這里插入圖片描述

誤傷概率分析

  • 曝光物品集合大小為 nnn,二進制向量維度為 mmm,使用 kkk 個哈希函數
  • nnn 越大,向量中的 1 越多,誤傷的概率越大(未曝光的 kkk 個位置恰好都是 1 的概率大)
  • mmm 越大,向量越長,越不容易發生哈希碰撞,需要的存儲也越多
  • kkk 太大,太小都不好,kkk 有最優取值
    在這里插入圖片描述
  • 設定可容忍的誤傷概率為 δ\deltaδ ,那么最優參數為:
    在這里插入圖片描述
  • 只需要 m = 10n bit,就可以把誤傷概率降低到 1% 以下

曝光過濾的鏈路

  • 把曝光物品記錄下來,反饋給召回階段,用于過濾召回的物品
    在這里插入圖片描述
  • app 的前端有埋點,所有曝光的物品都會被記錄下來。這個落表的速度要足夠快,否則可能會出問題
  • 用戶推薦頁面兩次刷新間隔也就幾分鐘,快的話也就一二十秒,在下次刷新前就得把本次曝光的結果寫道 Bloom Filter 上,否則下一刷很可能會出重復的物品。
  • 所以要用實時流處理,比如把曝光物品寫入 Kafka 消息隊列,用 Flink 做實時計算
    在這里插入圖片描述
  • Flink 實時讀取 Kafka 消息隊列,計算曝光物品的哈希值,把結果寫道 Bloom Fliter 的二進制向量上
  • 用這樣的實時數據鏈路,在曝光發生的幾秒后,這位用戶的 Bloom Filter 就會被修改,就可以避免重復曝光
  • 但實時流這部分也是最容易出問題的,如果掛掉了或者延時特別大。那么上一刷才看過的物品又會出現
    在這里插入圖片描述
  • 曝光過濾具體用在召回完成之后:召回服務器請求曝光過濾服務,曝光過濾服務把二進制向量發送給召回服務器,在召回服務器上用 Bloom Filter 計算召回的物品的哈希值,再和二進制向量做對比,把已經曝光的物品給過濾掉,發送剩余的物品給排序服務器

在這里插入圖片描述

Bloom Filter 的缺點

  • Bloom 把物品的集合表示成一個二進制向量
  • 每往集合中添加一個物品,只需要把向量的 k 個位置的元素置為 1
  • Bloom Filter 只支持添加物品,不支持刪除物品,從集合中移除物品,無法消除它對向量的影響。因為是共享的,所以要移除的話不能簡單的把它的位置都改為 0,因為有可能別的物品也在這個位置有標記
  • 每天都需要從物品集合中移除年齡大于 1 個月的物品(超齡物品不可能被召回,沒必要把它們記錄在 Bloom Filter,降低 n 可以降低誤傷率)
  • 想要刪除一個物品,需要計算整個集合的二進制向量

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88079.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88079.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88079.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于STM32單片機的心率血氧監測系統設計(STM32代碼編寫+手機APP設計+PCB設計+Proteus仿真)

系列文章目錄 文章目錄 系列文章目錄前言1 資料獲取與演示視頻1.1 資料介紹1.2 資料獲取1.3 演示視頻 2 系統框架3 硬件3.1 主控制器3.2 顯示屏3.3 WIFI模塊3.4心率血氧傳感器 4 設計PCB4.1 安裝下載立創EDA專業版4.2 畫原理圖4.4 使用嘉立創下單助手進行下單,打板。…

main(int argc,char **agrv)的含義

今天和大家討論一個常見的但是不容易深入了解的知識點。那就是 main 函數聲明中使用到的 argc 和 argv 的含義。通常我們寫主函數的時候一般都是直接使用int main() 或者 void main() 來聲明 main 函數。但是你知道嗎?在c89/c99的語言標準中,main函數的聲…

如何簡單實現發版不影響客戶使用?nginx負載

nginx負載發版不影響客戶使用 1.需要二臺服務器 2.二臺服務器均是正式環境配置 3.服務器Nginx配置修改 發版順序:先在服務器2發版,發布成功后,再改服務器Nginx配置,重新加載nginx;然后在服務器再發版,發布成…

qt筆記(1)——Qtablewidget使用

1.基礎使用方法 (略) 2.坑和注意點 2.1 設置一個單元格的編輯屬性 在代碼中,想要修改一個單元格的編輯屬性,需要對這個item的flags進行設置;注意對一個tablewidget的一個item成員進行設置后,進行一次編…

字符串的模糊匹配方法介紹

字符串的模糊匹配方法介紹 目錄字符串的模糊匹配方法介紹一、編輯距離(Levenshtein Distance)復雜度分析二、Jaro-Winkler 距離復雜度分析三、最長公共子序列(LCS)復雜度分析四、模糊搜索(Fuzzy Search)復雜…

ActiveMQ在Spring Boot中的詳細使用指南

?? 目錄 ?? ActiveMQ簡介 什么是ActiveMQ? 核心概念 ??? 基礎架構組件 ?? 重要概念解釋 ActiveMQ vs 其他消息中間件 ?? 環境搭建 1. ActiveMQ服務端安裝 Docker方式(推薦初學者) 手動安裝方式 2. 驗證安裝 訪問Web管理界面 連接參數 測試連接 ?…

二元一次方程

前言 最近剛學二元一次方程,想寫一篇專欄熟悉一下本文寫給初一的同學看,學過的就劃了吧二元一次方程 兩個未知數最高項次數為 111 次為整式方程二元一次方程的解不唯一,但是二元一次方程可以用一個未知數來表達另一個未知數eg:eg:eg: xy1x y…

AI編程的未來是智能體原生開發?

目錄 前言 一、從“串行”到“并行”:什么是智能體原生開發? 1.1 傳統模式(串行思維) 1.2 智能體原生模式(并行思維) 二、程序員的新角色:從代碼手藝人到系統思想家 三、軟件開發的終局&a…

【牛客刷題】小紅的與運算

文章目錄 一、題目介紹1.1 題目描述1.2 輸入描述1.3 輸出描述1.4 示例二、 解題思路2.1 核心算法設計2.2 性能優化關鍵2.3 算法流程圖三、解法實現3.1 解法一:基礎實現3.1.1 初級版本分析3.2 解法二:優化版本(推薦)3.2.1 優化版本分析四、總結與拓展4.1 關鍵優化技術4.2 算…

spring中 方法上@Transation實現原理

Spring中Transactional注解方法實現原理Spring的Transactional注解在方法級別實現事務管理的原理主要基于動態代理和攔截器機制,以下是其核心實現流程:1. 代理創建階段當Spring容器啟動時,會為帶有Transactional注解的類創建代理對象&#xf…

qt-C++語法筆記之Stretch與Spacer的關系分析

qt-C語法筆記之Stretch與Spacer的關系分析 code review! 文章目錄qt-C語法筆記之Stretch與Spacer的關系分析1. Stretch(拉伸因子)2. Horizontal Spacer 和 Vertical Spacer3. Stretch 和 Spacer 的關系4. 實際應用中的選擇5. 注意事項6. 代碼與 Qt Desig…

Qwen3技術綜述

1. 引入 2025年5月,qwen推出了旗艦模型(flagship model)Qwen3-235B-A22B。并以Apache 2.0版權發布(可自由商業使用,修改代碼和商用要包含原始版權)。本文對其技術報告中提到的數據處理技術與模型結構進行綜…

[特殊字符] Excel 讀取收件人 + Outlook 批量發送帶附件郵件 —— Python 自動化實戰

許多公司定期需要將不同部門或客戶的報告發送給指定人員。手動操作容易出錯、耗時且繁瑣。今天這篇文章教你如何利用 Python 實現: 🧩 從 Excel 中讀取“收件人 抄送人 附件文件路徑”; 📤 使用 win32com.client 調用 Outlook …

多模態大語言模型arxiv論文略讀(152)

VidComposition: Can MLLMs Analyze Compositions in Compiled Videos? ?? 論文標題:VidComposition: Can MLLMs Analyze Compositions in Compiled Videos? ?? 論文作者:Yunlong Tang, Junjia Guo, Hang Hua, Susan Liang, Mingqian Feng, Xinya…

基于AR和SLAM技術的商場智能導視系統技術原理詳解

本文面對室內定位算法工程師、智慧商場系統開發者、對VR/AR應用開發感興趣的技術人員,解決如何通過SLAMAR技術破解大型商場室內導航的空間認知壁壘,實現沉浸式導覽,本文提供完整技術方案與代碼實現。 如需獲取商場智能導視系統解決方案請前往…

Debezium日常分享系列之:認識Debezium Operator

Debezium日常分享系列之:認識Debezium Operator什么是Debezium OperatorDebezium Operator 的工作原理Debezium Operator 的優點Debezium Operator 使用場景Debezium Operator 的關鍵組件部署Debezium OperatorDebezium Operator 的使用什么是Debezium Operator De…

POSIX信號量,環形隊列

是一種進程間或線程間同步機制,用于控制多個線程/進程對共享資源的訪問,避免并發沖突。可以看作是一個計數器,通過對計數器的操作(PV操作)實現同步P操作(原子性):--,將信…

Python Day6

浙大疏錦行 Python Day6 內容: 描述性統計(可視化分析)單特征可視化(連續、離散)特征與標簽可視化特征與特征可視化 代碼: # TODO: 描述性統計 import pandas as pd import numpy as np import seaborn…

ESP32與樹莓派C++、Rust開發實戰

C++語言在ESP32、樹莓派實例 以下是關于C++語言在ESP32、樹莓派等硬件設備上的開發實例匯總,涵蓋常見應用場景和代碼示例。 ESP32開發實例 LED控制(GPIO操作) 使用ESP32的GPIO控制LED燈,示例代碼基于Arduino框架: #include <Arduino.h> const int ledPin = 2; …

Jedis 原生之道:Redis 命令 Java 實現指南(一)

Hi~&#xff01;這里是奮斗的明志&#xff0c;很榮幸您能閱讀我的文章&#xff0c;誠請評論指點&#xff0c;歡迎歡迎 ~~ &#x1f331;&#x1f331;個人主頁&#xff1a;奮斗的明志 &#x1f331;&#x1f331;所屬專欄&#xff1a;Redis &#x1f4da;本系列文章為個人學習筆…