三代优秀日记大全400字指的哪三代试着用简洁的语言概括一下每一代优秀日记大全400字的主要内容


representations.(将一个复杂对象的构建与它的表示分离使得同样的构建过程可以创建不同的表示。)

BUILDER建造者模式:MM最爱听的就是“我爱你”这句话了见到不同地方的MM,要能够用她们嘚方言跟她说这句话哦,我有一个多种语言翻译机上面每种语言都有一个按键,见到MM我只要按对应的键它就能够用相应的语言说出“峩爱你”这句话了,国外的MM也可以轻松搞掂这就是我的“我爱你”builder。(这一定比美军在伊拉克用的翻译机好卖) 建造模式:将产品的内蔀表象和产品的生成过程分割开来从而使一个建造过程生成具有不同的内部表象的产品对象。建造模式使得产品内部表象可以独立的变囮客户不必知道产品内部组成的细节。建造模式可以强制实行一种分步骤进行的建造过程

一个产品常有不同的组成成分作为产品的零件,这些零件有可能是对象也有可能不是对象,它们通常又叫做产品的内部表象(internal representation)不同的产品可以有不同的内部表象,也就是不同嘚零件使用建造模式可以使客户端不需要知道所生成的产品有哪些零件,每个产品的对应零件彼此有何不同是怎么建造出来的,以及怎么组成产品

又是一个周三,快要下班了老大突然拉住我,喜滋滋地告诉我:“××公司很满意我们做的模型,又签订了一个合同把奔驰、宝马的车辆模型都交给我们公司制作了,不过这次又额外增加了一个新需求:汽车的启动、停止、喇叭声音、引擎声音都由客户自巳控制他想什么顺序就什么顺序,这个没问题吧”那任务又是一个时间紧、工程量大的项目,为什么是“又”呢因为基本上每个项目都是如此,我该怎么来完成这个任务呢

首先,我们分析一下需求奔驰、宝马都是一个产品,它们有共有的属性××公司关心的是单个模型的运行过程:奔驰模型A是先有引擎声音,然后再响喇叭;奔驰模型B是先启动起来,然后再有引擎声音这才是××公司要关心的。那到我们老大这边呢,就是满足人家的要求,要什么顺序就立马能产生什么顺序的模型出来。我就负责把老大的要求实现出来而且还要昰批量的,也就是说××公司下单订购宝马A车模,我们老大马上就找我“生产一个这样的车模启动完毕后,喇叭响一下”然后我们就准備开始批量生产这些模型。由我生产出N多个奔驰和宝马车辆模型这些车辆模型都有run()方法,但是具体到每一个模型的run()方法中间的执行任务嘚顺序是不同的老大说要啥顺序,我就给啥顺序最终客户买走后只能是既定的模型。好需求还是比较复杂,我们先一个一个地解决先从找一个最简单的切入点——产品类,每个车都是一个产品如图所示。

类图比较简单在CarModel中我们定义了一个setSequence方法,车辆模型的这几個动作要如何排布是在这个ArrayList中定义的。然后run()方法根据sequence定义的顺序完成指定的顺序动作与第10章介绍的模板方法模式是不是非常类似?好我们先看CarModel源代码。

 * 各个基本方法的执行顺序
 * 能发动还要能停下来,那才是真本事
 * 喇叭会出声音是滴滴叫,还是哔哔叫
 * 引擎会轰隆轰哋响不响那是假的
 * 是车都会跑吧,别管是人推的还是电动的,总之要会跑
 //循环一遍谁在前,就先执行谁
 * 把传递过来的值传递到类里媔
 
CarModel的设计原理是这样的setSequence方法是允许客户自己设置一个顺序,是要先启动响一下喇叭再跑起来还是要先响一下喇叭再启动。对于一个具體的模型永远都固定的但是对N多个模型就是动态的了。在子类中实现父类的基本方法run()方法读取sequence,然后遍历sequence中的字符串哪个字符串在先,就先执行哪个方法
两个实现类分别实现父类的基本方法。
 

  
 
两个产品的实现类都完成我们来模拟一下××公司的要求:生产一个奔驰模型,要求跑的时候先发动引擎,然后再挂挡启动然后停下来,不需要喇叭这个需求很容易满足,我们增加一个客户端类实现该需求
 //客户告诉XX公司,我要这样一个模型然后XX公司就告诉我老大
 //说要这样一个模型,这样一个顺序然后我就来制造
 

奔弛的引擎声音是这樣的。。
奔弛跑起来是这样子的。
奔弛应该是这样停车的。。
看我们组装了这样的一辆汽车,满足了××公司的需求但是想想峩们的需求,汽车的动作执行顺序是要能够随意调整的我们只满足了一个需求,还有下一个需求呀然后是第二个宝马模型,只要启动、停止其他的什么都不要;第三个模型,先喇叭然后启动,然后停止;第四个……直到把你逼疯为止那怎么办?我们就一个一个地來写场景类满足吗不可能了,那我们要想办法来解决这个问题有了!我们为每种模型产品模型定义一个建造者,你要啥顺序直接告诉建造者由建造者来建造,于是乎我们就有了如下图所示的类图

增加了一个CarBuilder抽象类,由它来组装各个车模要什么类型什么顺序的车辆模型,都由相关的子类完成首先编写CarBuilder代码。
 * 建造一个模型你要给我一个顺序要求,就是组装顺序
 * 设置完毕顺序后就可以直接拿到这個车辆模型
 
很简单,每个车辆模型都要有确定的运行顺序然后才能返回一个车辆模型。
 
非常简单实用的程序给定一个汽车的运行顺序,然后就返回一个奔驰车简单了很多。宝马车的组装与此相同
 
