日志不是垃圾,是金矿:聊聊基于日志的大规模用户行为建模如何撑起推荐系统

举报
Echo_Wish 发表于 2026/03/04 20:59:49 2026/03/04
【摘要】 日志不是垃圾,是金矿:聊聊基于日志的大规模用户行为建模如何撑起推荐系统

日志不是垃圾,是金矿:聊聊基于日志的大规模用户行为建模如何撑起推荐系统

大家好,我是 Echo_Wish

很多做推荐系统的同学,一上来就聊模型:DeepFM、DIN、Transformer……仿佛模型越“深”,推荐就越准。

但我这些年做大数据和推荐落地,反而越来越笃定一件事:

推荐系统真正的“灵魂”,不在模型,而在日志。

没有高质量行为日志,再牛的模型都是空中楼阁。今天我们就聊聊——基于日志的大规模用户行为建模在推荐中的应用,以及它背后那些容易被忽视的关键问题。


一、日志是什么?不是埋点,是用户的“时间线”

在推荐系统里,日志通常包括:

  • 曝光日志(exposure)
  • 点击日志(click)
  • 加购日志(cart)
  • 收藏日志(favorite)
  • 下单日志(purchase)
  • 停留时长(dwell time)

本质上,这些是用户和系统交互的时间序列。

举个简单例子:

user_id | item_id | action   | timestamp
----------------------------------------
1001    | A       | exposure | 10:01
1001    | A       | click    | 10:02
1001    | B       | exposure | 10:03
1001    | B       | exposure | 10:04
1001    | C       | click    | 10:05

这不是冷冰冰的数据,这是用户真实的“注意力轨迹”。

而推荐系统要做的,就是在这个轨迹里,预测“下一步”。


二、行为建模第一步:把“日志”变成“特征”

1️⃣ 基础行为统计特征

比如我们想构造一个用户对某类商品的偏好程度:

from pyspark.sql import functions as F

# 假设 logs 是用户行为日志表
user_item_stat = logs.groupBy("user_id", "item_category") \
    .agg(
        F.sum(F.when(F.col("action") == "click", 1).otherwise(0)).alias("click_cnt"),
        F.sum(F.when(F.col("action") == "purchase", 1).otherwise(0)).alias("buy_cnt")
    )

# 加一个简单的偏好分
user_item_stat = user_item_stat.withColumn(
    "preference_score",
    F.col("click_cnt") * 0.3 + F.col("buy_cnt") * 0.7
)

这类统计特征是推荐系统的基石。

但问题来了:

静态统计 ≠ 行为趋势


2️⃣ 引入时间衰减:行为有“保质期”

用户三个月前点过篮球鞋,不代表现在还想买。

我们可以引入时间衰减:

from pyspark.sql.functions import unix_timestamp, current_timestamp, exp

logs = logs.withColumn(
    "time_diff",
    unix_timestamp(current_timestamp()) - unix_timestamp("timestamp")
)

# 半衰期为7天
half_life = 7 * 24 * 3600

logs = logs.withColumn(
    "decay_weight",
    exp(-F.col("time_diff") / half_life)
)

weighted_score = logs.groupBy("user_id", "item_category") \
    .agg(
        F.sum(
            F.when(F.col("action") == "click", 1)
            .otherwise(0) * F.col("decay_weight")
        ).alias("decayed_click_score")
    )

这一步,是很多推荐系统从“能用”到“好用”的关键。


三、从“统计特征”到“序列建模”

当用户行为规模上亿条,光靠统计特征就不够了。

这时候就需要:

  • 序列特征
  • session 切分
  • 行为 embedding
  • Transformer / RNN 等建模

我们来看一个简化的用户行为序列构造方式:

# 按时间排序,构造行为序列
from pyspark.sql.window import Window

w = Window.partitionBy("user_id").orderBy("timestamp")

sequence_df = logs.withColumn(
    "rank", F.row_number().over(w)
).groupBy("user_id").agg(
    F.collect_list("item_id").alias("item_seq")
)

输出可能是:

user_id | item_seq
1001    | [A, B, C, D, E]

接下来我们就可以喂给深度模型:

# 伪代码
user_embedding = Transformer(item_seq)
score = dot(user_embedding, item_embedding)

这里的核心思想是:

用户不是“标签集合”,而是“行为序列”。

这是推荐系统思维方式的升级。


四、大规模日志的工程挑战

很多人只看到模型,却忽视数据工程。

但真实世界里,你会遇到:

1️⃣ 日志延迟与乱序

实时日志可能晚到几分钟甚至几小时。

解决方案:

  • 使用 watermark
  • 做窗口容错
  • 延迟特征生成

2️⃣ 日志噪音

用户误点、爬虫流量、刷点击行为。

如果不做清洗,模型会学到垃圾模式。

比如:

# 过滤异常高频点击
abnormal_users = logs.groupBy("user_id") \
    .count() \
    .filter("count > 10000")

logs = logs.join(abnormal_users, "user_id", "left_anti")

日志清洗,往往比模型调参更重要。


五、我的一点真实感受

我见过太多团队:

  • 模型调到天花乱坠
  • embedding 维度拉到 512
  • GPU 集群轰鸣

结果上线效果不涨。

最后发现:

  • 曝光日志丢了
  • 点击埋点漏 30%
  • 时间戳错时区

推荐系统的本质不是“算法秀肌肉”,而是:

谁能更真实地还原用户行为。

大规模日志建模的核心,不是堆算力,而是三件事:

  1. 行为定义清晰
  2. 特征构造合理
  3. 数据链路稳定

模型只是放大器。


六、推荐系统的终极问题

当我们基于日志建模时,有个值得思考的问题:

我们是在“预测兴趣”,还是在“放大行为”?

如果用户偶然点了一次某类内容,我们持续推荐——
那是个性化,还是信息茧房?

日志是历史,但推荐决定未来。

作为工程师,我们不能只关心 AUC。

我们要问:

  • 是否引导用户探索?
  • 是否给新内容机会?
  • 是否平衡多样性?

这也是我越来越关注“探索机制”和“多样性建模”的原因。


七、总结

基于日志的大规模用户行为建模,本质上是一件三层结构的事:

第一层:数据层 —— 日志清洗、去重、时间对齐
第二层:特征层 —— 统计特征 + 时间衰减 + 序列构造
第三层:模型层 —— 深度建模、embedding、注意力机制

但真正决定推荐质量的,不是最底层,而是最顶层对“用户行为”的理解。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。