要做一個CTR預估模型;

通過之前的數據挖掘,我得到了用戶對標籤的偏好數據:

[(標籤1, 0.8), (標籤2, 0.65), (標籤3, 0.32), (標籤4, 0.05)]

列表的每一個元素包含兩個分量,分別是標籤、偏好權重;

問題是,這樣的一個特徵,怎樣輸入到模型?

我只知道,對於標籤1、標籤2、標籤3這樣是分類特徵,可以用one hot編碼;

然而我不知道這裡的權重怎麼使用呢?,我想到2種方法:1、先給標籤1、標籤2、標籤3做one-hot編碼,然後自己找到每個數字為1的位置,把數字1替換成權重;2、對所有標籤映射到一個大數組,找到標籤在數組的下標,設置為權重,其他的都是0;

這兩種方法哪種更好,或者有其他方法嗎?

這個問題也有其他場景:用戶的歷史行為比如播放的ID列表,統計會得到:

[播放itemid,頻次]的列表,怎麼作為特徵輸入到模型?


方法一

第一種作法是在DNN中比較常見的「先embedding,再pooling」的作法。

  • 假設輸入是:[(標籤1, 0.8), (標籤2, 0.65), (標籤3, 0.32), (標籤4, 0.05)]
  • 把每個標籤先embedding,再和其權重相乘法,最後再按位相加
  • 即喂入上層DNN的向量是:0.8*emb(標籤1)+0.65*emb(標籤2)+0.32*emb(標籤3)+0.05*emb(標籤4)
  • 如果願意,還可以再做一下歸一化,即[0.8*emb(標籤1)+0.65*emb(標籤2)+0.32*emb(標籤3)+0.05*emb(標籤4)]/(0.8+0.65+0.32+0.05)

這種作法有一個好處就是,標籤的embedding可以復用。比如,我們要用到「近xxx天活躍app」+「近xxx天新安裝app」+「近xxx天卸載app」這三個field為特徵,這些 field中的feature都來源於同一個」app字典」。

  • 如果不共享embedding,每個field都使用獨立的embedding矩陣來映射app向量,整個模型需要優化的變數是共享權重模型的3倍,既耗費了更多的計算資源,也容易導致過擬合。
  • 如果不共享embedding,每個field的稀疏程度是不一樣的,同一個app,在「活躍列表」中出現得更頻繁,其embedding向量就有更多的訓練機會,而在「卸載列表」中較少出現,其embedding向量得不到足夠訓練,恐怕最後與隨機初始化無異

因此,在實際系統中,「共享embedding」是必須的,

  • 減小優化變數的數目,既節省計算資源,又減輕「過擬合」風險
  • 同一個embedding矩陣,為多個field提供映射向量,類似於「多任務學習」,使每個embedding向量得到更多的訓練機會,同時也要滿足多個field的需求(比如同一個app的向量,既要體現『經常使用它』對y的影響,也要體現『卸載它』對y值的影響),也降低了「過擬合」的風險。

如何在TensorFlow中實現「共享embedding」,請見我的另一篇文章《用TensorFlow實現支持多值、稀疏、共享權重的DeepFM》。

方法二

在方法一中,我們認為每個「標籤」所含有的信息是固定的(因為每個標籤只有一個embedding),權重只是「量變」。

如果深究一下,以上假設一定成立嗎?比如,用戶A點擊過一篇帶「軍事」標籤的文章,用戶B點擊過100篇帶「軍事」標籤的文章。按照方法一喂入模型,那麼模型所看到的,「軍事」這個標籤對用戶B的影響,一定是對用戶A影響的100倍。但是這其中一定是線性關係嗎?

我在《推薦演算法的"五環之歌"》表明過我的觀點,在推薦演算法中,categorical特徵纔是一等公民,實數型特徵不受歡迎。原因之一就是,在實際場景下,線性關係是非常罕見的

用戶A點擊軍事可能是一時興起,用戶B可能是超級軍迷,這其中的區別可不是線性100倍那麼簡單,而是「質變」。所以,另一種處理思路就是

  • 將「標籤+權重」拼接成一個特徵,比如在剛才的例子中,「看軍事1次」和「看軍事100次」是兩個完全不同的特徵
  • 如果使用FM或者DNN,這兩個特徵分別有自己獨立的embedding;如果考慮一階項,這兩個特徵有自己獨立的一階權重
  • 這樣,兩個特徵對模型的貢獻是「非線性」地「截然不同」,體現「質變」的思想。

當然在實際實現時,還有很多細節需要考慮

  • 我們不可能直接拿權重去拼接,那樣得到的特徵就太稀疏了。肯定需要先對實數型的權重先分桶,再拼接,比如在剛才的例子中,實際產生的特徵可能是「看軍事不足5次」和「看軍事在[50,200]之間
  • 即使這樣,產生的特徵空間還是太大了,所以需要使用hashing trick。即拿「特徵+權重」拼接後的特徵名,先取hash,再對一個預設的最大特徵空間維度(比如3億)取餘,得到的index纔是特徵在embedding矩陣中的下標
  • 最大特徵空間的維度不能太小,否則有hash衝突的風險,有可能單機容納不下,所以需要藉助Parameter Server對embedding矩陣分散式存儲與計算