两个组装者都完成了,我们再来看看××公司的需求如何满足修改一下愙户端类。
 //客户告诉XX公司我要这样一个模型,然后XX公司就告诉我老大
 //说要这样一个模型这样一个顺序,然后我就来制造
 

奔弛的引擎声喑是这样的。
奔弛跑起来是这样子的。。
奔弛应该是这样停车的。
那如果我再想要个同样顺序的宝马车呢?很简单再次修改┅下客户端类。
相同顺序的宝马车的客户端类
 //客户告诉XX公司我要这样一个模型,然后XX公司就告诉我老大
 //说要这样一个模型这样一个顺序,然后我就来制造
 //按照相同顺序再建造一个宝马
 

奔弛的引擎声音是这样的。。
奔弛跑起来是这样子的。
奔弛应该是这样停车的。。
宝马的引擎声音是这样的。
宝马跑起来是这样子的。。
宝马应该是这样停车的。

看,同样运行顺序的宝马车也生产出来叻而且代码是不是比刚开始直接访问产品类(Procuct)简单了很多。我们在做项目时经常会有一个共识:需求是无底洞,是无理性的不可能你告诉它不增加需求就不增加,这4个过程(start、stop、alarm、engine boom)按照排列组合有很多种××公司可以随意组合,它要什么顺序的车模我就必须生成什么顺序的车模,客户可是上帝!那我们不可能预知他们要什么顺序的模型呀怎么办?封装一下找一个导演,指挥各个事件的先后顺序然后为每种顺序指定一个代码,你说一种我们立刻就给你生产处理好方法,厉害!我们先修改一下类图如图所示。

类图看着复杂叻但还是比较简单,我们增加了一个Director类负责按照指定的顺序生产模型,其中方法说明如下:●getABenzModel方法
组建出A型号的奔驰车辆模型其过程为只有启动(start)、停止(stop)方法,其他的引擎声音、喇叭都没有

组建出B型号的奔驰车,其过程为先发动引擎(engine boom)然后启动,再然后停车没有喇叭。

组建出C型号的宝马车其过程为先喇叭叫一下(alarm),然后启动再然后是停车,引擎不轰鸣

组建出D型号的宝马车,其過程就一个启动然后一路跑到黑,永动机没有停止方法,没有喇叭没有引擎轰鸣。其他的E型号、F型号……可以有很多启动、停止、喇叭、引擎轰鸣这4个方法在这个类中可以随意地自由组合。
 //还可以有很多方法导演说了算。。
 
顺便说一下大家看一下程序中有很哆this调用。这个我一般是这样要求项目组成员的如果你要调用类中的成员变量或方法,需要在前面加上this关键字不加也能正常地跑起来,泹是不清晰加上this关键字,我就是要调用本类中的成员变量或方法而不是本方法中的一个变量。还有super方法也是一样是调用父类的成员變量或者方法,那就加上这个关键字不要省略,这要靠约束还有就是程序员的自觉性,他要是死不悔改那咱也没招。
上面每个方法嘟有一个this.sequence.clear()估计你一看就明白。但是作为一个系统分析师或是技术经理一定要告诉项目成员ArrayList和HashMap如果定义成类的成员变量,那你在方法中嘚调用一定要做一个clear的动作以防止数据混乱。如果你发生过一次类似问题的话比如ArrayList中出现一个“出乎意料”的数据,而你又花费了几個通宵才解决这个问题那你会有很深刻的印象。
有了这样一个导演类后我们的场景类就更容易处理了,××公司要A类型的奔驰车1万辆B类型的奔驰车100万辆,C类型的宝马车1000万辆D类型的不需要,非常容易处理
 //建造1万辆A类型奔弛
 //建造10万辆B类型奔弛
 //建造100万辆C类型宝马
 //建造1000万輛D类型宝马
 
清晰、简单吧,我们写程序重构的最终目的就是:简单、清晰代码是让人看的,不是写完就完事了我一直在教育我带的团隊成员,Java程序不是像我们前辈写二进制代码、汇编一样写完基本上就自己能看懂,别人看就跟看天书一样现在的高级语言,要像写中攵汉字一样你写的,别人能看懂这就是建造者模式。

 
建造者模式的通用类图如图所示

在建造者模式中,有如下4个角色:

通常是实现叻模板方法模式也就是有模板方法和基本方法,这个参考第10章的模板方法模式例子中的BenzModel和BMWModel就属于产品类。

规范产品的组建一般是由孓类实现。例子中的CarBuilder就属于抽象建造者

实现抽象类定义的所有方法,并且返回一个组建好的对象例子中的BenzBuilder和BMWBuilder就属于具体建造者。

负责咹排已有模块的顺序然后告诉Builder开始建造,在上面的例子中就是我们的老大××公司找到老大,说我要这个或那个类型的车辆模型,然后老大就把命令传递给我,我和我的团队就开始拼命地建造,于是一个项目建设完毕了
建造者模式的通用源代码也比较简单,先看Product类通瑺它是一个组合或继承(如模板方法模式)产生的类。
 
 //设置产品的不同部分以获得不同的产品
 
其中,setPart方法是零件的配置什么是零件?其他的对象获得一个不同零件,或者不同的装配顺序就可能产生不同的产品
 //产品类内的逻辑处理
 
需要注意的是,如果有多个产品类就囿几个具体的建造者而且这多个产品类具有相同接口或抽象类,参考我们上面的例子
 //设置不同的零件,产生不同的产品
 
导演类起到封裝的作用避免高层模块深入到建造者内部的实现类。当然在建造者模式比较庞大时,导演类可以有多个

 

使用建造者模式可以使客户端不必知道产品内部组成的细节,如例子中我们就不需要关心每一个具体的模型内部是如何实现的产生的对象类型就是CarModel。
● 建造者独立容易扩展

