【上】王樹森《小紅書推薦系統公開課》- 課程筆記(推薦系統基礎、召回、排序)

寫在前面

本文為王樹森老師《小紅書推薦系統公開課》的課程筆記

  • 課程來源:ShusenWang的個人空間-ShusenWang個人主頁-嗶哩嗶哩視頻 (bilibili.com)
  • 課程資料:GitHub - wangshusen/RecommenderSystem

由于篇幅較長,分為【上】【下】兩篇文章來記錄。其中【上】包括推薦系統基礎、召回、排序,【下】包括特征交叉、行為序列、重排、物品冷啟動、漲指標的方法

【上】部分,內容導航如下:?


(一)推薦系統基礎

1、推薦系統的基礎概念

打開小紅書APP,默認打開 “發現” 頁面,展示推薦系統分發給你的內容,即用戶自己創作的筆記,將它們展示給其他用戶,形成陌生人社交的社區?

小紅書推薦系統的轉化流程

推薦系統決定給用戶曝光什么內容,用戶自己決定是否點擊、滑動到底、...

抖音沒有曝光和點擊,用戶下滑一次只能看到一個視頻?

短期消費指標

反映出用戶對推薦是否滿意

  • 點擊率 = 點擊次數 / 曝光次數
    • 越高說明推薦越精準
    • 不能作為唯一優化目標(標題黨)
  • 點贊率 = 點贊次數 / 點擊次數
    • 收藏率轉發率同理
  • 閱讀完成率 = 滑動到底次數 / 點擊次數 * 歸一化函數(跟筆記長度有關)
    • 筆記越長,完成閱讀的比例就越低
    • 若沒有歸一化函數,對長筆記會不公平

短期消費指標容易竭澤而漁,用戶很快會失去興趣,不再活躍。故還需關注多樣性(用戶沒看過的話題),有助于提高用戶黏性,留住用戶,讓用戶更活躍

北極星指標

衡量推薦系統好壞最重要的指標,根本標準

  • 用戶規模:日活用戶數DAU(只要今天登錄了一次小紅書就增加了一次DAU)、月活用戶數MAU(只要這個月登錄了一次小紅書就增加了一次MAU)
  • 消費:人均使用推薦的時長、人均閱讀筆記的數量
    • 通常與點擊率漲跌一致。若矛盾,應以北極星指標為準,如增加多樣性,點擊率不一定漲,但時長可能變多
  • 發布:發布滲透率、人均發布量
    • 激勵作者發布通常是由冷啟動來負責

