全部產品
Search
文件中心

Platform For AI:改進版swing相似性計算演算法

更新時間:Mar 13, 2025

本文為您介紹改進版swing相似性計算演算法原理,包括工具包下載、工具包詳細參數說明以及常見問題等。

改進版swing演算法

改進1:限定common neighbour數量

原版的swing演算法對於物品的同時被觸達的使用者數量過少的情況,並不適用。從統計學的角度來看,資料量過少,會導致結果的誤差過大。也就是說當同時觸達兩個物品的使用者數量過少時,這時候swing計算得出的結果誤差會比較大。

舉個極端的例子:

如下圖所示,有A、B、C三個視頻,X1到X10共10個皇馬死忠球迷,只關注音樂的音樂愛好者Y。皇馬死忠球迷會看與皇馬相關的內容,不管是發燒影片C,還是中低頻視頻A,他們都會觀看,可以假定他們都看了200個關於皇馬的視頻。其中有一個球迷X1,被其他朋友推薦了一首冷門音樂B,聽完發現不喜歡這種暗黑系古典音樂,還是喜歡比較激昂的皇馬隊歌A。音樂愛好者Y會聽各種音樂,不管是A,還是B,都會播放。那麼在這種情況下,由於視頻A、B的共現使用者量過少(只有2個),從而導致swing演算法得出的分數s(A,B)=0.33 > s(A,C)=0.22。但是很明顯,使用者在觀看視頻A的時候,推薦視頻C比推薦視頻B要好。

解法方法:問題是由兩個視頻的同時被看的使用者數量過少導致的,所以我們需要根據同時觀看過兩個視頻的使用者數量來對結果進行處理。我們在swing的基礎上,往其公式中增加了指示函數 Id(.) 來達到去噪的目的。同時,引入行為權重來打壓過熱的使用者或物品。改進後的公式如下:​

image.png

改進2:支援情境i2i

情境i2i —— 基於swing演算法學習全網點擊與情境點擊的共現,傾向於預測使用者在情境內的點擊,形式化表示如下:

image.png

下圖給出了全網i2i與情境i2i的結構圖,與全網i2i相比,情境i2i不考慮無情境心智(情境內無點擊)的使用者,只保留使用者與情境內點擊的邊。

改進版swing部署

  1. 下載演算法包到本地:swing-1.0.jar

如果下載不了,拷貝上述連結到瀏覽器開啟。

  1. 在MaxCompute專案空間下添加Jar包資源。

    image.png

    備忘:同一專案空間只需要部署一次。

輸入輸出格式

輸入表(支援分區表)至少包含兩列:

  • user_id:  bigint/string類型(代碼不檢查具體類型)的使用者ID或session id(推薦)

  • item_list: string類型的物品列表,物品與物品之間的分隔字元為英文分號(;),每個物品用bigint類型的ID表示

item序列由分號分割,每個點擊物品由至少3個欄位構成,即item_id,norm,timestamp,scene,其中item_id需要在開頭。

norm代表物品近期的熱度(比如,統計該item被多少個使用者點擊過),即當前item的模,用於懲罰超級熱門的item,解決“哈利傳輸速率效應”問題。如果不知道norm如何計算,或者資料本身“哈利傳輸速率效應”不嚴重,可以不填這一列。

“哈利傳輸速率效應”通常是指一種現象,即一個非常受歡迎和廣泛知名的專案(比如《哈利傳輸速率》系列書籍或電影)會在推薦列表中佔據主導地位,導致其它專案難以獲得同等的關注。

備忘:norm值僅跟當前物品相關,表示物品的全域熱度,跟目前使用者無關;在整個訓練資料集裡,同一物品的norm值必須要在多條記錄裡保持一致。

timestamp遵循 %Y%m%d%H%M%S(如:20190805223205) 的格式,如不需要可以用同一個timestamp填充。應按照點擊時間順序由遠至近組織item_list。

scene是可選欄位,為使用者行為所在的情境,用於支援情境i2i。

user_id

item_list

12031602

558448406561,137,20190805223205;585456515773,39397,20190806170331;10200442969,81,20190807223820

3954442742

658448406561,137,20190805223206;485456515773,39397,20190806170335

注意:同一條record中的item_list不要有重複的item_id, 建議 <user, item> pair每天只保留一個, 輸入表中的user_id的實際內容處理成 concat(user_id, date) 作為一個虛擬session_id。

輸出表格式(支援分區列):

  • item_id   bigint類型的錨定物品ID

  • similar_items  相似物品列表

其中similar_items形如item_id1,score1,coccur1,ori_score1;item_id2,score2,coccur2,ori_score2;...其中,ori_score1 是原始相似性分;score1是最大值歸一之後的分數;coccur1是共現次數。

注意:輸出表需要預先建立好,column類型不能搞錯,column name可自訂。

結果樣本:

item_id

similar_items

1084315

7876717,0.000047,2,0.003601;6929557,0.000250,2,0.019373;1084342,0.000780,4,0.060325;1089552,0.000963,4,0.074516;1083467,0.008233,5,0.637016;66042,0.012925,6,1.000000

1090195

1090172,0.015136,1,1.000000

參考命令列

在DataWorks上建立 ODPS MR 節點(ODPS SQL類型的節點可能會報錯),使用如下命令提交Job

jar [<GENERIC_OPTIONS>] <MAIN_CLASS> [ARGS];
        -conf <configuration_file>         Specify an application configuration file
        -resources <resource_name_list>    file\table resources used in mapper or reducer, seperate by comma
        -classpath <local_file_list>       classpaths used to run mainClass
        -D<name>=<value>                  Property value pair, which will be used to run mainClass
