Java 类名:com.alibaba.alink.operator.batch.recommendation.SwingTrainBatchOp
Python 类名:SwingTrainBatchOp

功能介绍

Swing 是一种被广泛使用的item召回算法,输入数据只包含user和item即可,使用简单。
Swing算法原理比较简单,是阿里最早使用到的一种召回算法,在阿里多个业务被验证过非常有效的一种召回方式。 它认为 user-item-user 的结构比 itemCF 的单边结构更稳定。
Swing指的是秋千,例如用户u和用户v,都购买过同一件商品i,则三者之间会构成一个类似秋千的关系图。
若用户u和用户v之间除了购买过i外,还购买过商品j,则认为两件商品是具有某种程度上的相似的。
也就是说,商品与商品之间的相似关系,是通过用户关系来传递的。为了衡量物品i和j的相似性,考察都购买了物品i和j的用户u和用户v,
如果这两个用户共同购买的物品越少,则物品i和j的相似性越高。
Swing算法的表达式如下:
用户权重 w_u = 1 / (user_click_num + userAlpha) ^ userBeta
score(item_i, item_j) = sum(wu * wv / (alpha + common_items(wu, wv)))
其中userAlpha、userBeta和alpha,用户可以根据自己的数据情况设置。
此外,可以通过设置maxUserItems和minUserItems,过滤掉关联item太多或者太少的用户信息。
对于出现次数过多的item,设置maxItemNumber参数,当出现次数大于maxItemNumber时,算法从所有的user中随机抽取maxItemNumber个用户,计算结果,因此该算法两次执行的结果不一定相同。
在电商场景中,user和item的关系可以为点击、购买、收藏等。在Feed流场景关系可以为点击、点赞、评论、收藏等,item可以为文章、博主、话题等。

参数说明

| 名称 | 中文名称 | 描述 | 类型 | 是否必须? | 取值范围 | 默认值 | | —- | —- | —- | —- | —- | —- | —- |

| itemCol | Item列列名 | Item列列名 | String | ✓ | | |

| userCol | User列列名 | User列列名 | String | ✓ | | |

| alpha | alpha参数 | alpha参数,默认1.0 | Float | | | 1.0 |

| maxItemNumber | item参与计算的人数最大值 | 如果item出现次数大于该次数,会随机选择该次数的用户数据,默认1000 | Integer | | | 1000 |

| maxUserItems | 用户互动的最大Item数量 | 如果用户互动Item数量大于该次数,该用户数据不参与计算过程,默认1000 | Integer | | | 1000 |

| minUserItems | 用户互动的最小Item数量 | 如果用户互动Item数量小于该次数,该用户数据不参与计算过程,默认10 | Integer | | | 10 |

| resultNormalize | 结果是否归一化 | 是否归一化,默认False | Boolean | | | false |

| userAlpha | 用户alpha参数 | 用户alpha参数,默认5.0, user weight = 1.0/(userAlpha + userClickCount)^userBeta | Float | | | 5.0 |

| userBeta | 用户beta参数 | 用户beta参数,默认-0.35, user weight = 1.0/(userAlpha + userClickCount)^userBeta | Float | | | -0.35 |

代码示例

Python 代码

  1. from pyalink.alink import *
  2. import pandas as pd
  3. useLocalEnv(1)
  4. df_data = pd.DataFrame([
  5. ["a1", "11L", 2.2],
  6. ["a1", "12L", 2.0],
  7. ["a2", "11L", 2.0],
  8. ["a2", "12L", 2.0],
  9. ["a3", "12L", 2.0],
  10. ["a3", "13L", 2.0],
  11. ["a4", "13L", 2.0],
  12. ["a4", "14L", 2.0],
  13. ["a5", "14L", 2.0],
  14. ["a5", "15L", 2.0],
  15. ["a6", "15L", 2.0],
  16. ["a6", "16L", 2.0],
  17. ])
  18. data = BatchOperator.fromDataframe(df_data, schemaStr='user string, item string, rating double')
  19. model = SwingTrainBatchOp()\
  20. .setUserCol("user")\
  21. .setItemCol("item")\
  22. .setMinUserItems(1)\
  23. .linkFrom(data)
  24. model.print()
  25. predictor = SwingRecommBatchOp()\
  26. .setItemCol("item")\
  27. .setRecommCol("prediction_result")
  28. predictor.linkFrom(model, data).print()