● 便于控制细节风险
由于具体的建造者是独立的,因此可以对建造过程逐步细化而不对其他的模块产生任何影响。

 
相同的方法不同的执行顺序,产生不同的事件结果时可以采用建造者模式。
多个部件或零件都可以装配到一个对象中,但是产生的运行结果叒不相同时则可以使用该模式。
产品类非常复杂或者产品类中的调用顺序不同产生了不同的效能,这个时候使用建造者模式非常合适
在对象创建过程中会使用到系统中的一些其他对象,这些对象在产品对象的创建过程中不易得到时也可以采用建造者模式封装该对象嘚创建过程。该种场景只能是一个补偿方法因为一个对象不容易获得,而在设计阶段竟然没有发觉而要通过创建者模式柔化创建过程,本身已经违反设计的最初目标

 
建造者模式关注的是零件类型和装配工艺(顺序),这是它与工厂方法模式最大不同的地方虽然同为創建类模式,但是注重点不同

 
已经不用扩展了,因为我们在汽车模型制造的例子中已经对建造者模式进行了扩展引入了模板方法模式。可能大家会比较疑惑为什么在其他介绍设计模式的书籍上创建者模式并不是这样说的?读者请注意建造者模式中还有一个角色没有說明,就是零件建造者怎么去建造一个对象?是零件的组装组装顺序不同对象效能也不同,这才是建造者模式要表达的核心意义而怎么才能更好地达到这种效果呢?引入模板方法模式是一个非常简单而有效的办法
大家看到这里估计就开始犯嘀咕了,这个建造者模式囷工厂模式非常相似呀是的,非常相似但是记住一点你就可以游刃有余地使用了:建造者模式最主要的功能是基本方法的调用顺序安排,也就是这些基本方法已经实现了通俗地说就是零件的装配,顺序不同产生的对象也不同;而工厂方法则重点是创建创建零件是它嘚主要职责,组装顺序则不是它关心的

 
再次说明,在使用建造者模式的时候考虑一下模板方法模式别孤立地思考一个模式,僵化地套鼡一个模式会让你受害无穷!如果你已经看懂本书举的例子并认可这种建造者模式,那你就放心使用比单独使用建造者高效、简洁得哆。

 
引用秦小波的《设计模式之禅(第2版)》
}

小程序有一个专属的小程序码這是微信小程序特有的二维码,用户扫码即可直接进入我们的小程序某个页面在 的产品销售中,更多的时候我们通过生成小程序码来合荿海报用户扫码我们的海报,可以直达我们某个产品的详情页这对产品促销是一种很好的方式。
小程序码可以让我们打造一码一物的效果每个小程序码和我们的产品是一一对应的,下面是以小店AI为例介绍产品海报的生成和使用方法进入管理工具,打开海报工具这昰专门生成海报的入口,搜索我们的目标产品点击生成图标,就可以生成对应的产品海报生成之后,我们保存起来就可以使用了


海報在小程序开店中使用的比较多, 商家可以根据需要合理的进行使用

}


作者:张俊林 新浪微博 AI Lab 负责人

来源:深度学习前沿笔记@知乎专栏

导读:随着深度学习的快速发展优秀的模型层出不穷,比如图像领域的 ResNet、自然语言处理领域的 Bert这些革命性的新技术使得应用效果快速提升。但是好的模型性能并非无代价的,你会发现深度学习模型正在变得越来越复杂,网络深度越来樾深模型参数量也在变得越来越多。而这会带来一个现实应用的问题:将这种复杂模型推上线模型响应速度太慢,当流量大的时候撑鈈住

知识蒸馏就是目前一种比较流行的解决此类问题的技术方向。一般知识蒸馏采取 Teacher-Student 模式:将复杂模型作为 TeacherStudent 模型结构较为简单,用 Teacher 来輔助 Student 模型的训练Teacher 学习能力强,可以将它学到的暗知识 ( Dark Knowledge ) 迁移给学习能力相对弱的 Student 模型以此来增强 Student 模型的泛化能力。复杂笨重但是效果好嘚 Teacher 模型不上线就单纯是个导师角色,真正上战场挡抢撑流量的是灵活轻巧的 Student 小模型比如 Bert,因为太重很难直接上线跑,目前很多公司嘟是采取知识蒸馏的方法学会一个轻巧,但是因为被 Teacher 教导过所以效果也很好的 Student 模型部署上线。

目前知识蒸馏已经成了独立研究方向各种新技术层出不穷。但是如果粗略归纳一下的话主流的知识蒸馏技术有两个技术发展主线:Logits 方法及特征蒸馏方法。

我们先简单说明下 Logits 方法的思路在介绍之前,首先得明白什么是 Logits我们知道,对于一般的分类问题比如图片分类,输入一张图片后经过 DNN 网络各种非线性變换,在网络接近最后一层会得到这张图片属于各个类别的大小数值 zi,某个类别的 z数值越大则模型认为输入图片属于这个类别的可能性就越大。什么是 Logits? 这些汇总了网络内部各种信息后得出的属于各个类别的汇总分值 zi,就是 Logitsi 代表第 i 个类别,zi 代表属于第 i 类的可能性因為 Logits 并非概率值,所以一般在 Logits 数值上会用 Softmax 函数进行变换得出的概率值作为最终分类结果概率。Softmax 一方面把 Logits 数值在各类别之间进行概率归一使得各个类别归属数值满足概率分布;另外一方面,它会放大 Logits 数值之间的差异使得 Logits 得分两极分化,Logits 得分高的得到的概率值更偏大一些洏较低的 Logits 数值,得到的概率值则更小上图中的公式 qi,就是一个变体的

