• 基于协同过滤的电商推荐系统(2):用户对商品的偏好得分


    目录

    0. 相关文章链接

    1. 为什么要计算用户对商品的偏好得分

    2. 什么是用户对商品的偏好得分

    2.1. 用户对商品的偏好得分概述

    2.2. 行为类型权重

    2.3. 行为次数

    2.4. 时间衰减系数

    3. 用户对商品的偏好得分的具体计算

    3.1. 用户针对商品的点击偏好得分计算

    3.2. 用户针对商品的收藏偏好得分计算

    3.3. 用户针对商品的加购偏好得分计算

    3.4. 用户针对商品的购买偏好得分计算

    3.5. 用户对商品偏好得分聚合和归一化


    0. 相关文章链接

    推荐系统文章汇总

    1. 为什么要计算用户对商品的偏好得分

            使用协同过滤算法,需要统计用户(User)对物品(Item)的评分(Score),然后依托这些数据进行协同过滤的计算(关于什么是协同过滤算法,可以查看博主另一篇博文:推荐算法之基于协同过滤推荐算法)。如果是在视频推荐中,可以根据用户对视频的评分(比如豆瓣)来进行计算。但是在电商中,没有用户对 商品/品类/风格 等的评分,那就只能通过其他相关数据(比如用户对商品的点击、加购、收藏、购买等)来统计每个用户对相关商品的评分,然后根据该商品归属于哪个 品类/风格 下面,来将对应数据映射到相关主题上。这样就能通过协同过滤来计算这些没有显示评分的业务。

            如豆瓣中那些有具体的评分数据的业务,是显示的评分;如电商中对商品没有具体的评分数据的业务,是隐式的评分(当然,电商中也可以使用用户对该商品的售后评价来统计)。

    2. 什么是用户对商品的偏好得分

    2.1. 用户对商品的偏好得分概述

    用户偏好得分 = 行为类型权重 * 行为次数 * 时间衰减系数

    2.2. 行为类型权重

    行为权重是指用户浏览、搜索、收藏、加购、下单等不同的行为,反映了物品对用户重要程度的差异;代价越高的行为权重值越高,一般情况下为:下单 > 加购 > 收藏 > 点击

    博主所使用的行为类型对应的权重值如下所示:

    点击商品:1分
    收藏商品:2.17分
    加购商品:5.19分
    购买商品:15.65分

    2.3. 行为次数

    行为次数是指用户行为次数,提现了用户对该物品的重要性。

    比如:

    点击次数
    收藏次数
    加购次数
    购买件数

    2.4. 时间衰减系数

            用户的行为会随着时间的过去,历史行为和当前的相关性不断减弱;越接近当前的行为,对当下的影响越强,衰减系数越高;时间衰减系数的取值范围为 (0,1]。

            博主这里使用的是以半衰期公式计算出来的时间衰减系数(其中包括 以半衰期为7天的时间衰减系数来统计30天的数据,  以半衰期为15天的时间衰减系数来统计60天的数据, 以半衰期为30天的时间衰减系数来统计120天的数据),具体公式为: 时间衰减系数 = EXP(n/7*LN(0.5)) 。

    如下统计了以半衰期为7天的时间衰减系数来统计30天的数据:

    1   0.905723664
    2   0.820335356
    3   0.742997145
    4   0.672950096
    5   0.609506827
    6   0.552044757
    7   0.5
    8   0.452861832
    9   0.410167678
    10  0.371498572
    11  0.336475048
    12  0.304753414
    13  0.276022378
    14  0.25
    15  0.226430916
    16  0.205083839
    17  0.185749286
    18  0.168237524
    19  0.152376707
    20  0.138011189
    21  0.125
    22  0.113215458
    23  0.10254192
    24  0.092874643
    25  0.084118762
    26  0.076188353
    27  0.069005595
    28  0.0625
    29  0.056607729
    30  0.05127096

    3. 用户对商品的偏好得分的具体计算

    注意:在具体计算中会用到特有的业务名词,具体的名词解释可以参考博主的另一篇博文:基于协同过滤的电商推荐系统(1):名次解释

    注意:在此博文中,博主使用的是用户对商品的30天偏好得分来统计,使用的时间衰减系数为 以半衰期为7天的时间衰减系数来统计30天的数据

    3.1. 用户针对商品的点击偏好得分计算

    需求:统计每个用户对每一款商品(goods_no)在这30天中的点击偏好得分

    具体口径:以用户id(user_id)和商品款号(goods_no)为主键,对偏好得分进行聚合(每一次的点击都会有一个得分)

    建表语句:

    1. drop table if EXISTS xxx_recommendation_system.user_goods_click_score_30day;
    2. CREATE EXTERNAL table if not EXISTS xxx_recommendation_system.user_goods_click_score_30day(
    3. user_id BIGINT COMMENT '用户id'
    4. , goods_no BIGINT COMMENT '商品款号'
    5. , goods_click_score_30day DOUBLE COMMENT '30天商品点击评分'
    6. ) COMMENT '用户商品点击评分表(30天)'
    7. STORED AS orc LOCATION 'obs://xxx-bigdata/xxx_recommendation_system.db/user_goods_click_score_30day'
    8. ;

    计算脚本:

    1. insert overwrite table xxx_recommendation_system.user_goods_click_score_30day
    2. select
    3. main_table.user_id
    4. , goods_table.goods_no
    5. , sum(main_table.goods_click_score_30day) as goods_click_score_30day
    6. from (
    7. SELECT
    8. user_id
    9. , goods_id
    10. , 1 * EXP(datediff1(to_date1(${bdp.system.bizdate},'yyyymmdd'),to_date1(dt,'yyyymmdd'),'dd') / 7 * LN(0.5)) AS goods_click_score_30day
    11. FROM xxx_data.dwd_log_goods_detail_page_dt
    12. WHERE dt BETWEEN TO_CHAR( DATEADD( to_date1(${bdp.system.bizdate},'yyyymmdd') ,-30 ,'dd') ,'yyyymmdd') and ${bdp.system.bizdate}
    13. ) as main_table
    14. left join xxx_data.dim_goods_id_info as goods_table
    15. on main_table.goods_id = goods_table.goods_id
    16. GROUP BY main_table.user_id, goods_table.goods_no
    17. DISTRIBUTE by floor(rand() * 10)
    18. ;

    其中的 dwd_log_goods_detail_page_dt 表,即为商品详情页面曝光表,每1条记录代表的该用户对该商品的一次点击

    其中的 dim_goods_id_info 表,即为商品上架维度表,每次商品上架都会有对应的goods_id和goods_no,其中goods_id唯一,goods_no不唯一

    3.2. 用户针对商品的收藏偏好得分计算

    需求:统计每个用户对每一款商品(goods_no)在这30天中的收藏偏好得分

    具体口径:以用户id(user_id)和商品款号(goods_no)为主键,对偏好得分进行聚合(每一个收藏都会有一个得分)

    建表语句:

    1. insert overwrite table xxx_recommendation_system.user_goods_collect_score_30day
    2. select
    3. main_table.user_id
    4. , goods_table.goods_no
    5. , sum(main_table.goods_collect_score_30day) as goods_collect_score_30day
    6. from (
    7. SELECT
    8. user_id
    9. , goods_id
    10. , 2.17 * EXP(datediff1(to_date1(${bdp.system.bizdate},'yyyymmdd'),to_date1(dt,'yyyymmdd'),'dd') / 7 * LN(0.5)) AS goods_collect_score_30day
    11. FROM xxx_data.dwd_log_goods_collect_dt
    12. WHERE dt between TO_CHAR( DATEADD( to_date1(${bdp.system.bizdate},'yyyymmdd') ,-30 ,'dd') ,'yyyymmdd') and ${bdp.system.bizdate}
    13. ) as main_table
    14. left join xxx_data.dim_goods_id_info as goods_table
    15. on main_table.goods_id = goods_table.goods_id
    16. GROUP BY main_table.user_id, goods_table.goods_no
    17. DISTRIBUTE by floor(rand() * 10)
    18. ;

    其中的 dwd_log_goods_collect_dt 表,即为商品收藏表,每1条记录代表的该用户对该商品的一次收藏

    其中的 dim_goods_id_info 表,即为商品上架维度表,每次商品上架都会有对应的goods_id和goods_no,其中goods_id唯一,goods_no不唯一

    3.3. 用户针对商品的加购偏好得分计算

    需求:统计每个用户对每一款商品(goods_no)在这30天中的加购偏好得分

    具体口径:以用户id(user_id)和商品款号(goods_no)为主键,对偏好得分进行聚合(每一个收藏都会有一个得分)

    建表语句:

    1. drop table if EXISTS xxx_recommendation_system.user_goods_add_cart_score_30day;
    2. CREATE EXTERNAL table if not EXISTS xxx_recommendation_system.user_goods_add_cart_score_30day(
    3. user_id BIGINT COMMENT '用户id'
    4. , goods_no BIGINT COMMENT '商品货号'
    5. , goods_add_cart_score_30day DOUBLE COMMENT '30天商品加购评分'
    6. ) COMMENT '用户商品加购评分表(30天)'
    7. STORED AS orc LOCATION 'obs://xxx-bigdata/xxx_recommendation_system.db/user_goods_add_cart_score_30day'
    8. ;

    计算脚本:

    1. insert overwrite table xxx_recommendation_system.user_goods_add_cart_score_30day
    2. select
    3. main_table.user_id
    4. , goods_table.goods_no
    5. , sum(main_table.goods_add_cart_score_30day) as goods_add_cart_score_30day
    6. from (
    7. SELECT
    8. user_id
    9. , goods_id
    10. , 5.19 * EXP(datediff1(to_date1(${bdp.system.bizdate},'yyyymmdd'),to_date1(dt,'yyyymmdd'),'dd') / 7 * LN(0.5)) AS goods_add_cart_score_30day
    11. FROM xxx_data.dwd_log_add_cart_dt
    12. WHERE dt between TO_CHAR( DATEADD( to_date1(${bdp.system.bizdate},'yyyymmdd') ,-30 ,'dd') ,'yyyymmdd') and ${bdp.system.bizdate}
    13. ) as main_table
    14. left join xxx_data.dim_goods_id_info as goods_table
    15. on main_table.goods_id = goods_table.goods_id
    16. GROUP BY main_table.user_id, goods_table.goods_no
    17. DISTRIBUTE by floor(rand() * 10)
    18. ;

    其中的 dwd_log_add_cart_dt 表,即为商品加购表,每1条记录代表的该用户对该商品的一次加购

    其中的 dim_goods_id_info 表,即为商品上架维度表,每次商品上架都会有对应的goods_id和goods_no,其中goods_id唯一,goods_no不唯一

    3.4. 用户针对商品的购买偏好得分计算

    需求:统计每个用户对每一款商品(goods_no)在这30天中的购买偏好得分

    具体口径:以用户id(user_id)和商品款号(goods_no)为主键,对偏好得分进行聚合(每一个收藏都会有一个得分)

    建表语句:

    1. drop table if EXISTS xxx_recommendation_system.user_goods_buy_score_30day;
    2. CREATE EXTERNAL table if not EXISTS xxx_recommendation_system.user_goods_buy_score_30day(
    3. user_id BIGINT COMMENT '用户id'
    4. , goods_no BIGINT COMMENT '商品款号'
    5. , goods_buy_score_30day DOUBLE COMMENT '30天购买评分'
    6. ) COMMENT '用户商品购买偏好得分表(30天)'
    7. STORED AS orc LOCATION 'obs://xxx-bigdata/xxx_recommendation_system.db/user_goods_buy_score_30day'
    8. ;

    计算脚本:

    1. insert overwrite table xxx_recommendation_system.user_goods_buy_score_30day
    2. select
    3. main_table.user_id
    4. , goods_table.goods_no
    5. , sum(main_table.goods_buy_score_30day) as goods_buy_score_30day
    6. from (
    7. SELECT
    8. user_id
    9. , goods_id
    10. , 15.65 * EXP(datediff1(to_date1(${bdp.system.bizdate},'yyyymmdd'),to_date1(dt,'yyyymmdd'),'dd') / 7 * LN(0.5)) AS goods_buy_score_30day
    11. FROM xxx_data.dwd_ys_sale_sp_order_info_final_dt
    12. WHERE dt between TO_CHAR( DATEADD( to_date1(${bdp.system.bizdate},'yyyymmdd') ,-30 ,'dd') ,'yyyymmdd') and ${bdp.system.bizdate}
    13. AND pay_status = 1
    14. AND is_real_pay = 1
    15. ) as main_table
    16. left join xxx_data.dim_goods_id_info as goods_table
    17. on main_table.goods_id = goods_table.goods_id
    18. GROUP BY main_table.user_id, goods_table.goods_no
    19. DISTRIBUTE by floor(rand() * 10)
    20. ;

    其中的 dwd_ys_sale_sp_order_info_final_dt 表,即为商品购买表(通过订单、订单详情、订单取消表聚合而来),每1条记录代表的该用户对该商品的一次购买

    其中的 dim_goods_id_info 表,即为商品上架维度表,每次商品上架都会有对应的goods_id和goods_no,其中goods_id唯一,goods_no不唯一

    3.5. 用户对商品偏好得分聚合和归一化

    需求:将用户对商品的点击偏好得分、收藏偏好得分、加购偏好得分、购买偏好得分进行聚合,并且由于不同商品之间可能差距过大,所以还需要进行归一化

    具体口径:针对不同用户、不同商品,之间聚合即可,并使用 ln() 函数进行归一化

    归一化:LN(该用户对该商品的评分 + 2)/LN(MAX(该用户对所有商品的最大评分 + 2))] ,因为其中的值存在0到1的,所以需要加2

    建表语句:

    1. drop table if EXISTS xxx_recommendation_system.user_goods_score_30day;
    2. CREATE EXTERNAL table if not EXISTS xxx_recommendation_system.user_goods_score_30day(
    3. user_id BIGINT COMMENT '用户id'
    4. , goods_no BIGINT COMMENT '商品款号'
    5. , score double comment '用户针对商品的偏好得分'
    6. , user_max_score double comment '该用户最大的对商品的得分'
    7. , score_normalization double comment '用户针对商品的偏好得分归一化后结果'
    8. ) COMMENT '用户商品偏好得分表(30天)'
    9. STORED AS orc LOCATION 'obs://xxx-bigdata/xxx_recommendation_system.db/user_goods_score_30day'
    10. ;

    计算脚本:

    1. INSERT OVERWRITE TABLE xxx_recommendation_system.user_goods_score_30day
    2. select
    3. user_id
    4. , goods_no
    5. , score
    6. , max(score) over(partition by user_id) as user_max_score
    7. , ln(score + 2) / ln(max(score) over(partition by user_id) + 2) as score_normalization
    8. from (
    9. select
    10. main_table.user_id
    11. , main_table.goods_no
    12. , coalesce(click_table.goods_click_score_30day, 0)
    13. + coalesce(collect_table.goods_collect_score_30day, 0)
    14. + coalesce(add_cart_table.goods_add_cart_score_30day, 0)
    15. + coalesce(buy_table.goods_buy_score_30day, 0) as score
    16. from (
    17. SELECT user_id, goods_no FROM xxx_recommendation_system.user_goods_click_score_30day
    18. union
    19. SELECT user_id, goods_no FROM xxx_recommendation_system.user_goods_collect_score_30day
    20. union
    21. SELECT user_id, goods_no FROM xxx_recommendation_system.user_goods_add_cart_score_30day
    22. union
    23. SELECT user_id, goods_no FROM xxx_recommendation_system.user_goods_buy_score_30day
    24. ) as main_table
    25. left join xxx_recommendation_system.user_goods_click_score_30day as click_table
    26. on main_table.user_id = click_table.user_id and main_table.goods_no = click_table.goods_no
    27. left join xxx_recommendation_system.user_goods_collect_score_30day as collect_table
    28. on main_table.user_id = collect_table.user_id and main_table.goods_no = collect_table.goods_no
    29. left join xxx_recommendation_system.user_goods_add_cart_score_30day as add_cart_table
    30. on main_table.user_id = add_cart_table.user_id and main_table.goods_no = add_cart_table.goods_no
    31. left join xxx_recommendation_system.user_goods_buy_score_30day as buy_table
    32. on main_table.user_id = buy_table.user_id and main_table.goods_no = buy_table.goods_no
    33. )
    34. ;

    求出数据,如下图所示,其中 score_normalization 字段表示进行归一化后的评分:


    注:其他推荐系统相关文章链接由此进 -> 推荐系统文章汇总


  • 相关阅读:
    第八章《Java高级语法》第2节:补码
    网站推荐 | 那些小众却精美的网站
    SpringBoot-RabbitMQ
    虹科培训 | 虹科携手PLCopen开展IEC 61131-3国际工程师培训
    【ubuntu】在虚拟机中如何给ubuntu硬盘扩容
    基于数据库实现全局唯一ID
    统计信号处理基础 习题解答6-5
    SpringCloud 组件Gateway服务网关【gateway快速入门】
    LINUX随笔十 SFTP不支持 ssh-dss,ssh-rsa
    线程与并发 ---常用的方法
  • 原文地址:https://blog.csdn.net/yang_shibiao/article/details/124714840