ARGS: <in_table/input_partition> <out_table/output_partition>

舉例如下:

公用雲端(彈外)使用者的命令:

##@resource_reference{"swing-1.0.jar"}
jar -resources swing-1.0.jar 
  -classpath swing-1.0.jar 
  -DtopN=150
  -Dmax.user.behavior.count=500
  -Dcommon.user.number.threshold=0
  -Dmax.user.per.item=600
  -Ddebug.info.print.number=10
  -Dalpha1=5
  -Dalpha2=1
  -Dbeta=0.3
  -Dodps.stage.mapper.split.size=1
  com.alibaba.algo.PaiSwing
  swing_click_input_table/ds=${bizdate}
  swing_output/ds=${bizdate}
;

注意:完整程式碼封裝括第一行的注釋; -D<key>=<value>指定參數值,-D後面不能有空格

彈內使用者的命令:

jar -resources swing-1.0.jar 
  -classpath http://schedule@{env}inside.cheetah.alibaba-inc.com/scheduler/res?id=XXXXX
  -DtopN=150
  -Dmax.user.behavior.count=500
  -Dcommon.user.number.threshold=0
  -Dmax.user.per.item=600
  -Ddebug.info.print.number=10
  -Dalpha1=5
  -Dalpha2=1
  -Dbeta=0.3
  -Dodps.stage.mapper.split.size=1
  com.alibaba.algo.PaiSwing
  swing_click_input_table/ds=${bizdate}
  swing_output/ds=${bizdate}
;

彈內classpath的擷取方式:

在DataWorks裡右擊swing資源套件,點擊“歷史版本”擷取檔案路徑(http開頭)

參數說明

參數名稱

參數描述

參數類型

common.user.number.threshold

同時訪問的使用者數量(過濾力度的設定),設定過大會導致剩下的結果過少,該參數需要根據具體業務情境進行調整探索

預設為0

max.user.per.item

每個物品使用多少個使用者的點擊序列來計算k近鄰

整數,預設值為700

max.user.behavior.count

每個使用者的最長序列長度,如果超過該長度會對最近進行截斷保留

整數,預設值為600

debug.info.print.number

輸出debug資訊的記錄數

整數,預設值為10

alpha1

swing演算法參數,見公式[1]

整數,預設值為5

beta

swing演算法參數,見公式[1]

實數,預設值為0.3

alpha2

swing演算法參數,見公式[1]

整數,預設值為1

user.column.name

使用者或session ID的列名

字串,預設值:"user_id"

item.list.column.name

{物品ID,Norm}列表欄位的列名

字串,預設值:"item_list"

topN

每個trigger物品保留的k近鄰數目

整數,預設值為200

odps.stage.mapper.split.size

【控制並發數】每個mapper處理的資料量

整數,單位M,預設值256

odps.stage.reducer.num

【控制並發數】計算物品Pair相似性的reducer的數量

整數,預設值為200

item.delimiter

input table中item list的分隔字元

預設值英文分號

item.field.delimiter

input table中item info的分隔字元

預設值英文逗號

pos_norm

物品熱度所對應欄位,從0開始,在上述範例中1

整數,預設值為1

pos_time

pos_time timestamp對應的欄位編號,從0開始,在上述範例中為2

整數,預設值為2

pos_scene

情境名對應的欄位編號,從0開始

整數,預設值為3

target.scene.name

目標情境名,用於情境i2i建模

預設為全網i2i

max.time.span

認為兩個物品存在鄰居關係的最長點擊間隔天數

整數,預設值為1

do_supplement_by_adamic_adar

當相似item數量不足topN時,是否嘗試用Adamic/Adar演算法補足

boolean, 預設值為true

FAQ

1. java.lang.ClassCastException: com.aliyun.odps.io.LongWritable cannot be cast to com.aliyun.odps.io.Text

FAILED: ODPS-0123131:User defined function exception - Traceback:
java.lang.ClassCastException: com.aliyun.odps.io.LongWritable cannot be cast to com.aliyun.odps.io.Text
 at com.aliyun.odps.udf.impl.batch.TextBinary.put(TextBinary.java:55)
 at com.aliyun.odps.udf.impl.batch.BaseWritableSerde.put(BaseWritableSerde.java:20)
 at com.aliyun.odps.udf.impl.batch.BatchUDTFCollector.collect(BatchUDTFCollector.java:54)
 at com.aliyun.odps.udf.UDTF.forward(UDTF.java:164)
 at com.aliyun.odps.mapred.bridge.LotTaskUDTF.collect(LotTaskUDTF.java:62)
 at com.aliyun.odps.mapred.bridge.LotReducerUDTF$ReduceContextImpl.write(LotReducerUDTF.java:167)
 at com.aliyun.odps.mapred.bridge.LotReducerUDTF$ReduceContextImpl.write(LotReducerUDTF.java:162)
 at com.aliyun.odps.mapred.bridge.LotReducerUDTF$ReduceContextImpl.write(LotReducerUDTF.java:151)
 at com.alibaba.algo.Paiswing$swingI2IReducer.reduce(Paiswing.java:346)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:497)
 at com.aliyun.odps.mapred.bridge.utils.MapReduceUtils.runReducer(MapReduceUtils.java:160)
 at com.aliyun.odps.mapred.bridge.LotReducerUDTF.run(LotReducerUDTF.java:330)
 at com.aliyun.odps.udf.impl.batch.BatchStandaloneUDTFEvaluator.run(BatchStandaloneUDTFEvaluator.java:53)

輸出表的item_id一定要是bigint類型,不能是string類型。注意create table語句的schema資訊。