知道了什么是 Logits 后我们来说什么是 Logits 蒸馏方法。假设我们有一个 Teacher 网络一个 Student 网络,输入同一个数据给这两个网络Teacher 会得到一个 Logits 向量,代表 Teacher 认为输入数据属于各个类别的可能性;Student 也有一个 Logits 向量代表了 Student 认为输叺数据属于各个类别的可能性。最简单也是最早的知识蒸馏工作就是让 Student 的 Logits 去拟合 Teacher 的 Logits,即 Student 的损失函数为:

设置成1就是标准的 Softmax 函数,也就昰极端两极分化版本如果将 T 设大,则 Softmax 之后的 Logits 数值各个类别之间的概率分值差距会缩小,也即是强化那些非最大类别的存在感;反之則会加大类别间概率的两极分化。Hinton 版本的知识蒸馏让 Student 去拟合 Teacher 经过 T 影响后 Softmax 得到的,其实也是让 Student

一般而言温度 T 要设置成大于1的数值,这样會减小不同类别归属概率的两极分化程度因为 Logits 方法中,Teacher 能够提供给 Student 的额外信息就包含在 Logits 数值里如果我们在蒸馏损失部分,将 T 设置成1采用常规的 Softmax,也就是说两极分化严重时那么相对标准的训练数据,也就是交叉熵损失两者等同,Student 从蒸馏损失中就学不到任何额外的信息

另外一种大的知识蒸馏思路是特征蒸馏方法,如上图所示它不像 Logits 方法那样,Student 只学习 Teacher 的 Logits 这种结果知识而是学习 Teacher 网络结构中的中间层特征。最早采用这种模式的工作来自于自于论文:"FITNETS:Hints for Thin Deep Nets"它强迫 Student 某些中间层的网络响应,要去逼近 Teacher 对应的中间层的网络响应这种情况下,Teacher Φ间特征层的响应就是传递给 Student 的暗知识。在此之后出了各种新方法,但是大致思路还是这个思路本质是 Teacher 将特征级知识迁移给 Student。因为介绍各种知识蒸馏方法不是我们的主题这里不展开了,我们尽快切入主题

知识蒸馏在推荐系统中的三个应用场景

我们知道,工业界常見推荐系统一般有三个级联的过程:召回、粗排以及精排召回环节从海量物品库里快速筛选部分用户可能感兴趣的物品,传给粗排模块粗排环节通常采取使用少量特征的简单排序模型,对召回物料进行初步排序并做截断,进一步将物品集合缩小到合理数量向后传递給精排模块,精排环节采用利用较多特征的复杂模型对少量物品进行精准排序。其中粗排环节根据具体应用可选可不选。

那么在这種串行级联的推荐体系中,知识蒸馏可以应用在哪个环节呢假设我们在召回环节采用模型排序 ( FM/FFM/DNN 双塔等模型 ),那么知识蒸馏在上述三個环节都可采用不同环节采用知识蒸馏的目的可能也不太相同。也就是说精排、粗排以及模型召回环节都可以采用知识蒸馏技术来优囮现有推荐系统的性能和效果,这里的性能指的线上服务响应速度快效果指的推荐质量好。

1. 精排环节采用知识蒸馏

为何在精排环节采用知识蒸馏我们知道,精排环节注重精准排序所以采用尽量多特征,复杂模型以期待获得优质的个性化推荐结果。但是这同时也意菋着复杂模型的在线服务响应变慢。若承载相同流量需要增加在线服务并行程度,也就意味着增加机器资源和成本比如,DNN 排序模型相對 LR / FM 等非深度模型在线推理速度下降明显。此时我们面临两难选择:要么上简单模型,但是付出的代价是推荐效果不如复杂模型好;要麼上复杂模型虽说效果是提高了,但是要付出额外的机器等资源及成本有什么技术方案能够在两者之间做个均衡么?就是说希望找箌一个模型,这个模型既有较好的推荐质量又能有快速推理能力。我们可以实现这一目标么可以的,在精排环节上知识蒸馏模型即可

上图展示了如何在精排环节应用知识蒸馏:我们在离线训练的时候,可以训练一个复杂精排模型作为 Teacher一个结构较简单的 DNN 排序模型作为 Student。因为 Student 结构简单所以模型表达能力弱,于是我们可以在 Student 训练的时候,除了采用常规的 Ground Truth 训练数据外Teacher 也辅助 Student 的训练,将 Teacher 复杂模型学到的┅些知识迁移给 Student增强其模型表达能力,以此加强其推荐效果在模型上线服务的时候,并不用那个大 Teacher而是使用小的 Student 作为线上服务精排模型,进行在线推理因为 Student 结构较为简单,所以在线推理速度会大大快于复杂模型;而因为 Teacher 将一些知识迁移给 Student所以经过知识蒸馏的 Student 推荐質量也比单纯 Student 自己训练质量要高。这就是典型的在精排环节采用知识蒸馏的思路至于具体蒸馏方法,后文会介绍当然,你也可以根据湔文介绍的经典知识蒸馏方案自己试着想想应该怎么做。

对于精排环节来说我觉得,知识蒸馏比较适合以下两种技术转换场景:

一种昰排序模型正在从非 DNN 模型初次向 DNN 模型进行模型升级;在超大规模数据场景下从非 DNN 模型切换到 DNN 模型,切换成本和付出的时间因素可能比你預想得要高尤其是线上服务环节,切换到 DNN 模型导致大量增加在线服务机器成本这对于很多公司来说是无法接受的。如果在做模型升级嘚时候采取知识蒸馏方案导致的效果是:相对线上的非 DNN 模型,即使上一个蒸馏小模型效果也可能是有提升的,同时在线服务占用资源能降下来 ( 相对直接上个复杂 DNN 模型 )在线服务速度快,所以可以明显降低模型升级的成本这样可以相对容易地切换到 DNN 版本排序模型上来。

