码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 一文看懂推荐系统:排序10:wide&deep模型,wide就是LR负责记忆,deep负责高阶特征交叉而泛化


    一文看懂推荐系统:排序10:wide&deep模型,wide就是LR负责记忆,deep负责高阶特征交叉而泛化

    提示:最近系统性地学习推荐系统的课程。我们以小红书的场景为例,讲工业界的推荐系统。
    我只讲工业界实际有用的技术。说实话,工业界的技术远远领先学术界,在公开渠道看到的书、论文跟工业界的实践有很大的gap,
    看书学不到推荐系统的关键技术。
    看书学不到推荐系统的关键技术。
    看书学不到推荐系统的关键技术。

    王树森娓娓道来**《小红书的推荐系统》**
    GitHub资料连接:http://wangshusen.github.io/
    B站视频合集:https://space.bilibili.com/1369507485/channel/seriesdetail?sid=2249610

    基础知识:
    【1】一文看懂推荐系统:概要01:推荐系统的基本概念
    【2】一文看懂推荐系统:概要02:推荐系统的链路,从召回粗排,到精排,到重排,最终推荐展示给用户
    【3】一文看懂推荐系统:召回01:基于物品的协同过滤(ItemCF),item-based Collaboration Filter的核心思想与推荐过程
    【4】一文看懂推荐系统:召回02:Swing 模型,和itemCF很相似,区别在于计算相似度的方法不一样
    【5】一文看懂推荐系统:召回03:基于用户的协同过滤(UserCF),要计算用户之间的相似度
    【6】一文看懂推荐系统:召回04:离散特征处理,one-hot编码和embedding特征嵌入
    【7】一文看懂推荐系统:召回05:矩阵补充、最近邻查找,工业界基本不用了,但是有助于理解双塔模型
    【8】一文看懂推荐系统:召回06:双塔模型——模型结构、训练方法,召回模型是后期融合特征,排序模型是前期融合特征
    【9】一文看懂推荐系统:召回07:双塔模型——正负样本的选择,召回的目的是区分感兴趣和不感兴趣的,精排是区分感兴趣和非常感兴趣的
    【10】一文看懂推荐系统:召回08:双塔模型——线上服务需要离线存物品向量、模型更新分为全量更新和增量更新
    【11】一文看懂推荐系统:召回09:地理位置召回、作者召回、缓存召回
    【12】一文看懂推荐系统:排序01:多目标模型
    【13】一文看懂推荐系统:排序02:Multi-gate Mixture-of-Experts (MMoE)
    【14】一文看懂推荐系统:排序03:预估分数融合
    【15】一文看懂推荐系统:排序04:视频播放建模
    【16】一文看懂推荐系统:排序05:排序模型的特征
    【17】一文看懂推荐系统:排序06:粗排三塔模型,性能介于双塔模型和精排模型之间
    【18】一文看懂推荐系统:特征交叉01:Factorized Machine (FM) 因式分解机
    【19】一文看懂推荐系统:物品冷启01:优化目标 & 评价指标
    【20】一文看懂推荐系统:物品冷启02:简单的召回通道
    【21】一文看懂推荐系统:物品冷启03:聚类召回
    【22】一文看懂推荐系统:物品冷启04:Look-Alike 召回,Look-Alike人群扩散
    【23】一文看懂推荐系统:物品冷启05:流量调控
    【24】一文看懂推荐系统:物品冷启06:冷启的AB测试
    【25】推荐系统最经典的 排序模型 有哪些?你了解多少?
    【26】一文看懂推荐系统:排序07:GBDT+LR模型
    【27】一文看懂推荐系统:排序08:Factorization Machines(FM)因子分解机,一个特殊的案例就是MF,矩阵分解为uv的乘积
    【28】一文看懂推荐系统:排序09:Field-aware Factorization Machines(FFM),从FM改进来的,效果不咋地


    提示:文章目录

    文章目录

    • 一文看懂推荐系统:排序10:wide&deep模型,wide就是LR负责记忆,deep负责高阶特征交叉而泛化
    • wide&deep模型
    • 一、提出wide&deep的动机
    • 二、wide&deep模型结构
    • 三、一些思考
    • 总结


    wide&deep模型

    这篇博客主要介绍谷歌于2016年发表在RecSys上的一篇文章,

    俗话说:谷歌家出品,必属精品。

    这篇文章提出的模型wide&deep着实对推荐系统领域有着非常大的影响,
    启发了后面几年推荐系统领域的一些工作,比如:deep&cross,deepFM等。 【后边我都会一一说的】

    这篇文章也是秉承着Google家文章一贯的风格【大道至简,非常关注工程实践】,
    不像国内某互联网公司某团队的paper简直是概念的堆砌,
    如果没有概念就造概念,让人看的眼花缭乱,明显是冲着发论文去的。

    恶心人!

    这篇博客主要以下几个点来介绍下wide&deep模型。

    《Wide & Deep Learning for Recommender Systems》
    在这里插入图片描述

    一、提出wide&deep的动机

    在这篇论文之前,工业界推荐系统主流的模型基本是LR或者普通的DNN(当然也有像FM和树模型及其变种),
    通常而言,线性模型比如LR比较擅长记忆,而DNN则比较擅长泛化。

    这里来解释下何为记忆,何为泛化???

    记忆: 其实就是模型直接学到样本中一些强特征,
    比如,尿布&瓶酒的例子,

    如果样本中频繁出现了买了尿布的人同时买了啤酒,
    也就是说尿布&啤酒共现的频率很高,
    那么模型可以直接记住这种共现,

    当做推荐的时候,如果一个人买了尿布,那么应该给他推荐啤酒。

    泛化: 泛化则是学习特征的传递能力,
    比如某个训练集为树叶,label为判断输入的东西是否是一个树叶,
    样本中的树叶基本都是绿色的锯齿状树叶,
    那么我们希望模型能够有泛化能力,
    当输入一个泛黄的圆形树叶,模型也能判断出这是个树叶。

    因此,为了结合这两种能力,提出了wide&deep模型,
    wide侧为一个LR模型,负责记忆,
    deep部分为一个多层全连接网络,负责泛化。

    二、wide&deep模型结构

    在这里插入图片描述
    从上图能够非常清晰的看到wide&deep模型包含两个部分,
    wide部分和deep部分。

    wide部分为一个线性模型LR,
    在这里插入图片描述

    deep部分为一个三层隐藏层[1024,512,256]的DNN。
    在这里插入图片描述

    模型网络结构虽然简直直白,但有几个细节需要关注下:

    训练方式:
    wide部分和deep部分使用logistics loss连接在一起,通过bp联合训练,而不是单独训练然后做ensemble。

    优化算法:
    wide部分采用Google家出产的FTRL优化算法
    deep部分采用AdaGrad(关于AdaGrad参见本人的博客:深度学习中优化方法
    ——momentum、Nesterov Momentum、AdaGrad、Adadelta、RMSprop、Adam)
    那么随之而来的2个问题:
    (a)两个不同的优化算法放在一起怎么优化?
    (b)为什么LR部分采用ftrl,而deep部分采用AdaGrad
    这两个问题留到博客最后的【一些思考】里再介绍。

    特征:
    在Google play的场景下主要分为连续值特征和类别特征,
    在这篇论文中,连续值特征被归一化到[0,1]范围内,类别特征则做了embedding,
    然后直接做了concate,输入到deep网络中。

    wide部分主要输入的是一些交叉特征,用于记忆。

    模型训练:
    采用热启的方式训练模型,上一次(天级别或者小时级)的模型embedding向量和权重初始化下一个时间的模型
    (ented a warm-starting system which initializes a new model with the embeddings and the linear model weights from the previous model.)。
    这一点和我厂的abacus保持一致。这样做的好处显而易见,lifetime learning + Fine Tune。

    模型更新校验: 每次更新到线上之前要做一次校验,
    校验待更新的模型是否正常,防止把有问题的模型更新到线上,发生问题。
    这一点透露着浓浓的工业风,也是一个工业系统必备的环节。

    三、一些思考

    问题1: wide部分和deep采用联合训练,
    但wide部分采用FTRL优化算法,deep部分采用AdaGrad优化算法,这个该怎么训练?

    这个问题直接看TensorFlow官方代码:https://github.com/tensorflow/tensorflow/blob/r1.11/tensorflow/python/estimator/canned/dnn_linear_combined.py

    deep侧:

    # deep侧
    with variable_scope.variable_scope(
            dnn_parent_scope,
            values=tuple(six.itervalues(features)),
            partitioner=dnn_partitioner) as scope:
          dnn_absolute_scope = scope.name
          dnn_logit_fn = dnn._dnn_logit_fn_builder(  # pylint: disable=protected-access
              units=head.logits_dimension,
              hidden_units=dnn_hidden_units,
              feature_columns=dnn_feature_columns,
              activation_fn=dnn_activation_fn,
              dropout=dnn_dropout,
              input_layer_partitioner=input_layer_partitioner,
              batch_norm=batch_norm)
          dnn_logits = dnn_logit_fn(features=features, mode=mode)
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    wide侧:

    # wide侧
        with variable_scope.variable_scope(
            linear_parent_scope,
            values=tuple(six.itervalues(features)),
            partitioner=input_layer_partitioner) as scope:
          linear_absolute_scope = scope.name
          logit_fn = linear._linear_logit_fn_builder(  # pylint: disable=protected-access
              units=head.logits_dimension,
              feature_columns=linear_feature_columns,
              sparse_combiner=linear_sparse_combiner)
          linear_logits = logit_fn(features=features)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    loss直接把wide部分的loss和deep部分的loss相加

    # loss函数
     if n_classes == 2:
          head = head_lib._binary_logistic_head_with_sigmoid_cross_entropy_loss(  # pylint: disable=protected-access
              weight_column=weight_column,
              label_vocabulary=label_vocabulary,
              loss_reduction=loss_reduction)
        else:
          head = head_lib._multi_class_head_with_softmax_cross_entropy_loss(  # pylint: disable=protected-access
              n_classes,
              weight_column=weight_column,
              label_vocabulary=label_vocabulary,
              loss_reduction=loss_reduction)
              
      # Combine logits and build full model.
      if dnn_logits is not None and linear_logits is not None:
        logits = dnn_logits + linear_logits
      elif dnn_logits is not None:
        logits = dnn_logits
      else:
        logits = linear_logits
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    BP时,采用不用的优化器优化wide侧和deep侧,
    这里核心语句在于:
    train_op = control_flow_ops.group(train_ops),
    从而做到了可以用不同的优化器来优化两侧。

      def _train_op_fn(loss):
        """Returns the op to optimize the loss."""
        train_ops = []
        global_step = training_util.get_global_step()
        if dnn_logits is not None:
          train_ops.append(
              dnn_optimizer.minimize(
                  loss,
                  var_list=ops.get_collection(
                      ops.GraphKeys.TRAINABLE_VARIABLES,
                      scope=dnn_absolute_scope)))
        if linear_logits is not None:
          train_ops.append(
              linear_optimizer.minimize(
                  loss,
                  var_list=ops.get_collection(
                      ops.GraphKeys.TRAINABLE_VARIABLES,
                      scope=linear_absolute_scope)))
    	# 核心语句,采用group函数
        train_op = control_flow_ops.group(*train_ops)
        with ops.control_dependencies([train_op]):
          return state_ops.assign_add(global_step, 1).op
    
      return head.create_estimator_spec(
          features=features,
          mode=mode,
          labels=labels,
          train_op_fn=_train_op_fn,
          logits=logits)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    问题2: 为什么wide侧采用FTRL,而deep侧采用AdaGrad?

    我个人觉得在wide侧采用FTRL,一方面是为了产生稀疏解,
    毕竟在论文中能够看到wide部分的交叉特征是两个id特征的交叉,
    这样可以大大缩小模型体积,利于线上部署。

    另外一方面,由于联合训练,必然会出现wide部分收敛速度远远快于deep部分,

    应该是谷歌大佬们为了缓解这种情况,因为ftrl和adagrad都是随着梯度的累计,
    学习率会变小,并且ftrl结合了L1正则和L2正则,使得ftrl收敛速度慢。

    注:这一点只是个人理解,如果有大佬有更好的理解,欢迎留言交流。


    总结

    提示:如何系统地学习推荐系统,本系列文章可以帮到你

    (1)找工作投简历的话,你要将招聘单位的岗位需求和你的研究方向和工作内容对应起来,这样才能契合公司招聘需求,否则它直接把简历给你挂了
    (2)你到底是要进公司做推荐系统方向?还是纯cv方向?还是NLP方向?还是语音方向?还是深度学习机器学习技术中台?还是硬件?还是前端开发?后端开发?测试开发?产品?人力?行政?这些你不可能啥都会,你需要找准一个方向,自己有积累,才能去投递,否则面试官跟你聊什么呢?
    (3)今日推荐系统学习经验:为了结合这两种能力,提出了wide&deep模型,wide侧为一个LR模型,负责记忆,deep部分为一个多层全连接网络,负责泛化。

  • 相关阅读:
    C++,基础函数、string、引用型变量reference
    Maven Surefire Exclude 无效问题排查日志
    计算机网络 —— 数据链路层(无线局域网)
    如何使用HTTP代理爬虫,防止对网站造成负面影响
    深入了解Java 8 新特性:Stream流的实践应用(一)
    2024毕业设计题目推荐
    Linux·设备
    Js中clientX/Y、offsetX/Y和screenX/Y之间区别
    C++ 20 协程(三)
    AVR汇编(六):分支指令
  • 原文地址:https://blog.csdn.net/weixin_46838716/article/details/126554295
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号