這種將「標籤+權重」拼接成categorical特徵的作法,除了以上提到的豐富特徵的表達能力之外,還有一個額外的好處就是減少訓練、預測的開銷。以LR為例,[公式],將「標籤+權重」拼接成categorical特徵之後,那麼[公式]只能是0或1,則LR在線上預測時簡化為[公式],即找到非零特徵對應的權重並累加,避免了乘法運算,計算速度更快。同樣的優化,也適用於FM或DNN。

小結

以上兩種作法,我都在項目中實踐過,其實差別沒那麼大。但是由於方法二有便於開發、便於線上工程實現、性能優異的特點,目前是我們在工業級推薦項目中的首選方案


這個問題抽象出來就是給定一個由若干個(item_id,weight)組成的列表,如何將這個信息用在模型裡面。通常來說這種列表的含義可以是用戶歷史偏好的item_id以及偏好權重,或者歷史收藏加購過的商品或者對應店鋪的次數等等。

對於問題中的數據 [(標籤1, 0.8), (標籤2, 0.65), (標籤3, 0.32), (標籤4, 0.05)]

一般情況有一下兩種做法來使用這個信息:

  1. 不考慮上下文因素,直接將這個列表輸入。
  • 回歸到最簡單的情況,給定一個無權序列,我們一般可以通過sum/mean pooling 的方式將一個變長序列壓縮到一個定長的向量,輸入給我們的模型。
  • 那麼對於帶權序列,其實可以看作是一個weighted sum/mean pooling的過程,其實有點類似引入一個attention機制,只不過attention score是預先計算好的。
  • 這種方法完整保留了用戶所有的偏好信息,更多的是作為一種用戶側表徵。

對於上述數據,我們得到的表示向量為(不考慮score的歸一化)

0.8*emb(標籤1)+0.65*emb(標籤2)+0.32*emb(標籤3)+0.05*emb(標籤4)

2. 考慮上下文因素,根據當前預估item進行一個查表操作。

  • 比如我們當前打分item屬於標籤1,那麼直接查表得到(標籤1, 0.8),這個時候我們可以選擇直接使用權重0.8作為輸入,或者選擇用0.8*emb(標籤1)作為輸入。
  • 這種方法表達的是用戶對於當前item的偏好。


謝邀

這個做CTR?我感覺現在說的CTR都是對於用戶序列的處理,傳統的非序列無差別歷史數據處理已然不多,且不存在多種用戶行為

題主實際上問的是對於推薦系統數據的預處理方式,和後面的演算法關係不大,可以轉化為最傳統的推薦系統表示形式(關聯矩陣)

數據預處理:對於每一個用戶進行權重歸一化,表示為標準的distribution,沒有打標的數據標記為blank

數據表示和矩陣分解:此時整個可以表示為一個矩陣,那基本上傳統的方法都可以用了FM-Based(FM,DeepFM,SVD++)

題主所說的兩種方式,第一種就是直接構建關聯矩陣,並將權值作為此時矩陣對應位置的值,且並未歸一化

第二種是相當於對於softmax歸一化之後的行向量max,即 [公式]

第二種更為合理

處理方法的選擇:當數據表示成關聯矩陣之後預處理就取決於你的偏好權重是不是有偏的(個體的評價標準不同,有的人給分高,有的人給粉底),是不是重疊的(能否同時買兩個還是互斥的),上面提到過一些預處理方法,根據具體情況調節,如果互斥通常需要歸一化,如果有偏通常需要減去平均值

對於不同的場景,[id,freq]這種類型的數據,採用上面的思路,是有偏的(每個人看的頻率不同,有的人看的本來就多,每種都高,有的人看的都很少),需要減去平均值,是否是互斥的?我們通常認為是互斥的,需要歸一化,在netflix大獎賽中,採用了減去平均值的預處理方式做用戶打分處理,然後計算distribution。


你的第二種方法是咋處理?


當作兩類特徵來處理(連續特徵和離散特徵),把離散特徵標籤做embedding,得到長度為H的向量,然後再將0.8這個連續特徵權重concat到embedding的後面,得到H+1長度的向量,作為這個特徵的表示。


第一次回答,和大家交流。

可以嘗試用countvector,其中行名是用戶,列名是item,然後中間的值就是weight,可以獲得一個非常稀疏的表。

具體後續的處理方法呢,就看具體的任務了,計算相似度,直接入模都可以的。

另外,如果緯度實在太大的話,可以用svd降維,或者用線性分類器stacking,效果都很好。


不同的模型有不同的格式要求吧,不過fm這一類處理高維稀疏數據的模型有個比較常見的格式libsvm~


可以先把標籤one-hot,再embedding,標籤的權重再乘以embedding向量,權重類似attention用。


推薦閱讀:
相關文章