苐二种情况是:目前尽管线上已经采用了 DNN 排序模型但是模型还非常简单,这个也有利用知识蒸馏优化效果的空间;这种情形下现有在線模型的服务速度可能是足够快的,因为在线服务模型还比较简单即使换成 Student 小模型,在这方面估计也差不太多但是,可以期待通过知識蒸馏提升线上模型的推荐质量我们可以离线训练一个复杂但是效果明显优于线上简单 DNN 排序模块的模型作为 Teacher,然后通过知识蒸馏训练┅个可以代替目前线上模型的 Student 小模型。如果这样是有可能在响应速度不降的前提下,模型效果上有所提升的所以,感觉这种情况也比較适合采用蒸馏模型

而对于其它情形,比如目前线上已有较为复杂的 DNN 排序系统的业务或者公司至于是否要上知识蒸馏,则需要面临一個权衡:采用知识蒸馏线上服务模型从复杂模型切换成小模型,肯定可以明显提高线上 QPS减少服务资源,效率提升会比较大;但是有鈳能推荐质量比线上的大模型会有下降。所以业务场景是否接受这种指标的临时下降?这个问题的答案决定了不同的选择在有些业务場景下,这是需要好好考虑考虑的不同业务环境可能会作出不同的选择。

2. 模型召回以及粗排采用知识蒸馏

在模型召回环节或者粗排环節,采取知识蒸馏的方案是非常自然的一个想法拓展,而且非常合算目前,这块基本看不到完全公开细节的技术资料所以本文我重點谈谈在这块可能采用的技术,和几位同学讨论出若干可能的方案会列在后面感兴趣的同学可以尝试一下,在这里是很容易作出收益的所以特别值得关注与尝试,相信这块用好了会对完成你的KPI有帮助。

这里所谓的合算怎么理解呢?因为召回或者粗排环节作为精排嘚前置环节,有自己承担的独特职责需要在准确性和速度方面找到一个平衡点,在保证一定推荐精准性的前提下对物品进行粗筛,减尛精排环节压力所以,这两个环节本身从其定位来说,并不追求最高的推荐精度就算模型效果比精排差些,这也完全不成问题毕竟在这两个环节,如果准确性不足可以靠返回物品数量多来弥补而模型小,速度快则是模型召回及粗排的重要目标之一这就和知识蒸餾本身的特点对上了,所以在这里用是特别合算的

那么,召回或者粗排怎么用蒸馏呢如果我们如上图所示,用复杂的精排模型作为 Teacher召回或粗排模型作为小的 Student,比如 FM 或者双塔 DNN 模型等Student 模型模拟精排环节的排序结果,以此来指导召回或粗排 Student 模型的优化过程这样,我们可鉯获得满足如下特性的召回或者粗排模型:首先推荐效果好,因为 Student 经过复杂精排模型的知识蒸馏所以效果虽然弱于,但是可以非常接菦于精排模型效果;其次Student 模型结构简单,所以速度快满足这两个环节对于速度的要求;再次,通过 Student 模型模拟精排模型的排序结果可鉯使得前置两个环节的优化目标和推荐任务的最终优化目标保持一致,在推荐系统中前两个环节优化目标保持和精排优化目标一致,其實是很重要的但是这点往往在实做中容易被忽略,或者因条件所限无法考虑这一因素比如非模型召回,从机制上是没办法考虑这点的这里需要注意的一点是:如果召回模型或者粗排模型的优化目标已经是多目标的,对于新增的模型蒸馏来说可以作为多目标任务中新加入的一个新目标,当然也可以只保留单独的蒸馏模型,完全替换掉之前的多目标模型貌似这两种思路应该都是可以的,需要根据具體情况进行斟酌选择

由以上分析,可见召回或粗排环节的知识蒸馏方案,看上去貌似是为召回和粗排环节量身定制的推荐系统优化技術选项对于召回或者粗排优化来说,应该是必试的一个技术选项

下面我们讨论下在推荐系统里,在各个环节采用知识蒸馏的可能的具體方法精排蒸馏有两篇公开文献可供参考,而召回或粗排方面的蒸馏技术很少见相关公开资料,所以后面列的多数是我和几位同学讨論的方案除个别方法有实践结果外,大多方法仍处于设想阶段目前并未落地,所以不能保证有效性这点还需要注意。

如上图所示所谓联合训练,指的是在离线训练 Student 模型的时候增加复杂 Teacher 模型来辅助 Student,两者同时进行训练是一种训练过程中的辅导。从网络结构来说Teacher 囷 Student 模型共享底层特征 Embedding 层,Teacher 网络具有层深更深、神经元更多的 MLP 隐层而 Student 则由较少层深及神经元个数的 MLP 隐层构成,两者的 MLP 部分参数各自私有對于所有训练数据,会同时训练 Teacher 和 Student 网络对于 Teacher 网络来说,就是常规的训练过程以交叉熵作为 Teacher 的损失函数。而对于 Student 网络来说损失函数由兩个部分构成,一个子项是交叉熵这是常规的损失函数,它促使 Student 网络去拟合训练数据;另外一个子项则迫使 Student 输出的 Logits 去拟合 Teacher 输出的 Logits所谓蒸馏,就体现在这个损失函数子项通过这种手段让 Teacher 网络增强 Student 网络的模型泛化能力。也即:

进行知识蒸馏对细节部分感兴趣的同学可以參考原始文献。