Java 代码

  1. import org.apache.flink.types.Row;
  2. import com.alibaba.alink.operator.batch.BatchOperator;
  3. import com.alibaba.alink.operator.batch.recommendation.SwingRecommBatchOp;
  4. import com.alibaba.alink.operator.batch.recommendation.SwingTrainBatchOp;
  5. import com.alibaba.alink.operator.batch.source.MemSourceBatchOp;
  6. import org.junit.Test;
  7. import java.util.Arrays;
  8. import java.util.List;
  9. public class SwingTrainBatchOpTest {
  10. @Test
  11. public void testSwingTrainBatchOp() throws Exception {
  12. List <Row> df_data = Arrays.asList(
  13. Row.of("a1", "11L", 2.2),
  14. Row.of("a1", "12L", 2.0),
  15. Row.of("a2", "11L", 2.0),
  16. Row.of("a2", "12L", 2.0),
  17. Row.of("a3", "12L", 2.0),
  18. Row.of("a3", "13L", 2.0),
  19. Row.of("a4", "13L", 2.0),
  20. Row.of("a4", "14L", 2.0),
  21. Row.of("a5", "14L", 2.0),
  22. Row.of("a5", "15L", 2.0),
  23. Row.of("a6", "15L", 2.0),
  24. Row.of("a6", "16L", 2.0)
  25. );
  26. BatchOperator <?> data = new MemSourceBatchOp(df_data, "user string, item string, rating double");
  27. BatchOperator <?> model = new SwingTrainBatchOp()
  28. .setUserCol("user")
  29. .setItemCol("item")
  30. .setMinUserItems(1)
  31. .linkFrom(data);
  32. model.print();
  33. BatchOperator <?> predictor = new SwingRecommBatchOp()
  34. .setItemCol("item")
  35. .setRecommCol("prediction_result");
  36. predictor.linkFrom(model, data).print();
  37. }
  38. }

运行结果

| mainItems | recommItemAndSimilarity | | —- | —- |

| 11L | {“object”:[“12L”],”score”:[1.3015095],”itemCol”:”item”} |

| 14L | {“object”:[],”score”:[],”itemCol”:”item”} |

| 16L | {“object”:[],”score”:[],”itemCol”:”item”} |

| 15L | {“object”:[],”score”:[],”itemCol”:”item”} |

| 13L | {“object”:[],”score”:[],”itemCol”:”item”} |

| 12L | {“object”:[“11L”],”score”:[1.3015095],”itemCol”:”item”} |

| user | item | rating | prediction_result | | —- | —- | —- | —- |

| a1 | 11L | 2.2000 | {“item”:”[“12L”]”,”score”:”[1.3015094995498657]”} |

| a1 | 12L | 2.0000 | {“item”:”[“11L”]”,”score”:”[1.3015094995498657]”} |

| a2 | 11L | 2.0000 | {“item”:”[“12L”]”,”score”:”[1.3015094995498657]”} |

| a2 | 12L | 2.0000 | {“item”:”[“11L”]”,”score”:”[1.3015094995498657]”} |

| a3 | 12L | 2.0000 | {“item”:”[“11L”]”,”score”:”[1.3015094995498657]”} |

| a3 | 13L | 2.0000 | {“item”:”[]”,”score”:”[]”} |

| a4 | 13L | 2.0000 | {“item”:”[]”,”score”:”[]”} |

| a4 | 14L | 2.0000 | {“item”:”[]”,”score”:”[]”} |

| a5 | 14L | 2.0000 | {“item”:”[]”,”score”:”[]”} |

| a5 | 15L | 2.0000 | {“item”:”[]”,”score”:”[]”} |

| a6 | 15L | 2.0000 | {“item”:”[]”,”score”:”[]”} |

| a6 | 16L | 2.0000 | {“item”:”[]”,”score”:”[]”} |