實驗流程

  • 做離線實驗不需要把算法部署到產品中,沒有跟用戶實際交互,沒有占用線上流量
  • 離線實驗結果沒有線上實驗結果可靠(北極星指標都是線上指標,只能通過線上實驗獲得
  • AB測試:把用戶隨機分成實驗組和對照組,實驗組用新策略,對照組用舊策略,對比兩者的業務指標,判斷新策略是否會顯著優于舊策略。若是,可以加大流量,最終推全

2、推薦系統的鏈路

推薦系統的目標是從物品的數據庫中選出幾十個物品展示給用戶

召回(幾億->幾千)

從物品的數據庫中快速取回一些物品

幾十條召回通道,每條召回通道取回幾十~幾百個物品,一共取回幾千個物品作為候選集

  • 召回通道:協同過濾、雙塔模型、關注的作者等
  • 融合、去重、過濾(排除掉用戶不喜歡的作者、筆記、話題等)

讓排序決定該把哪些物品曝光給用戶,以及展示的順序。為了解決計算量的問題,將排序分為粗排和精排(二者非常相似,但精排模型更大,用的特征更多)

粗排(幾千->幾百)

規模較小的機器學習模型給幾千個物品逐一打分,按照分數做排序和截斷,保留分數最高的幾百個物品送入精排(也會用一些規則,保證進入精排的筆記具有多樣性)

  • 排序分為粗排和精排,平衡計算量和準確性
  • 召回和粗排是最大的漏斗

精排(幾百->幾百)

大規模深度神經網絡給幾百個物品逐一打分,做排序和截斷(截斷可選)

  • 精排相比粗排用的特征更多,計算量更大,模型打分更可靠
  • 把多個預估值做融合(比如加權和)得到最終的分數,分數決定會不會展示給用戶,以及展示的位置

重排(幾百->幾十)

根據精排分數和多樣性分數做隨機抽樣,得到幾十個物品。用規則把相似內容打散,并插入廣告和運營推廣內容,根據生態要求調整排序,即為最終展示給用戶的結果

  • 重排主要是做多樣性抽樣(如MMR、DPP)、規則打散、插入廣告和運營內容
    • 做多樣性抽樣(比如MMR、DPP),從幾百個物品中選出幾十個
    • 用規則打散相似物品
    • 插入廣告、運營推廣內容,根據生態要求調整排序

整條鏈路上,召回和粗排是最大的漏斗(候選物品從幾億->幾千->幾百)?

3、AB測試

目的:

  • 離線實驗的指標有提升,不代表線上實驗也會有收益。判斷新策略能帶來多大的業務指標收益
  • 模型中有一些參數,需要用AB測試選取最優參數,如GNN網絡的深度可以是1/2/3層

離線實驗結果正向,下一步是做線上的小流量AB測試(一般10%用戶)

隨機分桶

若用戶數量足夠大,每個桶的DAU/留存/點擊率等指標都是相等的

例:召回團隊實現了一種GNN召回通道,離線實驗結果正向。下一步是做線上的小流量A/B測試,考慮新的召回通道對線上指標的影響。模型中有一些參數,比如GNN的深度取值∈{1, 2, 3},需要用A/B測試選取最優參數

  • 1~3桶的GNN深度分別為1~3層,4號桶沒有用GNN做召回
  • 計算每個桶的業務指標,比如DAU、人均使用推薦的時長、點擊率等
  • 如果某個實驗組指標顯著優于對照組,則說明對應的策略有效,如2桶的業務指標與對照組的diff有顯著性,說明2層的GNN召回通道是有效果的,值得推全(把流量擴大到100%,給所有用戶都使用2層GNN召回通道)

分層實驗

目標:解決流量不夠用的問題

  • 信息流產品的公司有很多部門和團隊,都需要做AB測試
    • 推薦系統(召回、粗排、精排、重排)
    • 用戶界面
    • 廣告
  • 如果把用戶隨機分成10組,1組做對照,9組做實驗,那么只能同時做9組實驗,無法滿足產品迭代需求

分層實驗:召回、粗排、精排、重排、用戶界面、廣告...(例如GNN召回通道屬于召回層)

  • 同層互斥:GNN實驗占了召回層的4個桶,其他召回實驗只能用剩余的6個桶
    • 兩個召回實驗不會同時作用到同一個用戶上
    • 避免一個用戶同時被兩個召回實驗影響,若兩個實驗相互干擾,實驗結果將變得不可控
  • 不同層正交:每一層獨立隨機對用戶做分桶,每一層都可以獨立用100%的用戶做實驗
    • 一個用戶可以同時受一個召回實驗和一個精排實驗的影響,因為它們的效果不容易相互增強或抵消

互斥 vs 正交:

  • 如果所有實驗都正交,則可以同時做無數組實驗
  • 同類的策略(例如精排模型的兩種結構)天然互斥,對于一個用戶,只能用其中一種
  • 同類的策略(例如添加兩條召回通道)效果會相互增強或相互抵消。互斥可以避免同類策略相互干擾
  • 不同類型的策略(例如添加召回通道、優化粗排模型)通常不會相互干擾,可以作為正交的兩層

Holdout機制

  • 每個實驗(召回、粗排、精排、重排)獨立匯報對業務指標的提升
  • 公司考察一個部門(比如推薦系統)在一段時間內對業務指標總體的提升
  • 取10%的用戶作為holdout桶(對照組),推薦系統使用剩余90%的用戶做實驗,兩者互斥
  • 10% holdout桶 vs 90% 實驗桶的diff(需要對指標做歸一化)為整個部門的業務指標收益

  • 每個考核周期結束之后,清除holdout桶,讓推全實驗從90%用戶擴大到100%用戶
  • 重新隨機劃分用戶,得到holdout桶和實驗桶,開始下一輪考核周期
  • 新的holdout桶與實驗桶各種業務指標的diff接近0
  • 隨著召回、粗排、精排、重排實驗上線和推全,diff會逐漸擴大?

實驗推全

若業務指標的diff顯著正向,則可以推全實驗。如重排策略實驗,取一個桶作為實驗組,一個桶作為對照組,實驗影響了20%用戶,若觀測到顯著正向的業務收益,則可以推全

  • 把重排層實驗關掉,把兩個桶空出來給其他實驗
  • 推全時新開一層,新策略會影響全部90%用戶
  • 在小流量階段,新策略會影響10%用戶,會微弱提升實驗桶和hold桶的diff
  • 推全后,新策略作用到90%用戶上,diff會擴大9倍
  • 如ab測試發現新策略會提升點擊率9個萬分點,小流量實驗只作用10%用戶上,所以只能把跟holdout桶的diff提升1個萬分點,推全后,理論上可以把diff提升到9個萬分點,跟ab實驗得到的結果一致

反轉實驗?

  • 有的指標(如點擊、交互)立刻受到新策略影響,有的指標(留存)有滯后性,需要長期觀測
  • 實驗觀測到顯著收益后需要盡快推全新策略。目的是騰出桶供其他實驗開展,或需要基于新策略做后續的開發
  • 用反轉實驗解決上述矛盾,既可以盡快推全,也可以長期觀測實驗指標
  • 在推全的新層中開一個舊策略的桶,可以把反轉桶保留很久,長期觀測實驗指標
  • 一個考核周期結束之后,會清除holdout桶,會把推全新策略用到holdout用戶上,不影響反轉桶;當反轉實驗完成時,新策略會用到反轉桶用戶上,實驗真正推全,對所有用戶生效

  • 分層實驗:同層互斥(不允許兩個實驗同時影響同一位用戶)、不同層正交(實驗有重疊的用戶)
  • Holdout:保留10%的用戶完全不受實驗影響,可以考慮整個部門對業務指標的貢獻
  • 實驗推全:擴大到90%流量上,新建一個推全層,與其它層正交
  • 反轉實驗:為了在盡早推全新策略的同時還能長期觀測各種指標,在新的推全層上,保留一個小的反轉桶,反轉桶使用舊策略。反轉桶可以保留很久,長期觀測新舊策略的diff

(二)召回

1、基于物品的協同過濾(ItemCF)

ItemCF的原理

我喜歡看《笑傲江湖》,《笑傲江湖》與《鹿鼎記》相似,我沒看過《鹿鼎記》——> 給我推薦《鹿鼎記》

推薦系統如何知道《笑傲江湖》與《鹿鼎記》相似?

  • 基于知識圖譜:
    • 兩本書的作者相同,故兩本書相似
  • 基于全體用戶的行為:
    • 看過《笑傲江湖》的用戶也看過《鹿鼎記》
    • 給《笑傲江湖》好評的用戶也給《鹿鼎記》好評

ItemCF的實現

假設點擊、點贊、收藏、轉發四種行為各1分

算出來=3.2

逐一計算用戶對候選物品的興趣分數,返回分數高的topn個物品

物品相似度

兩個物品的受眾重合度越高,兩個物品越相似

  • 例如,喜歡《射雕英雄傳》和《神雕俠侶》的讀者重合度很高,可以認為它們相似
相似度介于0~1,數值越大表示兩個物品越相似

?

上述公式只要是喜歡就看作1,不喜歡就看作0,沒有考慮用戶喜歡的程度

集合v這部分用戶占比越大,兩個物品的相似度就越高?

?

考慮用戶喜歡的程度,如點擊、點贊、收藏、轉發各自算1分,用戶對物品的喜歡程度最多是4分

  • 分子表示同時喜歡兩個物品的用戶v(如果興趣分數的取值是0或1,那么分子就是同時喜歡兩個物品的人數)
  • 分母第一項表示用戶對物品i1的興趣分數,關于所有用戶求連加,然后開根號
  • 把一個物品表示成一個向量,向量每個元素表示一個用戶,元素的值就是用戶對物品的興趣分數,兩個向量的夾角的余弦就是這個公式
相似度介于0~1

?

ItemCF的基本思想:根據物品的相似度做推薦

  • 如果用戶喜歡物品Item1,而且物品Item1和Item2相似
  • 那么用戶很可能喜歡物品Item2

預估用戶對候選物品的興趣:

計算兩個物品的相似度:

  • 把每個物品表示為一個稀疏向量,向量每個元素對應一個用戶
  • 相似度sim就是兩個向量夾角的余弦

ItemCF召回的完整流程

為了能在線上實時推薦,必須要事先做離線計算,建立兩個索引

事先做離線計算

建立 “用戶->物品” 的索引

  • 記錄每個用戶最近點擊、交互過的物品ID
  • 給定任意用戶ID,可以找到他近期感興趣的物品列表

建立 “物品->物品” 的索引

  • 計算物品之間兩兩相似度
  • 對于每個物品,索引它最相似的k個物品
  • 給定任意物品ID,可以快速找到它最相似的k個物品

線上做召回
  1. 給定用戶ID,通過 “用戶->物品” 的索引,找到用戶近期感興趣的物品列表(last-n)
  2. 對于last-n列表中每個物品,通過“物品->物品” 的索引,找到top-k相似物品
  3. 對于取回的相似物品(最多有nk個),用公式預估用戶對物品的興趣分數
  4. 返回分數最高的100個物品,作為推薦結果(即ItemCF召回通道的輸出,會跟其他召回通道的輸出融合起來并排序,最終展示給用戶)

索引的意義在于避免枚舉所有的物品

  1. 記錄用戶最近感興趣的n=200個物品
  2. 取回每個物品最相似的k=10個物品
  3. 給取回的nk=2000個物品打分(用戶對物品的興趣)
  4. 返回分數最高的100個物品作為ItemCF通道的輸出

用索引,離線計算量大(需要更新2個索引),線上計算量小(不需訪問上億個物品)

ItemCF召回通道的輸出,會跟其他召回通道的輸出融合起來做排序

如果取回的物品ID有重復的,就去重,并把分數加起來

ItemCF的原理:

  • 用戶喜歡物品i1,那么用戶喜歡與物品i1相似的物品i2
  • 物品相似度:
    • 不是根據物品的內容判定物品相似,而是根據用戶行為
    • 如果喜歡i1、i2的用戶有很大的重疊,那么i1與i2相似

ItemCF召回通道:

  • 維護兩個索引:
    • 用戶->物品列表:用戶最近交互過的n個物品
    • 物品->物品列表:相似度最高的k個物品
  • 線上做召回:
    • 利用兩個索引,每次取回nk個物品
    • 預估用戶對每個物品的興趣分數:
    • 返回分數最高的100個物品,作為召回結果

2、Swing召回通道(ItemCF的變種)?

與ItemCF非常像,區別就是如何定義物品的相似度

ItemCF:?

?

ItemCF的問題:兩篇筆記受眾不同,但由于被分享到一個小圈子,導致很多用戶同時交互過這兩篇筆記。需要降低小圈子用戶的權重

Swing模型即給用戶設置權重,解決小圈子問題

α是個人工設置的參數;overlap為u1和u2的重疊,重疊大說明兩個人是一個小圈子,對相似度的貢獻應減小

Swing與ItemCF唯一的區別在于物品相似度

  • ItemCF:兩個物品重合的用戶比例高,則判定兩個物品相似
  • Swing:額外考慮重合的用戶是否來自一個小圈子
    • 同時喜歡兩個物品的用戶記作集合v
    • 對于v中的用戶u1和u2,重合度記作overlap(u1, u2)
    • 兩個用戶重合度大,則可能來自一個小圈子,權重降低

3、基于用戶的協同過濾(UserCF)

UserCF原理

有很多跟我興趣非常相似的網友,其中某個網友對某筆記點贊、轉發,而我沒看過這篇筆記,那么可能給我推薦這篇筆記

推薦系統如何找到跟我興趣非常相似的網友呢?

  • 點擊、點贊、收藏、轉發的筆記有很大的重合
  • 關注的作者有很大的重合

UserCF實現

0代表用戶沒有看過物品,或對物品不感興趣

計算出=2.8

用戶相似度

用戶有共同的興趣點,即喜歡的物品有重合

介于0-1,越接近1表示兩個用戶越相似

上述公式同等對待熱門和冷門的物品,需降低熱門物品的權重

物品越熱門,n_l?越大,分子(即物品的權重)越小?

UserCF的基本思想:

  • 如果用戶user1跟用戶user2相似,而且user2喜歡某物品,那么用戶user1也很可能喜歡該物品

預估用戶user對候選物品item的興趣:

計算兩個用戶的相似度:

  • 把每個用戶表示為一個稀疏向量,向量每個元素對應一個物品
  • 如果用戶對物品不感興趣,向量元素為0;若感興趣,元素為1,或1除以物品的熱門程度
  • 相似度sim就是兩個向量夾角的余弦

UserCF召回的完整流程

為了能在線上實時推薦,必須要事先做離線計算,建立兩個索引

事先做離線計算

建立 “用戶->物品” 的索引

  • 記錄每個用戶最近點擊、交互過的物品ID
  • 給定任意用戶ID,可以找到他近期感興趣的物品列表

建立?“用戶->用戶” 的索引

  • 對于每個用戶,索引他最相似的k個用戶
  • 給定任意用戶ID,可以快速找到他最相似的k個用戶

線上做召回
  1. 給定用戶ID,通過??“用戶->用戶” 的索引,找到topk相似用戶
  2. 對于每個top-k相似用戶,通過?“用戶->物品” 的索引,找到用戶近期感興趣的物品列表(last-n)
  3. 對于取回的nk個相似物品,用公式預估用戶對每個物品的興趣分數
  4. 返回分數最高的100個物品,作為召回結果

若取回的物品有重復的,去重,并把分數加起來

UserCF的原理:

  • 用戶u1跟用戶u2相似,而且u2喜歡某物品,那么u1也可能喜歡該物品
  • 用戶相似度:
    • 如果用戶u1和u2喜歡的物品有很大的重疊,那么u1和u2相似
    • (分母是做歸一化,讓相似度分數介于0~1之間)

UserCF召回通道:

  • 維護兩個索引:
    • 用戶->物品列表:用戶近期交互過的n個物品
    • 用戶->用戶列表:相似度最高的k個用戶
  • 線上做召回:
    • 利用兩個索引,每次取回nk個物品
    • 預估用戶user對每個物品item的興趣分數:
    • 返回分數最高的100個物品,作為召回結果

--------------------------------------------- 分割線,上面都是協同過濾召回 ---------------------------------------?

4、離散特征處理

  • 協同過濾召回(以上內容)
  • 向量召回(之后內容)

離散特征

如性別、國籍、英文單詞、物品ID、用戶ID

處理:

  • 建立字典:把類別映射成序號
  • 向量化:把序號映射成向量
    • One-hot編碼:把序號映射成高維稀疏向量,序號對應位置的元素為1,其他位置元素都是0
    • Embedding:把序號映射成低維稠密向量

One-Hot編碼

性別:男、女兩種類別

  • 字典:男->1,女->2
  • One-hot編碼:用2維向量表示性別
    • 未知 -> 0 -> [0, 0]
    • 男 -> 1 -> [1, 0]
    • 女 -> 2 -> [0, 1]

國籍:中國、美國、印度等200種類別

  • 字典:中國->1,美國->2,印度->3,...
  • One-hot編碼:用200維稀疏向量表示國籍
    • 未知 -> 0 -> [0, 0, 0, 0, ...,? 0]
    • 中國 -> 1 -> [1, 0, 0, 0, ...,? 0]
    • 美國 -> 2 -> [0, 1, 0, 0, ...,? 0]
    • 印度 -> 3 -> [0, 0, 1, 0, ...,? 0]

局限:類別數量太大時,通常不用one-hot編碼

Embedding(嵌入)

把每個類別映射為一個低維的稠密向量

參數數量 = 向量維度 × 類別數量

  • 設Embedding得到的向量都是4維的
  • 一共有200個國籍
  • 參數數量=800

編程實現:TensorFlow、Pytorch提供Embedding層

  • 參數以矩陣的形式保存,矩陣大小是向量維度×類別數量
  • 輸入是序號,比如美國的序號是2
  • 輸出是向量,比如美國對應參數矩陣的第2列

兩者聯系

Embedding其實就是矩陣向量乘法,類似全連接層

離散特征處理:One-hot編碼、embedding

類別數量很大時,用embedding,如:

  • word embedding
  • 用戶ID embedding
  • 物品ID embedding

------------------------------------------------- 分割線,下面都是向量召回 ------------------------------------------

5、矩陣補充(Matrix Completion)、最近鄰查找

矩陣補充(Matrix Completion)是向量召回最簡單的一種,已經不太常用,是為了幫助理解雙塔模型

矩陣補充模型結構

輸出是一個實數(用戶對物品興趣的預估值),越大表示用戶對物品越感興趣

  • 左邊的Embedding Layer:矩陣列的數量為用戶數量,每一列都是向量a這樣的對用戶的表征
  • 右邊的Embedding Layer
  • 兩個Embedding Layer不共享參數

矩陣補充模型訓練

(1)基本想法:

矩陣A和B是Embedding層的參數

?

(2)數據集:是很多三元組的集合

(3)訓練:讓模型的輸出擬合興趣分數

  • (u, i, y)三元組 是訓練集中的一條數據,表示 用戶u 對 物品i 的 真實興趣分數y
  • 對目標函數求min,可以用隨機梯度下降,每次更新A和B的一列

(4)直觀解釋:

綠色位置的數據訓練模型,預估所有灰色位置的分數。給定一個用戶,選出用戶對應行中分數較高的物品,推薦給用戶?

矩陣補充的缺點?

矩陣補充在實踐中效果不好,在工業界不work

  • 缺點1:僅用ID Embedding,沒利用物品、用戶屬性
    • 物品屬性:類目、關鍵詞、地理位置、作者信息
    • 用戶屬性:性別、年齡、地理定位、感興趣的類目
    • 雙塔模型可以看做矩陣補充的升級版,會結合物品屬性和用戶屬性
  • 缺點2:負樣本的選取方式不對
    • 樣本:用戶-物品的二元組,記作(u, i)
    • 正樣本:曝光之后,有點擊、交互(正確的做法)
    • 負樣本:曝光之后,沒有點擊、交互(錯誤的做法
  • 缺點3:做訓練的方法不好
    • 內積 <au, bi> 不如余弦相似度
    • 用平方損失(回歸),不如用交叉熵損失(分類)

矩陣補充線上服務

模型存儲:

  1. 訓練得到矩陣A和B。A的每一列對應一個用戶,B的每一列對應一個物品
  2. 把矩陣A的列存儲到key-value表,key是用戶ID,value是A的一列。給定用戶ID,返回一個向量(用戶Embedding)
  3. 矩陣B的存儲和索引比較復雜,不能簡單地用key-value存儲

線上服務:

近似最近鄰查找(Approximate Nearest Neighbor Search)

避免暴力枚舉(暴力枚舉計算量正比于物品數量),近似最近鄰查找的結果未必最優,但不會比最優差多少

支持最近鄰查找的系統:

  • 系統:Milvus、Faiss、HnswLib,等
  • 衡量最近鄰的標準:
    • 歐式距離最小(L2距離)
    • 向量內積最大(內積相似度):矩陣補充用的就是這個
    • 向量夾角余弦最大(cosine相似度):最常用,即夾角最小

有些系統不支持余弦相似度,可以把所有向量都做歸一化,讓它們的二范數等于1,那么內積就等于余弦相似度

每個點是一個物品的Embedding向量,a為用戶的Embedding向量

?

在做線上服務前,把數據劃分為很多區域:

  • cos相似度,劃分結果為扇形
  • 歐式距離,劃分結果為多邊形

劃分后,每個區域用一個向量表示,這些向量的長度都是1。劃分區域后,建立索引,key為每個區域的向量,value為區域中所有點的列表

首先計算用戶a與索引向量的相似度,通過索引找出該區域內的所有點,再計算用戶a與該區域所有點的相似度

矩陣補充:

  • 把物品ID、用戶ID做embedding,映射成向量
  • 兩個向量的內積<au, bi>作為 用戶u 對 物品i 興趣的預估
  • 讓<au, bi>擬合真實觀測的興趣分數,用回歸的方式學習模型的embedding層參數
  • 矩陣補充模型有很多缺點,效果不好。工業界不用矩陣補充,而是用雙塔模型

線上召回:

  • 把用戶向量a作為query,查找使得<a, bi>最大化的物品i(內積最大的 top k 物品i)
  • 暴力枚舉速度太慢,實踐中用近似最近鄰查找
  • Milvus、Faiss、HnswLib等開源向量數據庫支持近似最近鄰查找

6、雙塔模型(DSSM)

雙塔模型可以看做是矩陣補充模型的升級

模型結構

用戶離散特征:

  • 所在城市、感興趣的話題等:Embedding,不同的離散特征要用不同的Embedding層得到向量
  • 性別:對類別數量很少的離散特征,用One-hot編碼即可,可以不做Embedding

用戶連續特征:年齡、活躍程度、消費金額

  • 歸一化:讓特征的均值為0,標準差為1
  • 有些長尾分布的連續特征需要特殊處理,如取log、分桶

神經網絡可以是簡單的全連接網絡,也可以是更復雜的深度交叉網絡?

物品的表征類似處理

?

雙塔模型使用了ID之外的多種特征作為輸入,輸出介于-1~1的余弦相似度(余弦相似度相當于先對兩個向量做歸一化,再求內積,比內積更常用

正負樣本的選擇

  • 正樣本:歷史記錄顯示用戶喜歡的物品。如用戶點擊的物品
  • 負樣本:用戶不感興趣的物品
    • 沒有被召回的?
    • 召回但是被粗排、精排淘汰的?
    • 曝光但是未點擊的? —— 不能作為召回的負樣本,可以作為排序的負樣本

訓練方法

pairwise:Jui-Ting Huang et al. Embedding-based Retrieval in Facebook Search. In KDD, 2020.(Facebook)

listwise:

Xinyang Yi et al. Sampling-Bias-Corrected Neural Modeling for Large Corpus Item
Recommendations. In RecSys, 2019.(YouTube)
  1. pointwise:獨立看待每個正樣本、負樣本,做簡單的二元分類。即把正樣本和負樣本組成一個數據集,在數據集上做隨機梯度下降訓練雙塔模型
  2. pairwise:每次取一個正樣本、一個負樣本,組成一個二元組,損失函數為triplet hinge loss或triplet logistic loss
  3. listwise:每次取一個正樣本、多個負樣本,組成一個list,訓練方式類似于多元分類
pointwise訓練
  • 把召回看做二元分類任務
  • 對于正樣本,鼓勵 cos(a,b) 接近+1
  • 對于負樣本,鼓勵 cos(a,b) 接近-1
  • 控制正負樣本數量為1:2或者1:3(行業經驗)
pairwise訓練

輸入一個三元組,用戶的特征向量為a,兩個物品的特征向量為b+和b-。兩個物品塔共享參數

讓用戶對正樣本的興趣分數盡量高(最好接近+1),對負樣本的興趣分數盡量低(最好接近-1)

(1)Triplet Hinge Loss:孿生網絡?

m是個超參數

?

(2)Triplet Logistic Loss:讓cos(a, b-)盡量小,讓cos(a,b+)盡量大??

σ是個>0的超參數,控制損失函數的形狀
listwise訓練

最大化正樣本的余弦相似度,最小化負樣本的余弦相似度?

?

不適用于召回的模型

上圖為粗排/精排的模型,不能應用于召回

  • 前期融合,在進入全連接層之前就把特征向量拼起來了 —— 排序模型
  • 雙塔模型屬于后期融合,兩個塔在最終輸出相似度時才融合 —— 召回模型

前期融合的模型不適用于召回,否則要把所有物品的特征挨個輸入模型,預估用戶對所有物品的興趣,無法使用近似最近鄰查找來加速計算。通常用于排序(從幾千個物品中選出幾百個)

雙塔模型:

  • 用戶塔、物品塔各輸出一個向量
  • 兩個向量的余弦相似度作為興趣的預估值,越大,用戶越有可能對物品感興趣
  • 三種訓練方式:
    • pointwise:每次用一個用戶、一個物品(可正可負)
    • pairwise:每次用一個用戶、一個正樣本、一個負樣本。訓練目標是最小化triplet loss,即讓正樣本余弦相似度盡量大,負樣本余弦相似度盡量小
    • listwise:每次用一個用戶、一個正樣本、多個負樣本。訓練時用softmax激活+交叉熵損失,讓正樣本余弦相似度盡量大,負樣本余弦相似度盡量小

正負樣本

選對正負樣本的作用 > 改進模型結構

正樣本:

  • 正樣本:曝光而且有點擊的用戶-物品二元組(用戶對物品感興趣)
  • 問題:二八法則,少部分物品占據大部分點擊,導致正樣本大多是熱門物品。拿過多熱門物品當正樣本,會對冷門物品不公平,讓熱門更熱、冷門更冷
  • 解決方案:過采樣冷門物品,或降采樣熱門物品
    • 過采樣(up-sampling):一個樣本出現多次
    • 降采樣(down-sampling):一些樣本被拋棄。如以一定概率拋棄熱門物品,拋棄的概率與樣本的點擊次數正相關

負樣本:用戶不感興趣的物品,或鏈路上每一步被淘汰的物品

簡單負樣本:未被召回物品

(1)全體物品:從全體物品中做非均勻抽樣,作為負樣本

未被召回的物品,大概率是用戶不感興趣的。幾億個物品里只有幾千個被召回,故未被召回的物品 ≈ 全體物品

0.75是個經驗值

使用非均勻抽樣,熱門物品成為負樣本的概率大

(2)batch內負樣本

圖中是一個batch內的樣本。訓練時要鼓勵正樣本的余弦相似度盡量大,負樣本的余弦相似度盡量小

一個物品成為負樣本的概率越大,模型對這個物品打壓就會越狠?

修正偏差(糾偏),避免過分打壓熱門物品

這樣理解Batch內負樣本的修正:p越小,-logp越大,softmax結果s更高。如果是正樣本(s>0.5),那導數會偏小(輸出已經很接近正確標簽,不希望模型做出太大的調整);如果是負樣本,那導數會偏大。就形成了對低頻物品(p小)更強的負樣本的傾向,相當于是放大了冷門負樣本的梯度

-logp算是物品的先驗,模型實際上是非常容易擬合先驗的,所以要debias掉

注意,線上召回時,還是用原本的余弦相似度,不用做這種調整,不用減掉 logpi

困難負樣本:粗排/精排淘汰
  • 被粗排淘汰的物品 (比較困難)
  • 精排分數靠后的物品 (非常困難)

訓練雙塔模型,其實是對正負樣本做二元分類:

  • 全體物品(簡單)分類準確率高
  • 被粗排淘汰的物品 (比較困難) 容易分錯
  • 精排分數靠后的物品 (非常困難) 更容易分錯
訓練數據

混合幾種負樣本,50%的負樣本是從全體物品隨機非均勻抽樣得到(簡單負樣本),50%的負樣本是沒通過粗排精排的物品,即從粗/精排淘汰的物品中隨機抽樣得到(困難負樣本)

常見的錯誤

選擇負樣本的原理:

  • 召回的目標:快速找到用戶可能感興趣的物品,再交給后面的排序逐一甄別
    • 全體物品(easy): 絕大多數是用戶根本不感興趣的
    • 被排序淘汰(hard): 用戶可能感興趣,但是不夠感興趣。這樣的負樣本做分類時比較難以區分,所以是困難負樣本
    • 有曝光沒點擊(不能作為負樣本): 用戶感興趣,可能碰巧沒有點擊【 可以作為排序的負樣本,不能作為召回的負樣本

正樣本:曝光而且有點擊的用戶-物品二元組

簡單負樣本:

  • 全體物品中做非均勻隨機抽樣
  • batch內負樣本

困難負樣本:被召回,但是被排序淘汰(跟正樣本很像,做分類會有困難)

錯誤:曝光但是未點擊的物品做召回的負樣本。這類負樣本只能用于排序,不能用于召回

線上服務/線上召回

訓練好的兩個塔,分別提取用戶特征和物品特征

  • 向量數據庫存儲物品特征向量和ID的二元組,用作最近鄰查找
  • 不要事先計算和存儲用戶向量。當用戶發起推薦請求時,調用神經網絡現算一個特征向量a,然后把向量a作為query,去向量數據庫中檢索查找最近鄰

離線存儲:把物品向量b存入向量數據庫

  • 完成訓練之后,用物品塔計算每個物品的特征向量b
  • 把幾億個物品向量b存入向量數據庫,比如Milvus、Faiss、HnswLib
  • 向量數據庫建索引(把向量空間劃分成很多區域,每個區域用一個向量表示),以便加速最近鄰查找?

線上召回:查找用戶最感興趣的k個物品?

  • 給定用戶ID和畫像,線上用神經網絡算用戶向量a
  • 最近鄰查找:把向量a作為query,調用向量數據庫做最近鄰查找,返回余弦相似度最大的k個物品,作為召回結果
事先存儲物品向量b,線上現算用戶向量a,為什么?
  • 每做一次召回,用到一個用戶向量a,幾億物品向量b(線上算物品向量的代價過大)
  • 用戶興趣動態變化,而物品特征相對穩定 (可以離線存儲用戶向量,但不利于推薦效果)

訓練好雙塔模型之后,在開始線上服務之前,先要做離線存儲,在向量數據庫建好索引之后,可以做線上召回

跟ItemCF、Swing、UserCF等召回通道的結果融合

模型更新

全量更新(天級別)

今天凌晨,用昨天全天的數據訓練模型

  • 在昨天模型參數的基礎上做訓練(不是隨機初始化)
    • 用昨天全天的數據(要先random shuffle打亂,然后打包成TFRecord)訓練1個epoch,即每條數據只過一遍
  • 訓練完成后,發布新的用戶塔神經網絡(在線上實時計算用戶向量,作為召回的query)和物品向量(存入向量數據庫,向量數據庫會重新建索引,在線上做最近鄰查找),供線上召回使用
  • 全量更新對數據流、系統的要求比較低
    • 不需要實時的數據流,對生成訓練數據的速度沒有要求,延遲一兩個小時也沒關系。只需要把每天的數據落表,在凌晨做個批處理,把數據打包成TFRecord格式即可
    • 每天只需要把神經網絡和物品向量發布一次即可
  • 只有做全量更新時才更新全連接層
增量更新(分鐘級別)

做online learning更新模型參數,每隔幾十分鐘就要把新的模型參數發布出去,刷新線上的用戶塔Embedding層參數

  • 用戶興趣會隨時發生變化
  • 實時收集線上數據,做流式處理,實時生成訓練模型用的TFRecord文件
  • 對模型做online learning,梯度下降增量更新ID Embedding參數 (不更新神經網絡其他部分的參數,全連接層是鎖住的,不做增量更新;只有全量更新會更新全連接層參數)
  • 發布用戶ID Embedding(哈希表),供用戶塔在線上計算用戶向量,可以捕捉用戶最新的興趣點。這個過程會有延遲,但可以被縮短到幾十分鐘
全量 vs 增量

今天凌晨的全量更新,是基于昨天凌晨全量訓練出來的模型,而不是用下面增量訓練出來的模型。在完成這次全量之后,下面增量訓練出來的模型就可以扔掉了?

能否只做增量更新,不做全量更新?

  • 小時級數據有偏,統計值跟全天數據差別很大(不同時間段用戶的行為不同);分鐘級數據偏差更大
  • 全量更新: random shuffle (為了消除偏差)一天的數據,做 1 epoch 訓練
  • 增量更新:按照數據 從早到晚的順序 ,做 1 epoch 訓練
  • 隨機打亂 優于 按順序排列數據 全量訓練 優于 增量訓練

全量訓練的模型更好,而增量訓練可以實時捕捉用戶的興趣?

雙塔模型:

  • 用戶塔、物品塔各輸出?個向量,兩個向量的余弦相似度作為興趣的預估值,越大越好
  • 三種訓練的方式:pointwise、pairwise、listwise
  • 正樣本:用戶點擊過的物品
  • 負樣本:從全體物品中隨機抽樣 (簡單負樣本)、被排序淘汰的物品 (困難負樣本)

召回:

  • 做完訓練,把物品向量存儲到向量數據庫,供線上最近鄰查找
  • 線上召回時,給定用戶ID、用戶畫像,調用訓練好的用戶塔神經網絡 現算用戶向量a
  • 把a 作為query,查詢物品的向量數據庫,找到余弦相似度最高的k個物品向量,返回k個物品ID

更新模型:定期全量+實時增量

  • 全量更新: 今天凌晨,用昨天的數據訓練整個神經網絡,做 1 epoch 的隨機梯度下降(每條數據只用一遍)
  • 增量更新:用實時數據訓練神經網絡,只更新 ID? Embedding,鎖住全連接層不更新
  • 實際的系統:全量更新(每天)?& 增量更新(實時)?相結合。每隔幾十分鐘,發布最新的用戶 ID Embedding,供用戶塔在線上計算用戶向量(好處:捕捉用戶的最新興趣點)

7、雙塔模型+自監督學習

自監督學習:改進雙塔模型的方法,能提升業務指標,目的是把物品塔訓練的更好

雙塔模型的問題

  • 推薦系統的頭部效應嚴重:
    • 少部分物品占據大部分點擊
    • 訓練雙塔模型時用點擊數據作為正樣本,模型學習物品的表征靠的就是點擊行為
    • 大部分物品的點擊次數不高
  • 高點擊物品的表征學得好,長尾物品的表征學的不好(長尾物品的曝光和點擊次數太少,訓練的樣本數量不夠)
  • 自監督學習:對物品做data augmentation,更好地學習長尾物品的向量表征

雙塔模型的訓練(同時訓練用戶塔和物品塔)

用batch內負樣本

  • 一個batch內有n對正樣本
  • 組成n個list,每個list中有1對正樣本和n-1對負樣本
listwise訓練
用戶a,物品b

讓模型給正樣本打的分數盡量高,給負樣本打的分數盡量低

損失函數:考慮batch內第i個用戶和全部n個物品

listwise訓練雙塔模型的損失函數
糾偏

batch內負樣本會過度打壓熱門物品,造成偏差。如果用batch內負樣本,需要糾偏,使熱門物品不至于被過分打壓。訓練結束,在線上做召回時,還是用原本的余弦相似度?

訓練雙塔模型
  • i:第i個用戶
  • n:batch內一共有n個用戶

自監督學習(訓練物品塔)

  • 雙塔模型的listwise訓練方式,同時訓練用戶塔和物品塔
  • 自監督學習訓練物品塔

Tiansheng Yao et al. Self-supervised Learning for Large-scale Item Recommendations. In CIKM, 2021.?【Google】

盡管對應不同的特征變換,但同一物品的兩個向量表征應有較高的相似度?

不同物品的向量表征的分布應盡量分散開?

如何變換物品特征

四種方法:

  1. Random Mask(隨機選一些離散特征,將它們的值換為default)
  2. Dropout(僅對多值離散特征生效)
  3. 互補特征(將物品的多個特征隨機分組,鼓勵兩組特征形成的物品表征向量相似)
  4. Mask一組關聯的特征(計算互信息來衡量特征兩兩之間的關聯。隨機選一個特征,mask該特征及其最相關的k/2種特征,其余保留)

(1)Random Mask

一個物品可以有多個類目

  • 如果不做random mask,正常的特征處理方法是對數碼和攝影分別做embedding,得到兩個向量,再做求和或平均,得到一個向量,表征物品類目
  • 如果對類目特征做mask,這個物品的類目特征就變成了default。default表示默認的缺失值,對default做embedding,得到一個向量表征類目。也就是說,做mask后,物品的類目特征直接被丟掉(數碼和攝影都沒了)

(2)Dropout(僅對多值離散特征生效)

多值離散特征:離散特征 + 一個物品可以有多個該特征的取值

random mask是對整個類目特征的取值都丟掉,dropout只丟掉類目特征取值的50%

(3)互補特征(complementary)

由于是對同一物品的表征,訓練時要鼓勵cos相似度盡量大

正常的做法是把四種特征的值分別做embedding,然后拼起來輸入物品塔,最終得到物品的向量表征

(4)mask一組關聯的特征

特征之間有較強的關聯,遮住一個特征并不會損失太多的信息,模型可以從其他強關聯特征中學到遮住的特征

兩個特征關聯越強,p(u,v)就比較大,它們的互信息就越大

  • 好處:效果好,推薦的主要指標比random mask、dropout、互補特征等方法效果更好
  • 壞處:方法復雜,實現的難度大,不容易維護(每添加一個新的特征,都需要重新計算所有特征的MI)
如何用變換后的特征訓練模型
每個物品被表征為2個向量

?

這里冷熱門物品被抽樣到的概率是相同的(注意跟訓練雙塔的區別。訓練雙塔得到的數據是根據點擊行為抽樣的,熱門物品被抽到的概率大。雙塔抽的是用戶-物品二元組,這里只抽物品)?

考慮batch中第i個物品的特征向量bi',和全部m個物品的特征向量b'':

訓練時希望向量si接近yi,說明物品塔訓練的好,即使做隨機特征變換,對物品的向量表征也影響不大。用yi和si的交叉熵作為損失函數

雙塔模型存在的問題:

  • 雙塔模型學不好低曝光物品的向量表征(其實這是數據的問題,而不是雙塔模型的問題。真實推薦系統都存在頭部效應,小部分物品占據了大部分的曝光和點擊)

Google提出一種自監督學習的方法,用在雙塔模型上效果很好(低曝光物品、新物品的推薦變得更準

  • 對一個物品用兩種特征變換,物品輸出兩個特征向量
  • 同一物品的兩個不同特征變換得到的向量應該有高相似度
  • 不同物品應讓物品的向量表征盡量分散在整個特征空間上

訓練:

  • 對點擊做隨機抽樣,得到n對用戶-物品二元組作為一個batch。這個batch用來訓練雙塔,包括用戶塔和物品塔。根據點擊做抽樣,熱門物品被抽到的概率高
  • 從全體物品中均勻抽樣,得到m個物品作為另一個batch。熱門和冷門物品被抽到的概率是相同的,這個batch用來做自監督學習,只訓練物品塔
  • 做梯度下降使損失函數減小。α決定自監督學習起到的作用

8、Deep Retrieval召回

Deep Retrieval(字節):

Weihao Gao et al. Learning A Retrievable Structure for Large-Scale Recommendations. In
CIKM , 2021.
TDM(阿里): Han Zhu et al. Learning Tree-based Deep Model for Recommender Systems. In KDD , 2018.
  • 經典的雙塔模型把用戶、物品表示為向量,線上做向量最近鄰查找
  • Deep Retrieval把物品表征為路徑(path),線上查找用戶最匹配的路徑,從而召回一批物品(類似于阿里的TDM,但更簡單)

Deep Retrieval和TDM都用深度學習,但都不做向量最近鄰查找

索引:關聯路徑和物品

L1~L3表示結構的3層(深度depth),每一層里面有K個節點(寬度width)

路徑就是幾個節點連接起來,路徑可以有重合的節點

物品->路徑的索引:訓練神經網絡時要用到

  • 一個物品對應多條路徑
  • 用3個節點表示一條路徑:path = [a,b,c]

路徑->物品的索引:線上做召回時要用到

  • 一條路徑對應多個物品(給定一條路徑,會取回很多個物品作為召回的結果)

預估模型-神經網絡(尋找用戶感興趣的路徑)

給定用戶特征,預估用戶對路徑的興趣分數(根據用戶特征,召回多條路徑)

預估用戶對路徑的興趣:

假設結構有3層?

過程:

Deep Retrieval結構:3層,每層K個節點
  • 如果結構的每一層有k個節點,那么p1就是一個k維向量
  • 向量p1對應L1層,向量p1的k個元素是神經網絡對L1層k個節點打的分。分數越高,節點就越有可能被選中(用Beam Search的方法。假設選中節點a)
  • 向量x不變,直接作為下一層的輸入,對節點a做embedding,與x做concat,輸入另一個神經網絡
3層神經網絡不共享參數
  • 假設根據向量p1,從k個節點中選出節點a。把向量x和節點a一起送入下一層神經網絡,輸出k維向量p2(對應結構中的第二層)
  • 同理選出節點b,把向量x和節點a、b一起輸入下一層神經網絡。從3層中各選出一個節點,組成路徑 [a,b,c]

線上召回:user->path->item

給定用戶特征,召回一批物品

用Beam Search召回一批路徑:

beam size(每層選的節點數量)越大,計算量越大,但同時search的結果也會越好(最簡單的情況即beam size=1)

Beam Search相當于貪心算法,選中的節點分別最大化p1、p2、p3,但獨立對p1、p2、p3求最大化,未必會最大化這三項的乘積?

p1、p2、p3分別是三層神經網絡的輸出

?

選中路徑path=[5,4,1]

?

size大一些,結果會比貪心算法好一些,但計算量也變大?

步驟:

  • 第一步:給定用戶特征,用神經網絡做預估,用beam search召回一批路徑
  • 第二步:利用索引,召回一批物品
    • 查看索引path->item(在線上做召回之前,線下已經把路徑和物品匹配好了)
    • 每條路徑對應多個物品
  • 第三步:對物品做排序,選出一個子集作為最終召回結果
    • 用小的排序模型來打分排序,如雙塔模型,防止物品超出召回通道的配額

離線訓練(同時學習神經網絡參數和物品表征)

神經網絡可以判斷用戶對物品的興趣,物品表征則是把物品映射到路徑

訓練時只用正樣本,用戶-物品二元組,只要用戶點過物品就算正樣本

學習神經網絡參數

判斷用戶對路徑有多感興趣

x是用戶的特征
學習物品表征

解釋:圖中的用戶都點擊過左邊的物品,如果其中很多用戶也對路徑感興趣(興趣分數是神經網絡預估出來的),我們就判斷物品和路徑有很強的關聯,可以把路徑作為物品的表征?

用戶是物品和路徑之間的中介

最小化損失,相當于根據score對path做排序,排序結果的top j,即對于每個物品item,選擇score最高的j條路徑,作為物品的表征?

為了防止非常多的物品集中在一條路徑上的情況,希望每條path上的item數量比較平衡,需要用正則項約束path。如果某條path上已經有了很多item,這條path就會受到懲罰,避免關聯到更多物品

物品與J條路徑的相關性越高,損失函數就越小;正則reg控制路徑l上的物品不要太多?

交替訓練神經網絡和物品表征

訓練神經網絡時,把物品當做中介,將用戶和路徑關聯起來

線上召回:用戶->路徑->物品(兩階段,先用神經網絡尋找用戶感興趣的路徑,路徑長度與神經網絡層數相關;再取回路徑上的物品)

這里也說明了為什么要用正則項控制一條path上的item不能太多,否則有時候召回的物品數量會特別多,有時候會特別少

Deep Retrieval召回的本質是用路徑作為用戶和物品之間的中介

雙塔模型召回的本質是用向量表征作為用戶和物品之間的中介

離線訓練:同時學習 用戶-路徑物品-路徑 的關系

避免讓索引失去平衡

9、其他召回通道

地理位置召回

GeoHash召回(附近召回)

用戶可能對附近發生的事感興趣

  • GeoHash:對經緯度的編碼(把經緯度編碼為二進制哈希碼),地圖上一個長方形區域(以GeoHash作為索引,記錄地圖上一個長方形區域內的優質筆記)
  • 索引:GeoHash -> 優質筆記列表(按時間倒排,即最新的筆記排在最前面)
  • 召回時,給定用戶的GeoHash,會取回這個區域內比較新的一些優質筆記

召回純粹只看地理位置,完全不考慮用戶興趣(就是因為沒有個性化,才需要考慮優質筆記。筆記本身質量好,即使沒有個性化,用戶也很可能會喜歡看;反之,既沒有個性化,又不是優質筆記,召回的筆記大概率通不過粗精排)

同城召回

用戶可能對同城發生的事感興趣

  • 根據用戶所在城市和曾經生活過的城市做召回
  • 索引:城市 -> 優質筆記列表(按時間倒排)

這條召回通道沒有個性化

作者召回

關注的作者召回

用戶對關注的作者發布的筆記感興趣

  • 索引:用戶->關注的作者,作者->發布的筆記(按時間順序倒排,新發布的筆記排在最前面)
  • 召回:用戶->關注的作者->最新的筆記
有交互的作者召回

即使沒關注作者,如果推送有交互作者發布的筆記也可能會感興趣而繼續看

如果用戶對某筆記感興趣(點贊、收藏、轉發),那么用戶可能對該作者的其他筆記感興趣

  • 索引:用戶->有交互的作者
  • 召回:用戶->有交互的作者->最新的筆記

作者列表需要定期更新,保留最新交互的作者,刪除一段時間沒有交互的作者

相似作者召回

如果用戶喜歡某作者(感興趣的作者包括用戶關注的作者+用戶有交互的作者),那么用戶喜歡相似的作者。取回每個作者最新的一篇筆記

相似性的計算類似于ItemCF:如果兩個作者的粉絲有很大重合,那么兩個作者相似

緩存召回

想法:復用前n次推薦精排的結果(精排前50但是沒有曝光的,緩存起來,作為一條召回通道)

  • 精排輸出幾百篇筆記,送入重排;重排做多樣性的隨機抽樣(如DPP),選出幾十篇
  • 精排結果一大半沒有曝光,被浪費

問題:緩存大小固定(比如最多存100篇筆記),需要退場機制。有很多條規則作為退場機制,如

  • 一旦筆記成功曝光,就從緩存退場
  • 如果超出緩存大小,就移除最先進入緩存的筆記
  • 筆記最多被召回10次,達到10次就退場
  • 每篇筆記最多被保存3天,達到3天就退場

還能再細化規則,如想要扶持曝光比較低的筆記,那么可以根據筆記的曝光次數來設置規則,讓低曝光的筆記在緩存中存更長時間

三大類、六條召回通道:

  • 地理位置召回:用戶對自己附近的人和事感興趣
    • GeoHash召回、同城召回
  • 作者召回:
    • 關注的作者、有交互的作者、相似的作者
  • 緩存召回:把精排中排名高、但是沒有成功曝光的筆記緩存起來,再多嘗試幾次

10、曝光過濾 & Bloom Filter

曝光過濾通常在召回階段做,具體的方法就是用Bloom Filter(給用戶曝光過等價于用戶看過

曝光過濾問題

實驗表明,重復曝光同一個物品會損害用戶體驗(抖音、小紅書);但YouTube這樣的長視頻就沒有曝光過濾,看過的可以再推薦??

在小紅書,n和r的量級都是幾千,暴力對比的計算量太大。實踐中不做暴力對比,而是用Bloom Filter

Bloom Filter

判斷一個物品ID是否在已曝光的物品集合中

  • 如果判斷為no,那么該物品一定不在集合中
  • 如果判斷為yes,那么該物品很可能在集合中(可能誤傷,錯誤判斷未曝光物品為已曝光,將其過濾掉

概括一下:根據Bloom Filter的判斷做曝光過濾,肯定能干掉所有已經曝光的物品,用戶絕對不可能重復看到同一個物品;但是有一定概率會誤傷,召回的物品明明沒有曝光過,卻被Bloom Filter給干掉了?

Burton H. Bloom. Space/time trade-offs in hash coding with allowable
errors. Communications of the ACM, 1970.

Bloom Filter是一種數據結構?

  • 把物品集合表征為一個m維二進制向量(每個元素是一個bit,要么是0要么是1)
  • 每個用戶有一個曝光物品的集合,表征為一個向量,需要m bits的存儲
  • 有k個哈希函數,每個哈希函數把物品ID映射成介于 0~m-1 之間的整數
  • k和m都是需要設置的參數

最簡單的情況:k=1(只有1個哈希函數)?

初始向量全0

向量的某個位置已經是1的話,不需要修改數值?
  • 如果Bloom Filter認為沒有曝光,那么這個物品肯定沒有曝光(不可能把已曝光的物品誤判為未曝光)
  • 如果Bloom Filter認為已曝光,有可能是正確的,有可能是誤判(有一定概率把未曝光物品認為已曝光,導致未曝光物品被過濾掉)

k=3,用3個不同的哈希函數把物品ID映射到3個位置上,把3個位置的元素都置為1。同樣地,如果向量的某個位置元素已經是1,不需要修改數值??

每個曝光物品只需要占幾個bits的存儲

?

如果物品已經曝光,那么其3個位置肯定都是1,如果其中某個位置為0,說明該物品實際未曝光

Bloom Filter誤傷的概率:?

用戶歷史記錄上有n個曝光物品,只需要 m=10n bits,就可以把誤差概率降低到1%以下

推薦系統中曝光過濾的鏈路
  • 推薦系統的鏈路:多路召回、粗排、精排、重排,最終選出一批物品曝光給用戶
  • 曝光過濾的鏈路:把曝光的物品記錄下來,更新Bloom Filter,用于過濾召回的物品

APP前端有埋點,所有曝光的物品都會被記錄下來。但這個落表的速度要足夠快,在用戶推薦界面下一刷之前,就要把本次曝光的結果寫到Bloom Filter上,否則下一刷很可能會出重復的物品,所以要用實時流處理,比如把曝光物品寫入Kafka消息隊列,用Flink做實時計算

Flink實時讀取Kafka消息隊列,計算曝光物品的哈希值,把結果寫入Bloom Filter的二進制向量。用這樣的實時數據鏈路,在曝光發生幾秒之后,這位用戶的Bloom Filter就會被修改,之后就能避免重復曝光

曝光過濾用在召回完成之后。召回服務器請求曝光過濾服務,曝光過濾服務把用戶的二進制向量發送給召回服務器,在召回服務器上用Bloom Filter計算召回物品的哈希值,再跟二進制向量對比,把已經曝光的物品過濾掉,剩余的物品都是未曝光的,發送給排序服務器

Bloom Filter缺點
小紅書首頁只推薦年齡小于1個月的物品

?

只需要計算出k個哈希值(k是哈希函數的數量)

刪除物品,不能簡單把這個物品對應的k個元素從1改為0,否則會影響其他物品。這是因為向量的元素是所有物品共享的,如果把向量的一個元素改為0,相當于把很多物品都移除掉了。想要刪除一個物品,需要重新計算整個集合的二進制向量

推薦系統的曝光過濾問題、Bloom Filter數據結構


(三)排序

1、多目標排序模型

推薦系統的鏈路

  • 有很多條召回通道,從幾億篇筆記中取出幾千篇
  • 從中選出用戶最感興趣的,要用到粗排和精排,粗排給召回的筆記逐一打分,保留分數最高的幾百篇
  • 然后用精排模型給粗排選出的幾百篇筆記打分,不做截斷,讓幾百篇筆記全都帶著精排分數進入重排
  • 重排做多樣性抽樣,把相似內容打散,最終有幾十篇筆記被選中,展示給用戶

粗排、精排原理基本相同,只是粗排模型小,特征少,效果差一些,粗排的目的是做快速的初步篩選(如果不用粗排,直接把很大的精排模型用在幾千篇候選筆記上,計算代價大)

排序的依據

以小紅書為例,排序的主要依據是用戶對筆記的興趣,興趣可以反映在用戶與筆記的交互上。對于每篇筆記,系統記錄以下統計量:

  • 曝光次數(impression):一篇筆記被展示給多少用戶
  • 點擊次數(click):一篇筆記被多少用戶點開
  • 點贊次數(like)
  • 收藏次數(collect)
  • 轉發(share)

可以用點擊率之類的消費指標衡量一篇筆記受歡迎的程度

  • 點擊率 = 點擊次數 / 曝光次數
  • 點贊率 = 點贊次數 / 點擊次數(收藏率、轉發率同理)。用戶點開筆記之后才會發生點贊、收藏、轉發等行為,故分母是點擊次數,而不是曝光次數

排序依據:?

  • 在把筆記展示給用戶之前,需要事先預估用戶對筆記的興趣(排序模型預估點擊率、點贊率、收藏率、轉發率等多種分數);
  • 融合這些預估分數,比如加權和(比如點擊率的權重是1,點贊率、收藏率、轉發率的權重是2),權重是做ab測試調出來的
  • 根據融合的分數做排序、截斷,保留分數高的筆記

簡單的多目標模型

排序模型的輸入是各種各樣的特征

  • 用戶特征:用戶ID、用戶畫像
  • 物品特征:物品ID、物品畫像、作者信息(筆記的作者)
  • 統計特征:
    • ??????????????用戶統計特征(用戶在過去30天中一共曝光/點擊...了多少篇筆記)
    • 物品統計特征(候選物品在過去30天中一共獲得了多少次曝光/點擊...機會)
  • 場景特征:隨著用戶請求傳過來的,包含
    • 當前時間(如當前是否是周末或節假日)
    • 用戶所在地點(候選物品和用戶是否在同一城市)
神經網絡可以是全連接,或Wide&Deep,等等

輸出4個預估值,都介于0~1之間,排序主要依靠這4個預估值?

?

模型訓練:

4個任務,每個任務都是一個二元分類,如判斷用戶是否會點擊物品。用交叉熵損失函數

權重αi是根據經驗設置的

?

實際訓練中會有很多困難,如類別不平衡(正樣本少,負樣本多)

  • 每100次曝光,約有10次點擊、90次無點擊
  • 每100次點擊,約有10次收藏、90次無收藏

解決方案:負樣本降采樣(down-sampling)

  • 保留一小部分負樣本
  • 讓正負樣本數量平衡,節約計算(比如原本一天積累的數據需要在集群上訓練10h,做降采樣后,負樣本減少很多,訓練只需3h)

預估值校準

給定用戶特征和物品特征,用神經網絡預估出點擊率、點贊率等分數之后,要對這些預估分數做校準,做完校準之后才能把預估值用于排序?

為什么要做校準?

α(采樣率)越小,負樣本越少,模型對點擊率的高估就會越嚴重

Xinran He et al. Practical lessons from predicting clicks on ads at Facebook. In the 8th International Workshop on Data Mining for Online Advertising.

對預估點擊率的校準公式:左邊的?p_{true}?表示校準之后的點擊率,右邊是對預估點擊率?p_{pred}?做的變換,α為采樣率

在線上做排序時,首先讓模型預估點擊率p_{pred},然后用上述公式做校準,拿校準之后的點擊率p_{true}做排序的依據

排序的多目標模型,用于估計點擊率、點贊率等指標。做完預估之后,要根據負采樣率對預估值做校準

2、Multi-gate Mixture-of-Experts(MMoE)

模型結構

Google的論文提出MMoE模型:Jiaqi Ma et al. Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts. In KDD, 2018.

模型的輸入是一個向量,包含用戶特征、物品特征、統計特征、場景特征

  • 3個神經網絡結構相同,都是由很多全連接層組成,但它們不共享參數
  • 3個神經網絡各輸出一個向量,即3個“專家”(實踐中通常用4個或8個。專家神經網絡的數量是個超參數,需要手動調)

左、右邊的神經網絡也有多個全連接層
  • softmax輸出向量的3個元素都>0且相加為1?
  • p1~p3分別對應3個專家神經網絡,之后會將這3個元素作為權重,對向量x1~x3做加權平均。q1~q3同理

神經網絡可以有一個或多個全連接層,其輸出取決于具體的任務,比如輸出對點擊率的預估,是一個介于0~1之間的實數

這里假設多目標模型只有點擊率和點贊率兩個目標,所以只有兩組權重。

對神經網絡輸出的向量做加權平均,用加權平均得到的向量去預估某個業務指標。若多目標模型有n個目標,就要用n組權重

MMoE問題:極化現象

YouTube的論文提出極化問題的解決方案:Zhe Zhao et al. Recommending What Video to Watch Next: A Multitask Ranking System. In RecSys, 2019.

softmax會發生極化(Polarization):softmax輸出值一個接近1,其余接近0

如左邊softmax輸出值 ≈ [0,0,1],說明左邊的預估點擊率任務只使用了第三號專家神經網絡(沒有讓三個專家神經網絡的輸出融合,只是簡單使用了一個專家)

那么MMoE就相當于一個簡單的多目標模型,不會對專家做融合,失去了MMoE的優勢

解決極化問題:

如果有n個專家神經網絡,那么每個softmax的輸入和輸出都是n維向量。不希望看到其中一個輸出的元素接近1,其余n-1個元素接近0

在訓練時,對softmax的輸出使用dropout,這樣會強迫每個任務根據部分專家做預測

  • softmax輸出的n個數值被mask的概率都是10%
  • 每個專家被隨機丟棄的概率都是10%

如果用dropout,不太可能會發生極化,否則預測的結果會特別差。假如發生極化,softmax輸出的某個元素接近1,萬一這個元素被mask,預測的結果會錯得離譜。為了讓預測盡量精準,神經網絡會盡量避免極化的發生,避免softmax輸出的某個元素接近1。用了dropout,基本上能避免極化

用MMoE不一定會有提升,有可能是實現不夠好,也有可能是不適用于特定的業務場景

3、預估分數的融合公式

多目標模型輸出對點擊率、點贊率等指標的預估。怎么融合多個預估分數?介紹工業界排序的幾種融分公式

加權和

Pclick表示模型預估的點擊率,權重為1;其他以此類推

Pclick*1就是預估的點擊率,Pclick*Plike是曝光之后用戶點贊的概率

海外某短視頻APP的融分公式

Ptime是指預估短視頻的觀看時長(比如預測用戶會觀看10s),w1和α1都是超參數,通過線上ab選出合適的值

國內某短視頻APP(快手)的融分公式

不是直接用預估的分數,而是用每個分數的排名

α和β都是需要調的超參數。預估的播放時長越長,排名越靠前,r_{time}越小,最終得分就越高

某電商的融分公式

指數α1~α4是超參數,需要調。若都為1,該公式就表示電商的營收,有很明確的物理意義

4、視頻播放建模

播放時長&完播率2個指標

指標1:視頻播放時長

  • 圖文筆記排序的主要依據:點擊、點贊、收藏、轉發、評論...
  • 視頻排序的依據還有播放時長和完播

視頻播放時長是連續變量,但直接用回歸擬合效果不好,建議用YouTube的時長建模

Paul Covington, Jay Adams, & Emre Sargin. Deep Neural Networks for YouTube Recommendations. In RecSys, 2016.

神經網絡叫做Share Bottom(被所有任務共享),每個全連接層對應一個目標(比如點擊、點贊、收藏、播放時長),這里只關心播放時長的預估:?

對z(實數,可正可負)做sigmoid變換得到p=sigmoid(z),讓p擬合y = t / (1+t)(?t表示用戶實際觀看視頻的時長,t越大,y也越大),訓練中用p和y的交叉熵作為損失函數【訓練完畢后,p就沒有用了

CE(y, p) = y*logp + (1-y)*log(1-p)

可以用exp(z)作為播放時長的預估線上做推理時,只用z的指數函數,把它作為對播放時長t的預估

總結一下,右邊的全連接層輸出z,對z做sigmoid變換得到p,在訓練中用p

y(= t / (1+t),其中t為播放時長)和p的交叉熵作為損失函數訓練模型,訓練完成后p就沒有用了;

線上做推理時,只用z的指數函數,把它作為對播放時長t的預估?

建模

實踐中把分母1+t去掉也沒問題,相當于給損失函數做加權,權重是播放時長

最終把exp(z)作為融分公式中的一項,它會影響到視頻的排序

指標2:視頻完播率

2種建模方法:回歸;二元分類

回歸方法

y的大小介于0~1之間?

二元分類方法

需要算法工程師自己定義完播指標

預估的播放率會跟點擊率等指標一起作為排序的依據

?

有利于短視頻,而對長視頻不公平

視頻越長,函數值f越小,把調整之后的分數記作p_{finish},可以反映出用戶對視頻的興趣,而且對長、短視頻是公平的

p_{finish}?與播放時長、點擊率、點贊率等指標一起,決定視頻的排序

視頻的排序;視頻有兩個獨特的指標:播放時長完播率

5、排序模型的特征

排序所需特征

用戶畫像特征(User Profile)

召回和排序的模型中都有用戶屬性,用戶屬性記錄在用戶畫像中

  • 用戶ID(在召回、排序中做embedding)
    • 用戶ID本身不攜帶有用的信息,但作用很大,通常用32 or 64維向量
  • 人口統計學屬性:性別、年齡等
  • 賬號信息:新老(用戶注冊時間)、活躍度...
    • 模型需要專門針對新用戶和低活用戶做優化
  • 感興趣的類目、關鍵詞、品牌
    • 屬于用戶興趣信息,這些信息可以是用戶自己填寫的,也可以是算法自動提取的
筆記畫像特征(Item Profile)
  • 物品ID(在召回、排序中作embedding)
  • 發布時間(或者年齡)
    • 在小紅書,一篇筆記發布時間越久,價值就越低,尤其是強時效性話題
  • GeoHash(經緯度編碼)、所在城市
    • GeoHash表示地圖上一個長方形的區域
  • 標題、類目、關鍵詞、品牌...
    • 筆記的內容,通常對這些離散的內容特征做Embedding
  • 字數、圖片數、視頻清晰度、標簽數...
    • 筆記自帶的屬性,反映出筆記的質量,筆記的點擊和交互指標與之相關
  • 內容信息量、圖片美學...
    • 算法打的分數,事先用人工標注的數據訓練cv和nlp模型,當新筆記發布時,用模型給筆記打分,把分數寫到物品畫像中,可以作為排序模型的特征
統計特征(用戶/筆記)

(1)用戶統計特征:

  • 用戶最近30天 (7天、1天、1小時) 的曝光數、點擊數、 點贊數、收藏數…
    • 各種時間粒度,可以反映出用戶的實時興趣、短期興趣和中長期興趣
  • 按照筆記 圖文/視頻 分桶 (比如最近7天,該用戶對圖文筆記的點擊率、對視頻筆記的點擊率)
    • 對圖文、視頻兩類筆記分開做統計,可以反映出用戶對兩類筆記的偏好
  • 按照筆記類目分桶 (比如最近30天,用戶對美妝筆記的點擊率、對美食筆記的點擊率、對科技數碼筆記的點擊率)

(2)筆記統計特征:

  • 筆記最近30天 (7天、1天、1小時) 的曝光數、點擊數、點贊數、收藏數…
    • 統計量反映出筆記的受歡迎程度。如果點擊率、點贊率等指標都很高,說明筆記質量高,算法應該給這樣的筆記更多的流量
    • 時間粒度是針對筆記的實效性。若筆記已經過時(如30天指標高,但1天指標低),不應該給更多的流量
  • 筆記受眾:按照用戶性別、年齡、地域分桶
  • 作者特征:發布筆記數、粉絲數、消費指標(曝光數、點擊數、點贊數、收藏數)
    • 作者統計特征反映了作者的受歡迎程度以及作品的平均品質
場景特征(Context)

隨著推薦請求傳來的,不用從用戶畫像、筆記畫像等數據庫中獲取

  • 用戶定位GeoHash (經緯度編碼) 、城市
    • 用戶可能對自己附近的事感興趣
  • 當前時刻 (分段,做embedding)
    • 一個人在同一天不同時刻的興趣可能有所區別
  • 是否是周末或節假日
    • 周末或節假日用戶可能對特定的話題感興趣
  • 手機品牌、手機型號、操作系統
    • 安卓or蘋果

特征處理

離散特征:做embedding

  • 用戶ID、筆記ID、作者ID(數量大,消耗內存大)
  • 類目、關鍵詞、城市、手機品牌

連續特征:做分桶,變成離散特征

  • 年齡(如把連續的年齡變為十個年齡段,做one-hot或Embedding)、筆記字數、視頻長度

連續特征:其他變換

  • 曝光數、點擊數、點贊數等數值做log(1+x),可以解決異常值問題
    • 曝光數等(大多數筆記只有幾百次,少數筆記能有上百萬次)為長尾分布,計算會出現異常(訓練梯度會很離譜,推理的預估值會很奇怪)
  • 或者把點擊、點贊等轉化為點擊、點贊等值,并做平滑(去掉偶然性造成的波動)
  • 實際處理中,兩種變換之后的連續特征都會作為模型的輸入,如log(1+點擊數)、平滑之后的點擊率都會被用到

特征覆蓋率

特征工程需要注重特征覆蓋率

  • 理想情況下,每個特征都能覆蓋100%樣本,即不存在特征缺失
  • 但實際很多特征無法覆蓋100%樣本,例:
    • 很多用戶不填年齡,因此用戶年齡特征的覆蓋率遠小于100%
    • 很多用戶設置隱私權限,APP不能獲得用戶地理定位,因此場景特征有缺失

提高特征覆蓋率,可以讓精排模型更準;另外還要考慮,當特征缺失時,用什么作為默認值

數據服務(線上服務的簡化版系統架構)

  • 用戶畫像(User Profile)
  • 物品畫像(Item Profile)
  • 統計數據

以上3個數據源都存儲在內存數據庫中。線上服務時,排序服務器會從3個數據源取回所需的數據,然后把讀取的數據做處理,作為特征喂給模型,模型就能預估出點擊率、點贊率等指標

當用戶刷小紅書時,用戶請求會被發送到推薦系統的主服務器上,主服務器會把請求發送到召回服務器上。做完召回后,召回服務器會把幾十路召回的結果做歸并,把幾千篇筆記的ID返回給主服務器(召回需要調用用戶畫像)

主服務器把筆記ID、用戶ID、場景特征(1個用戶ID+幾千個筆記ID。筆記ID是召回的結果,用戶ID和場景特征都是從用戶請求中獲取的,場景特征包括當前時刻、用戶所在地點以及手機的型號和操作系統)發送給排序服務器

接下來,排序服務器要從多個數據源中取回排序所需的特征,主要是這3個數據源:用戶畫像、物品畫像、統計數據

  • 用戶畫像數據庫線上壓力小,因為每次只讀1個用戶的特征
    • 性別、年齡幾乎不變
    • 用戶活躍度、興趣標簽等為天級別的刷新
  • 物品畫像數據庫壓力大,因為粗排要給幾千篇筆記排序,讀取幾千篇筆記的特征
    • 物品自身屬性、算法給物品打的標簽在很長一段時間內不會發生變化

對用戶畫像和物品畫像最重要的是讀取速度快,而不太需要考慮時效性,因為它們都是靜態的,甚至可以儲存在排序服務器本地,讓讀取變得更快

  • 統計數據:用戶統計值的數據庫壓力小,存物品統計值的數據庫壓力大
    • 統計數據不能在本地緩存,因為它動態變化,時效性很強

在收集到排序所需的特征之后,排序服務器把特征打包傳給TF Serving。TensorFlow會給筆記打分,把分數返回給排序服務器,排序服務器會用融合的分數、多樣性分數、業務規則給筆記排序,把排名最高的幾十篇筆記返回給主服務器,這就是最終給用戶曝光的筆記

6、粗排模型

粗排 vs 精排

粗排犧牲準確性,以保證線上推理的速度快(目的是做初步篩選,從幾千篇筆記中選出幾百篇,而不是真正決定把哪些筆記曝光給用戶);精排的模型足夠大,犧牲更多的計算,確保預估的準確性足夠高

精排模型 & 雙塔模型

Shared Bottom含義為被多個任務共享【精排模型的代價主要在這,因為它很大,神經網絡也很復雜】

精排模型屬于前期融合(先對所有特征做concatenation,再輸入神經網絡),但線上推理代價大(如果有n篇候選筆記,整個大模型要做n次推理)

兩個向量的余弦相似度表明用戶是否對物品感興趣

在訓練好模型之后,把物品向量b存儲在向量數據庫,在線上不需要用物品塔做計算。線上推理只需要用到用戶塔,每做一次推薦,用戶塔只做一次推理,計算出一個向量a【雙塔模型的計算代價很小,適合做召回

雙塔模型屬于后期融合(把用戶、物品特征分別輸入不同的神經網絡,不對用戶、物品特征做融合,直到最后才計算a和b的相似度),線上計算量小(用戶塔只需要做一次線上推理,計算用戶表征a;物品表征b事先儲存在向量數據庫中,物品塔在線上不做推理),但預估準確性不如精排模型

粗排的三塔模型

小紅書的粗排是三塔模型,效果介于雙塔和精排之間

借鑒【阿里媽媽】Zhe Wang et al. COLD: Towards the Next Generation of Pre-Ranking System. In DLP- KDD , 2020

交叉特征是指用戶特征和物品特征做交叉

訓練粗排模型的方法就是正常的端到端訓練,跟精排完全一樣

三塔模型介于前期融合(把底層特征做concatenation)和后期融合之間,是把三個塔輸出的向量做concatenation

  • 物品的屬性相對比較穩定,可以把物品塔輸出向量緩存在PS,每隔一段時間刷新一次。由于做了緩存,物品塔在線上幾乎不用做推理,只有遇到新物品時才需要做推理。粗排給幾千個物品打分,物品塔實際只需要做幾十次推理,所以物品塔的規模可以比較大
  • 統計特征會實時動態變化(每當一個用戶發生點擊等行為,其統計特征都發生變化;每當一個物品獲得曝光和交互,其點擊次數、點擊率等指標都會發生變化)。由于交叉塔的輸入會實時發生變化,不應該緩存交叉塔輸出的向量,交叉塔在線上的推理避免不掉,故交叉塔必須足夠小、計算夠快(通常來說交叉塔只有一層,寬度也比較小)

模型的上層結構:?

模型上層做n次推理,代價大于交叉塔的n次推理

三塔模型的線上推理

  • 物品塔輸出的向量事先緩存在Parameter Server上,只有當沒有命中緩存時,才需要物品塔做推理(實際上緩存命中率非常高,99%的物品都能命中緩存,不需要做推理。給幾千個候選物品做粗排,物品塔只需要做幾十次推理)
  • 交叉塔的輸入都是動態特征,不能做緩存
  • 三個塔各輸出一個向量,融合起來作為上層網絡的輸入

粗排大部分的計算量都在上層網絡

粗排模型的設計理念:盡量減小推理的計算量,使得模型可以在線上給幾千篇筆記打分

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

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

相關文章

C#中的比較和邏輯運算符

在C#編程中&#xff0c;比較和邏輯運算符是控制程序流程和執行條件判斷的重要工具。以下是C#中一些常用的比較和邏輯運算符及其示例。 相等運算符 運算符用于比較兩個值是否相等。如果相等&#xff0c;返回 true&#xff1b;否則返回 false。 示例 int a 5, b 5; bool is…

【busybox記錄】【shell指令】unlink

目錄 內容來源&#xff1a; 【GUN】【unlink】指令介紹 【busybox】【unlink】指令介紹 【linux】【unlink】指令介紹 使用示例&#xff1a; 刪除文件 - 默認 常用組合指令&#xff1a; 指令不常用/組合用法還需繼續挖掘&#xff1a; 內容來源&#xff1a; GUN &#x…

深入解析Web前端三大主流框架:Angular、React和Vue

Web前端三大主流框架分別是Angular、React和Vue。下面我將為您詳細介紹這三大框架的特點和使用指南。 Angular 核心概念: 組件(Components): 組件是Angular應用的構建塊,每個組件由一個帶有裝飾器的類、一個HTML模板、一個CSS樣式表組成。組件通過輸入(@Input)和輸出(…

【OrangePi AIpro】開箱初體驗以及OAK深度相機測試

1. 簡介 Orangepi AIPRO 是一款采用昇騰AI技術路線&#xff0c;集成4核64位處理器AI處理器的單板計算機&#xff0c;集成圖形處理器&#xff0c;支持8TOPS AI算力&#xff0c;擁有8GB/16GB LPDDR4X&#xff0c;可以外接eMMC模塊&#xff0c;支持雙4K高清輸出。 Orange Pi AIpr…

VirtualDisplay圖像數據流trace分析

1. 計算器App更新圖像幀&#xff08;QueuedBuffer - ViewRootImpl[Calculator]#0BLAST#0&#xff09;&#xff0c;調用eglSwapBuffersWithDamageKHR&#xff0c;然后queueBuffer向surfaceflinger提交圖像buffer 2. sf調用latchBuffer獲取buffer&#xff0c;進行一些狀態的處理…

CBK-D2-安全與架構工程.md

CBK-D2-安全與架構工程 密碼學和對稱密鑰算法 密碼通信的基礎知識 明文P-plaintext、加密encrypt、密文C-ciphertext、解密decrypt、密鑰Key 多數情況下,密鑰無非是一個極大的二進制數 每一種算法都有一個特定密鑰控制key space,是一個特定的數值范圍 密鑰空間由位大小b…

數字圖像處理系列 | 線性濾波(高斯濾波)(3)

我們知道了什么是 線性平移不變系統是在做卷積操作 之后&#xff0c;我們發展出了一些非常簡單的 線性濾波&#xff0c; 去增強圖片&#xff0c;提取圖片特征 文章目錄 1. 卷積如何在離散圖片中工作的Vis 原圖和mask做卷積時發生了什么首先&#xff0c;如何得到 (i.j)位置的卷積…

操作系統中的內存管理

虛擬內存 操作系統會提供一種機制&#xff0c;將不同進程的虛擬地址和不同內存的物理地址映射起來。如果程序要訪問虛擬地址的時候&#xff0c;由操作系統轉換成不同的物理地址&#xff0c;這樣不同的進程運行的時候&#xff0c;寫入的是不同的物理地址&#xff0c;這樣就不會沖…

Python 技能提升(一)

python注釋規范 # Add commit for you codes. # The proper addition of comments is so beautiful.from abc import abstractmethoddef add(a: int, b: int) -> int:# You can write some necessary notes here.# Such as the role of functions, the types and roles of …

Slurm集群使用基礎

Introduction 我們在做生物信息分析時&#xff0c;對于大規模的上游數據的處理&#xff0c;一般需要在大型服務器或集群上進行。我最早接觸并使用的是一個基于SLURM調度系統的集群&#xff0c;在此記錄一下基礎使用方法。 高性能計算集群&#xff08;High-Performance Comput…

React 使用JSX或者TSX渲染頁面

02 Rendering with JSX Your first JSX content In this section, we’ll implement the obligatory " Hello, World " JSX application. At this point, we’re just dipping our toes in the water; more in-depth examples will follow. We’ll also discuss wh…

vs code中編寫c++基本使用以及問題總結

vs code基本使用以及總結 launch.json作用 這個文件配置了調試器的設置&#xff0c;允許你定義如何啟動和調試你的程序。這包括配置執行路徑、傳遞給程序的參數、環境變量以及特定語言或框架的調試器選項。 常用配置 "version": "0.2.0": 這是配置文件…

kotlin基礎之協程

Kotlin協程&#xff08;Coroutines&#xff09;是Kotlin提供的一種輕量級的線程模型&#xff0c;它允許我們以非阻塞的方式編寫異步代碼&#xff0c;而無需使用回調、線程或復雜的并發API。協程是一種用戶態的輕量級線程&#xff0c;它可以在需要時掛起和恢復&#xff0c;從而有…

安卓中的圖片壓縮

安卓中如何進行圖片壓縮&#xff1f; 在安卓中進行圖片壓縮通常有以下幾種方法&#xff1a; 質量壓縮: 通過降低圖片的質量來減小文件大小。這可以通過Bitmap的compress()方法實現&#xff0c;其中可以設置壓縮質量&#xff08;0-100&#xff09;。 ByteArrayOutputStream baos…

【滲透測試】|文件上傳

1、安裝使用蟻劍 https://blog.csdn.net/weixin_42474304/article/details/116376746 1、登陸dvwa,進入初級文件上傳&#xff0c;上傳一句話木馬文件cmd.php&#xff0c; //cmd.php <?php eval($_POST[ccit]); ?> //eval: 執行命令的函數 //ccit:一句話木馬文件的參數…

滲透測試工具Cobalt strike-2.CS基礎使用

三、結合metasploit,反彈shell 在kali中開啟使用命令開啟metasploit msfconsole ┌──(root?oldboy)-[~] └─# msfconsole --- msf6 > use exploit/multi/handler [*] Using configured payload generic/shell_reverse_tcp --- msf6 exploit(multi/handler) > show …

[10] CUDA程序性能的提升 與 流

CUDA程序性能的提升 與 流 1. CUDA程序性能的提升 在本節中,我們會看到用來遵循的基本的一些性能來提升準則,我們會逐一解釋它們1.1 使用適當的塊數量和線程數量 研究表明,如果塊的數量是 GPU 的流多處理器數量的兩倍,則會給出最佳性能,不過,塊和線程的數量與具體的算法…

什么是訪問控制漏洞

什么是AC Bugs&#xff1f; 實驗室 Vertical privilege escalation 僅通過隱藏目錄/判斷參數來權限控制是不安全的&#xff08;爆破url/爬蟲/robots.txt/Fuzz/jsfinder&#xff09; Unprotected functionality 訪問robots.txt 得到隱藏目錄&#xff0c;訪問目錄 &#xff0c;…

基于Visual Studio版本的AI編程助手

Visual Studio 是一個出色的 IDE,可用于構建適用于 Windows、Mac、Linux、iOS 和 Android 的豐富、精美的跨平臺應用程序。 使用一系列技術(例如 WinForms、WPF、WinUI、MAUI 或 Xamarin)構建豐富。 1、安裝 點擊上方工具欄拓展選項,選擇管理拓展選項 接著在聯機頁面中搜索&q…

基于51單片機的室內空氣質量檢測-仿真設計

本設計是基于單片機的空氣質量檢測設計&#xff0c;主要實現以下功能&#xff1a; 可實現通過SGP30測量二氧化碳及甲醛濃度&#xff0c;當超過設置的最大值時&#xff0c;進行報警及通風和凈化空氣處理 可實現通過MQ-4測量甲烷濃度&#xff0c;當超過設置的最大值時&#xff0…