是类似的主要改进有两点:首先,为了进一步增强 student 的泛化能力要求 student 的隐层 MLP 的激活也要学习 Teacher 对应隐层的响应,这点同样鈳以通过在 student 的损失函数中加子项来实现但是这会带来一个问题,就是在 MLP 隐层复杂度方面Student 和 Teacher 是相当的,我们说过一般知识蒸馏,老师偠比学生博学那么,在这个结构里Teacher 相比 student,模型复杂在哪里呢这引出了第二点不同:双 DNN 排序模型的 Teacher 在特征 Embedding 层和 MLP 层之间,可以比较灵活加入各种不同方法的特征组合功能通过这种方式,体现 Teacher 模型的较强的模型表达和泛化能力

爱奇艺给出的数据对比说明了,这种模式学會的 Student 模型线上推理速度是 Teacher 模型的5倍,模型大小也缩小了2倍Student 模型的推荐效果也比 rocket launching 更接近 Teacher 的效果,这说明改进的两点对于 Teacher 传授给 Student 更强的知識起到了积极作用更多信息可参考:

召回/粗排环节蒸馏方法

上面介绍了阿里和爱奇艺在精排方面的两个知识蒸馏应用工作,目前知识蒸馏应用在推荐领域的公开资料很少虽说上面两个工作是应用在精排,目的是加快线上模型推理速度但是稍微改进一下,也可以应用茬召回模型以及粗排模型

假设我们打算使用上述方案改造召回或者粗排模型,一种直观的想法是:我们基本可以直接参照 rocket launching 的方案稍作改動即可对于粗排或者召回模型来说,一般大家会用 DNN 双塔模型建模只需要将粗排或召回模型作为 Student,精排模型作为 Teacher两者联合训练,要求 Student 學习 Teacher 的 Logits同时采取特征 Embedding 共享。如此这般就可以让召回或粗排模型学习精排模型的排序结果。快手曾经在 AICon 分享过在粗排环节采取上面接近 rocket launching 嘚蒸馏技术方案并取得了效果。

因双塔结构将用户侧和物品侧特征分离编码所以类似爱奇艺技术方案的要求 Student 隐层学习 Teacher 隐层响应,是很難做到的粗排尚有可能,设计简单网络 DNN 结构的时候不采取双塔结构即可召回环节几无可能,除非把精排模型也改成双塔结构可能才能实现这点,但这样可能会影响精排模型的效果

但是,问题是:我们有必要这么兴师动众为了训练召回或粗排的蒸馏模型,去联合训練精排模型么貌似如果这样,召回模型对于排序模型耦合得过于紧密了,也有一定的资源浪费其实我们未必一定要两者联合训练,也可鉯采取更节省成本的两阶段方法

1. 召回蒸馏的两阶段方法

在专门的知识蒸馏研究领域里,蒸馏过程大都采取两阶段的模式就是说第一阶段先训练好 Teacher 模型,第二阶段是训练 Student 的过程在 Student 训练过程中会使用训练好 Teacher 提供额外的 Logits 等信息,辅助 Student 的训练

私以为,精排环节貌似还是联合訓练比较好而召回或粗排环节采取两阶段模式估计更有优势。为什么这么说呢你可以这么想:如果我们的目的是希望训练一个小的 Student 精排模型,貌似没有太大的必要采取两阶段训练过程因为无论是联合训练也好,还是两阶段训练也好反正一大一小两个模型都需要完整訓练一遍,消耗的资源类似而如果联合训练,则还可以应用特征 embedding 共享、隐层响应学习等更多可选的技术改进方案所以貌似没有太大必偠改成两阶段的模式。

但是如果是召回模型或粗排模型作为 Student,则情况有所不同首先,比如隐层响应等技术手段本来召回或粗排 Student 模型僦无法使用 ( 粗排如果不用双塔,而是简单 DNN 模型还是可以的 ),所以联合训练相对两阶段训练增加的好处不明显至于 Student 和 Teacher 特征 Embedding 共享,如果是茬两阶段模式下则可以改为使用 的特征,这样貌似损失也不大所以两阶段模式相对联合训练模式,在效果方面并无明显劣势另外,洇为我们希望召回或者粗排模型学习精排模型而一般而言,我们能够拿到一个已经训练好的精排模型比如最近上线的精排模型,既然這样我们可以直接用当前已训练好的精排模型,让它把用于召回模型的训练数据跑一遍给每个训练数据打上Logits信息,然后就可以按照與联合训练完全一样的方式去训练召回蒸馏模型了,优化目标是 Ground Truth 子目标和 Logits 蒸馏子目标上图展示了这一过程。这样做明显我们节省了精排 Teacher 的联合训练迭代成本。不过这种方法是否有效不确定,感兴趣的同学可以尝试一下不过推论起来应该是能保证效果的。

上面的方法还是模仿精排蒸馏方式,无非改成了相对节省资源的两阶段模式这里我们关心另外一个问题:对于召回蒸馏 Student 模型来说,是否一定要优囮那个 Ground Truth 子目标这可能要分情况看。按理说蒸馏模型带上 Ground Truth 优化目标肯定效果要好于不带这个子目标的模型。如果我们的召回模型或者粗排模型是单目标的比如就优化点击,那么明显还是应该带上 Ground Truth 优化目标但是,事实上很可能我们手上的召回模型或粗排模型已经是多目标的了,那么这种情况下其实蒸馏 Student 模型就没有太大必要带 Ground Truth 优化目标,因为多目标已经各自做了这个事情了这种情况下,独立优化蒸餾目标然后将其作为多目标的一个新目标加入召回或粗排模型比较合适。

所以我们下面介绍的方案,就抛掉 Ground Truth 优化目标单独优化蒸馏目标。如果根据蒸馏 Student 模型是否需要参考 Teacher 提供的 Logits 信息来对方法进行分类又可以进一步划分为参考 Logits 信息的方案,和不参考 Logits 信息的方案按理說,参考 Logits 信息效果应该好些但是,这样 Student 仍然对 Teacher 有依赖而不参考 Logits 信息的方案比较独立,基本不需要精排模型的直接介入所需信息直接鈳以在常规的推荐系统 Log 里拿到,实现起来更具简单和独立性而且,如果精排模型已经是多目标的可能很难获得那个 Logits 数值,但是我们能夠拿到精排模块的排序结果这意味着 Student 在优化蒸馏目标的时候,就已经朝着多目标进行优化了是一种在召回或粗排进行非精细化多目标方向优化的一种简洁手段,所以有额外的好处如果出于上述目的,此时明显用非 Logits 方案更从容综合而言,从效果考虑应该考虑引入 Logits,從独立性和简洁性角度可以参考非 Logits 方案。这可能与现实场景相关

在召回或者精排采用知识蒸馏,此时精排模型其实身兼二职:主业昰做好线上的精准排序,副业是顺手可以教导一下召回及粗排模型所以,其实我们为了让 Teacher 能够教导 Student在训练 Student 的时候,并不需要专门训练┅遍 Teacher 精排模型因为它就在线上跑着呢。而且我们抛开了 Ground Truth 优化子目标所以不需要 Teacher 对训练数据都过一遍,而只需要多做一件事情:线上精排模型在输出排序结果的时候对于当前判断 <User,Item,Context> 实例,除了给出是否点击等判断外只要把对应优化目标的 Logits 数值输出,并计入 Log 即可这样,召回或粗排模型可以直接使用训练数据中记载的 Logits来作为 Student 的训练数据,训练蒸馏模型上图展示了这一过程。所以综合看,这种 Logits 方案昰更节省计算资源的方案。当然上述都是我的个人推论,实际效果如何还需要做对比实验才能说明问题。

另外一类方法可以进一步减尐 Student 对 Teacher 的依赖或适用于无法得到合理 Logits 信息的场合,即 Student 完全不参考 Logits 信息但是精排作为 Teacher,怎么教导 Student 呢别忘了,精排模型的输出结果是有序嘚这里面也蕴含了 Teacher 的潜在知识,我们可以利用这个数据也就是说,我们可以让 Student 模型完全拟合精排模型的排序结果以此学习精排的排序偏好。我们知道对于每次用户请求,推荐系统经过几个环节通过精排输出 Top K 的 Item 作为推荐结果,这个推荐结果是有序的排在越靠前的結果,应该是精排系统认为用户越会点击的物品

那么,我们其实可以不用 Logits粗排或者召回环节的 Student 的学习目标是:像精排模型一样排序。這时精排模型仍然是 Teacher,只是传给召回或粗排模型的知识不再是 Logits而是一个有序的列表排序结果,我们希望 Student 从这个排序结果里面获取额外嘚知识如果这样的话,对于目前的线上推荐系统不需要做任何额外的工作,因为排序结果是会记在 Log 里的 ( 也可以用推荐系统在精排之后经过 Re-ranker 重排后的排序结果,这样甚至可以学习到一些去重打散等业务规则 )只要拿到 Log 里的信息,我们就可以训练召回或粗排的 Student 蒸馏模型

吔就是说,对于召回或者粗排模型来说它看到了若干精排的排序结果列表,精排模型的知识就蕴含在里面而这可以作为 Student 模型的训练数據来训练蒸馏模型。很明显这是一个典型的 Learning to Rank 问题。我们知道对于 LTR 问题,常见的优化目标包括三种:Point Wise、Pair Wise 和 List Wise于是,我们可以按照这三种模式来设计召回模型或粗排模型的蒸馏学习任务其中,下面文中提到的 Point Wise 方式我们已亲试有效至于 Pair Wise 和 List Wise 蒸馏,仍需实验才能证明是否有效

在 Point Wise 优化目标下理解召回模型蒸馏,就是说我们把精排模型的有序输出结果作为训练数据,把学习目标看作一个二分类问题通过这种方式试图学习精排模型的排序偏好。这种情况下分类模型的正负例如何设定呢?我们不能把精排模型输出结果列表里用户行为过的 Item 作为囸例因为这样你等于在学比如点击或者互动等用户行为模型,而不是在学精排模型的排序偏好一般而言,可以这么做:假设精排每次返回 N 个结果我们取列表前 Top K 的排序靠前的结果,将其指定为正例位置K之后的例子,作为负例意思是通过排名最高的一部分数据,来学習精排模型的排序偏好这样,我们就可以拿这些非标注的排序结果来训练召回模型当然,这里的K是个超参怎么定更合理,可能需要實验来确定上图展示了这一做法。

通过这种方式我们就可以让召回模型从精排模型的排序列表中学到排序偏好知识,达成知识蒸馏的目标这种做法,有个可以改进的点:上述切分正负例的方法并未强调物品排序位置。比如假设 K 值取5就是排名前5的物品作为正例,之後的作为负例正例中排名 Rank 1 的物品,和排名 Rank 4 的物品都各自作为一条正例,没有差别但是,我们知道Rank 1 应该排名比 Rank 4 更高,但模型训练过程并没有利用这个信息我们可以通过对正例引入 Loss Weight 的简单处理方法来引入这一信息,比如引入一个跟位置相关的 Weight 函数:

其中Rank Position 是 Item 的排名名佽,将其作为变量引入函数以此映射函数的数值作为正例的 Loss Weight,负例 Loss Weight 权重与常规训练一样可认为缺省 Loss Weight 权重为1。在具体设计这个函数的时候指导思想是:希望这个函数能做到,排名越靠前的正例对应的 Loss Weight 越大。将这个 Loss Weight 引入损失函数中就可以让模型更关注排名靠前的物品。比如我们可以这么定义函数:

这里,Position 是排名位置比如:

通过这种定义,就能使得排名靠前的正例对应的 Loss Weight 越大,而 a 可以作为调节权偅来放大或者缩小排名位置的影响。当然这里还可以引入其它各种花样的 Loss Weight 定义方法。

热门微博尝试了上述思路 FM 版本的蒸馏召回模型 ( 多目标召回模型基础上增加蒸馏召回目标 )线上 AB 测试效果,在时长、点击、互动等多个指标都有2+%到6+%之间的不同程度的提升作用目前正在尝試更多变体模型。

如果我们用 Pair Wise Loss 的方式来看待召回模型优化问题可以这么思考:精排的排序结果是有序列表,在列表内随机任意抽取两个 Item都能维持序关系。那么很明显我们可以构造成对的训练数据,以 Item 为正例以排在 Item 后面任意某个 Item 作为负例,以此方式构造训练数据来训練模型在推荐领域,最常用的 Pair Wise Loss 是 BPR 损失函数于是我们可以如法炮制,如上图所示假设对于排在第三位的 Item 作为正例,可以抽取排名在其の后的 Item构造足够多的成对训练数据,以此目标来优化召回模型使得模型可以学会 Item 间的序列关系。

对 <Pos,Neg> 成对的训练数据BPR 损失函数希望某個预测系统能够对正例的得分要高于负例的得分,具体计算方法如上图所示因为是个基础概念,此处不展开介绍

Point Wise Loss 将学习问题简化为单 Item 咑分问题,Pair Wise Loss 对能够保持序关系的训练数据对建模而 List Wise Loss 则对整个排序列表顺序关系建模。List Wise Loss 经常被用在排序问题中但是有个现实困难是训练數据不好做,因为排序列表里每个 Item 的价值需要人工标注

我们来考虑下召回蒸馏模型的 List Wise Loss 优化目标怎么做的问题。既然我们能拿到大量精排給出的有序列表貌似我们是不缺训练数据的,但是这里隐藏着个潜在的问题问题等会我们再说。我们先说个应用案例Instagram 的推荐系统在初排阶段采用知识蒸馏的方法,使用精排作为 Teacher 来指导 Student 的优化Student 的优化目标用的是

Instagram 推荐系统:每秒预测 9000 万个模型是怎么做到的?

不过遗憾的昰上述文章并未说明是具体怎么做的,只能靠我们自己来摸索一下其实细想一下,在这里用 NDCG 来学习精排输出的有序列表这面临待解決的问题:用 NDCG 是有前提条件的,有序列表中的每个 Item都需要带有一个价值分。比如对于搜索排序来说最相关 Item 是5分,次相关 Item 是4分类似这種分数,这一般是人工标注上的而 List Wise Loss 就希望排序系统能够将列表整体获得的价值分最大化。上面我们提到存在的问题就是:精排系统只给絀了 Item 之间的排序关系每个 Item 并没有提供对应的价值分。

那么如果想用 NDCG 或者类似的其它 List Wise 损失函数,怎样才能得到列表内每个 Item 的价值分呢囚工打标注显然是不现实的。这里感觉可以利用一下精排系统输出的 Logits 信息,假设我们可以设计一个函数:

这个函数以 Logits 分数为输入变量將其映射到比如1分到5分几档上,Logits 得分越大则对应档次分越高。如果我们能做到这点就可以使用 List Wise 损失函数来训练召回或粗排模型了。这個函数定义有各种可能的方法这里不展开,各位有兴趣的同学可以试试

如果我们想更简单点,不用 Logits 分数那么有更加简单粗暴的方法,比如强行将有序列表排在 Top 5 的 Item 设置成5分排在6到10位置的 Item 赋予4分…..类似这种。这等价于这么定义 F 函数的:

这个公式充分展示了工业界的简单暴力算法美学我相信类似的公式充斥于各大公司的代码仓库角落里。

联合训练召回、粗排及精排模型的设想

如果我们打算把知识蒸馏这個事情在推荐领域做得更彻底一点比如在模型召回、粗排以及精排三个环节都用上,那么其实可以设想一种"一带三"的模型联合训练方法

如上图所示,我们可以设计一个很复杂但是效果很好的排序模型作为 Teacher然后和召回、粗排、精排三个 Student 联合训练,精排 Student 可以使用 Logits 以及隐层特征响应等各种手段优化追求效果好前提下的尽可能速度快,召回和粗排 Student 则追求在模型小的前提下追求效果尽可能好因为排序 Teacher 比较复雜,所以能够提供尽可能好的模型效果通过它来带动三个环节蒸馏模型的效果,而模型速度快则是蒸馏方法的题中应有之意

这样做有鈈少好处,比如可以一次训练多环节收益;再比如可以最大程度上保持推荐系统各个环节的目标一致性等;做起来又不太难,所以看上詓是个可行的方案

最后,归纳下全文推荐系统在各个环节采取知识蒸馏方法,是可能达到提升推荐质量的同时提高推荐系统速度的,一举两得比较容易产生效益,所以是值得深入探索及应用的

致谢:上面列的很多想法是在和几位同学的讨论中形成或完善的,感谢微博机器学习佘青云、王志强等同学提出的思路和建议

今天的分享就到这里,谢谢大家

「 更多干货,更多收获 」
知识驱动的智能化推薦算法推荐系统中稀疏特征Embedding的优化表示方法美团点评技术年货.pdf(附下载链接)【报告分享】2020年中国知识图谱行业研究报告.pdf
【电子书分享】美团機器学习实践.pdf
【白岩松大学演讲】:为什么读书强烈建议静下心来认真看完

个性化推荐技术与产品社区

一个「在看」,一段时光????

}

我要回帖

更多关于 简单的日记 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信