<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          復(fù)雜模型該如何上線?知識(shí)蒸餾在推薦系統(tǒng)中的應(yīng)用

          共 16526字,需瀏覽 34分鐘

           ·

          2021-03-17 19:34

          點(diǎn)擊上方“程序員大白”,選擇“星標(biāo)”公眾號(hào)

          重磅干貨,第一時(shí)間送達(dá)

          轉(zhuǎn)載自:煉丹筆記
          作者:張俊林@新浪微博
          目錄
          • 知識(shí)蒸餾典型方法
          • 知識(shí)蒸餾在推薦系統(tǒng)中的三個(gè)應(yīng)用場(chǎng)景

          • 知識(shí)蒸餾在三類推薦排序中的方法介紹

          • 聯(lián)合訓(xùn)練召回、粗排及精排模型的設(shè)想

          前言

              隨著深度學(xué)習(xí)的快速發(fā)展,優(yōu)秀的模型層出不窮,比如圖像領(lǐng)域的ResNet、自然語言處理領(lǐng)域的Bert,這些革命性的新技術(shù)使得應(yīng)用效果快速提升。但是,好的模型性能并非無代價(jià)的,你會(huì)發(fā)現(xiàn),深度學(xué)習(xí)模型正在變得越來越復(fù)雜,網(wǎng)絡(luò)深度越來越深,模型參數(shù)量也在變得越來越多。而這會(huì)帶來一個(gè)現(xiàn)實(shí)應(yīng)用的問題:將這種復(fù)雜模型推上線,模型響應(yīng)速度太慢,當(dāng)流量大的時(shí)候撐不住。

              知識(shí)蒸餾就是目前一種比較流行的解決此類問題的技術(shù)方向。一般知識(shí)蒸餾采取Teacher-Student模式:將復(fù)雜模型作為Teacher,Student模型結(jié)構(gòu)較為簡(jiǎn)單,用Teacher來輔助Student模型的訓(xùn)練,Teacher學(xué)習(xí)能力強(qiáng),可以將它學(xué)到的暗知識(shí)(Dark Knowledge)遷移給學(xué)習(xí)能力相對(duì)弱的Student模型,以此來增強(qiáng)Student模型的泛化能力。復(fù)雜笨重但是效果好的Teacher模型不上線,就單純是個(gè)導(dǎo)師角色,真正上戰(zhàn)場(chǎng)擋搶撐流量的是靈活輕巧的Student小模型。比如Bert,因?yàn)樘?,很難直接上線跑,目前很多公司都是采取知識(shí)蒸餾的方法,學(xué)會(huì)一個(gè)輕巧,但是因?yàn)楸籘eacher教導(dǎo)過,所以效果也很好的Student模型部署上線。
          知識(shí)蒸餾典型方法
              目前知識(shí)蒸餾已經(jīng)成了獨(dú)立研究方向,各種新技術(shù)層出不窮。但是如果粗略歸納一下的話,主流的知識(shí)蒸餾技術(shù)有兩個(gè)技術(shù)發(fā)展主線:Logits方法特征蒸餾方法。
              我們先簡(jiǎn)單說明下Logits方法的思路。在介紹之前,首先得明白什么是Logits。我們知道,對(duì)于一般的分類問題,比如圖片分類,輸入一張圖片后,經(jīng)過DNN網(wǎng)絡(luò)各種非線性變換,在網(wǎng)絡(luò)接近最后一層,會(huì)得到這張圖片屬于各個(gè)類別的大小數(shù)值  ,某個(gè)類別的  數(shù)值越大,則模型認(rèn)為輸入圖片屬于這個(gè)類別的可能性就越大。
          什么是Logits? 
              這些匯總了網(wǎng)絡(luò)內(nèi)部各種信息后,得出的屬于各個(gè)類別的匯總分值  ,就是Logits, i代表第i個(gè)類別,  代表屬于第i類的可能性。因?yàn)長(zhǎng)ogits并非概率值,所以一般在Logits數(shù)值上會(huì)用Softmax函數(shù)進(jìn)行變換,得出的概率值作為最終分類結(jié)果概率。Softmax一方面把Logits數(shù)值在各類別之間進(jìn)行概率歸一,使得各個(gè)類別歸屬數(shù)值滿足概率分布;另外一方面,它會(huì)放大Logits數(shù)值之間的差異,使得Logits得分兩極分化,Logits得分高的得到的概率值更偏大一些,而較低的Logits數(shù)值,得到的概率值則更小。上圖中的公式  ,就是一個(gè)變體的Softmax公式,如果把T拿掉或令T=1,則是個(gè)標(biāo)準(zhǔn)的Softmax公式,  就是第i個(gè)類別的Logits數(shù)值,  是Logits數(shù)值經(jīng)過Softmax變換后,歸屬于第i個(gè)類別的概率值。
              知道了什么是Logits后,我們來說什么是Logits蒸餾方法?假設(shè)我們有一個(gè)Teacher網(wǎng)絡(luò),一個(gè)Student網(wǎng)絡(luò),輸入同一個(gè)數(shù)據(jù)給這兩個(gè)網(wǎng)絡(luò),Teacher會(huì)得到一個(gè)Logits向量,代表Teacher認(rèn)為輸入數(shù)據(jù)屬于各個(gè)類別的可能性;Student也有一個(gè)Logits向量,代表了Student認(rèn)為輸入數(shù)據(jù)屬于各個(gè)類別的可能性。最簡(jiǎn)單也是最早的知識(shí)蒸餾工作,就是讓Student的Logits去擬合Teacher的Logits,即Student的損失函數(shù)為:

              其中,  是Teacher的Logits,  是Student的Logits。在這里,Teacher的Logits就是傳給Student的暗知識(shí)。
              Hinton在論文Distilling the Knowledge in a Neural Network中提出了稱為Softmax Temperature的改進(jìn)方法,并第一次正式提出了“知識(shí)蒸餾”的叫法。Softmax Temperature改造了Softmax函數(shù)(公式參考上圖),引入了溫度T,這是一個(gè)超參數(shù)。如果我們把T設(shè)置成1,就是標(biāo)準(zhǔn)的Softmax函數(shù),也就是極端兩極分化版本。如果將T設(shè)大,則Softmax之后的Logits數(shù)值,各個(gè)類別之間的概率分值差距會(huì)縮小,也即是強(qiáng)化那些非最大類別的存在感;反之,則會(huì)加大類別間概率的兩極分化。Hinton版本的知識(shí)蒸餾,讓Student去擬合Teacher經(jīng)過T影響后Softmax得到的,其實(shí)也是讓Student去學(xué)習(xí)Teacher的Logits,無非是加入T后可以動(dòng)態(tài)調(diào)節(jié)Logits的分布。Student的損失函數(shù)由兩項(xiàng)組成,一個(gè)子項(xiàng)是Ground Truth,就是在訓(xùn)練集上的標(biāo)準(zhǔn)交叉熵?fù)p失,讓Student去擬合訓(xùn)練數(shù)據(jù),另外一個(gè)是蒸餾損失,讓Student去擬合Teacher的Logits:

              H是交叉熵?fù)p失函數(shù),  是Student模型的映射函數(shù),  是Ground Truth Label,  是Teacher的Logits,  是Student的Logits,  是Softmax Temperature函數(shù),  用于調(diào)節(jié)蒸餾Loss的影響程度。
              一般而言,溫度T要設(shè)置成大于1的數(shù)值,這樣會(huì)減小不同類別歸屬概率的兩極分化程度,因?yàn)長(zhǎng)ogits方法中,Teacher能夠提供給Student的額外信息就包含在Logits數(shù)值里。如果我們?cè)谡麴s損失部分,將T設(shè)置成1,采用常規(guī)的Softmax,也就是說兩極分化嚴(yán)重時(shí),那么相對(duì)標(biāo)準(zhǔn)的訓(xùn)練數(shù)據(jù),也就是交叉熵?fù)p失,兩者等同,Student從蒸餾損失中就學(xué)不到任何額外的信息。
              另外一種大的知識(shí)蒸餾思路是特征蒸餾方法,如上圖所示。它不像Logits方法那樣,Student只學(xué)習(xí)Teacher的Logits這種結(jié)果知識(shí),而是學(xué)習(xí)Teacher網(wǎng)絡(luò)結(jié)構(gòu)中的中間層特征。最早采用這種模式的工作來自于自于論文:“FITNETS:Hints for Thin Deep Nets”,它強(qiáng)迫Student某些中間層的網(wǎng)絡(luò)響應(yīng),要去逼近Teacher對(duì)應(yīng)的中間層的網(wǎng)絡(luò)響應(yīng)。這種情況下,Teacher中間特征層的響應(yīng),就是傳遞給Student的暗知識(shí)。在此之后,出了各種新方法,但是大致思路還是這個(gè)思路,本質(zhì)是Teacher將特征級(jí)知識(shí)遷移給Student。因?yàn)榻榻B各種知識(shí)蒸餾方法不是我們的主題,這里不展開了,我們盡快切入主題。
          知識(shí)蒸餾在推薦系統(tǒng)中的三個(gè)應(yīng)用場(chǎng)景


              我們知道,工業(yè)界常見推薦系統(tǒng)一般有三個(gè)級(jí)聯(lián)的過程:召回、粗排以及精排。召回環(huán)節(jié)從海量物品庫里快速篩選部分用戶可能感興趣的物品,傳給粗排模塊,粗排環(huán)節(jié)通常采取使用少量特征的簡(jiǎn)單排序模型,對(duì)召回物料進(jìn)行初步排序,并做截?cái)?,進(jìn)一步將物品集合縮小到合理數(shù)量,向后傳遞給精排模塊,精排環(huán)節(jié)采用利用較多特征的復(fù)雜模型,對(duì)少量物品進(jìn)行精準(zhǔn)排序。其中,粗排環(huán)節(jié)根據(jù)具體應(yīng)用可選可不選。

              那么,在這種串行級(jí)聯(lián)的推薦體系中,知識(shí)蒸餾可以應(yīng)用在哪個(gè)環(huán)節(jié)呢?假設(shè)我們?cè)谡倩丨h(huán)節(jié)采用模型排序(FM/FFM/DNN雙塔等模型),那么知識(shí)蒸餾在上述三個(gè)環(huán)節(jié)都可采用,不同環(huán)節(jié)采用知識(shí)蒸餾的目的可能也不太相同。也就是說,精排、粗排以及模型召回環(huán)節(jié)都可以采用知識(shí)蒸餾技術(shù)來優(yōu)化現(xiàn)有推薦系統(tǒng)的性能和效果,這里的性能指的線上服務(wù)響應(yīng)速度快,效果指的推薦質(zhì)量好。

          1. 精排環(huán)節(jié)采用知識(shí)蒸餾

              為何在精排環(huán)節(jié)采用知識(shí)蒸餾?我們知道,精排環(huán)節(jié)注重精準(zhǔn)排序,所以采用盡量多特征,復(fù)雜模型,以期待獲得優(yōu)質(zhì)的個(gè)性化推薦結(jié)果。但是,這同時(shí)也意味著復(fù)雜模型的在線服務(wù)響應(yīng)變慢。若承載相同流量,需要增加在線服務(wù)并行程度,也就意味著增加機(jī)器資源和成本,比如,DNN 排序模型相對(duì)LR/FM等非深度模型,在線推理速度下降明顯。
              此時(shí),我們面臨兩難選擇:要么上簡(jiǎn)單模型,但是付出的代價(jià)是推薦效果不如復(fù)雜模型好;要么上復(fù)雜模型,雖說效果是提高了,但是要付出額外的機(jī)器等資源及成本。有什么技術(shù)方案能夠在兩者之間做個(gè)均衡么?就是說,希望找到一個(gè)模型,這個(gè)模型既有較好的推薦質(zhì)量,又能有快速推理能力。我們可以實(shí)現(xiàn)這一目標(biāo)么?可以的,在精排環(huán)節(jié)上知識(shí)蒸餾模型即可。
              上圖展示了如何在精排環(huán)節(jié)應(yīng)用知識(shí)蒸餾:我們?cè)陔x線訓(xùn)練的時(shí)候,可以訓(xùn)練一個(gè)復(fù)雜精排模型作為Teacher,一個(gè)結(jié)構(gòu)較簡(jiǎn)單的DNN排序模型作為Student。因?yàn)镾tudent結(jié)構(gòu)簡(jiǎn)單,所以模型表達(dá)能力弱,于是,我們可以在Student訓(xùn)練的時(shí)候,除了采用常規(guī)的Ground Truth訓(xùn)練數(shù)據(jù)外,Teacher也輔助Student的訓(xùn)練,將Teacher復(fù)雜模型學(xué)到的一些知識(shí)遷移給Student,增強(qiáng)其模型表達(dá)能力,以此加強(qiáng)其推薦效果。在模型上線服務(wù)的時(shí)候,并不用那個(gè)大Teacher,而是使用小的Student作為線上服務(wù)精排模型,進(jìn)行在線推理。因?yàn)镾tudent結(jié)構(gòu)較為簡(jiǎn)單,所以在線推理速度會(huì)大大快于復(fù)雜模型;而因?yàn)門eacher將一些知識(shí)遷移給Student,所以經(jīng)過知識(shí)蒸餾的Student推薦質(zhì)量也比單純Student自己訓(xùn)練質(zhì)量要高。這就是典型的在精排環(huán)節(jié)采用知識(shí)蒸餾的思路。至于具體蒸餾方法,后文會(huì)介紹。當(dāng)然,你也可以根據(jù)前文介紹的經(jīng)典知識(shí)蒸餾方案,自己試著想想應(yīng)該怎么做。
              對(duì)于精排環(huán)節(jié)來說,我覺得,知識(shí)蒸餾比較適合以下兩種技術(shù)轉(zhuǎn)換場(chǎng)景:
              一種是排序模型正在從非DNN模型初次向DNN模型進(jìn)行模型升級(jí);在超大規(guī)模數(shù)據(jù)場(chǎng)景下,從非DNN模型切換到DNN模型,切換成本和付出的時(shí)間因素可能比你預(yù)想得要高,尤其是線上服務(wù)環(huán)節(jié),切換到DNN模型導(dǎo)致大量增加在線服務(wù)機(jī)器成本,這對(duì)于很多公司來說是無法接受的。如果在做模型升級(jí)的時(shí)候采取知識(shí)蒸餾方案,導(dǎo)致的效果是:相對(duì)線上的非DNN模型,即使上一個(gè)蒸餾小模型,效果也可能是有提升的,同時(shí)在線服務(wù)占用資源能降下來(相對(duì)直接上個(gè)復(fù)雜DNN模型),在線服務(wù)速度快,所以可以明顯降低模型升級(jí)的成本,這樣可以相對(duì)容易地切換到DNN版本排序模型上來。
              第二種情況是:目前盡管線上已經(jīng)采用了DNN 排序模型,但是模型還非常簡(jiǎn)單,這個(gè)也有利用知識(shí)蒸餾優(yōu)化效果的空間;這種情形下,現(xiàn)有在線模型的服務(wù)速度可能是足夠快的,因?yàn)樵诰€服務(wù)模型還比較簡(jiǎn)單,即使換成Student小模型,在這方面估計(jì)也差不太多。但是,可以期待通過知識(shí)蒸餾提升線上模型的推薦質(zhì)量。我們可以離線訓(xùn)練一個(gè)復(fù)雜但是效果明顯優(yōu)于線上簡(jiǎn)單DNN排序模塊的模型作為Teacher,然后通過知識(shí)蒸餾,訓(xùn)練一個(gè)可以代替目前線上模型的Student小模型。如果這樣,是有可能在響應(yīng)速度不降的前提下,模型效果上有所提升的。所以,感覺這種情況也比較適合采用蒸餾模型。
              而對(duì)于其它情形,比如目前線上已有較為復(fù)雜的DNN排序系統(tǒng)的業(yè)務(wù)或者公司,至于是否要上知識(shí)蒸餾,則需要面臨一個(gè)權(quán)衡:采用知識(shí)蒸餾,線上服務(wù)模型從復(fù)雜模型切換成小模型,肯定可以明顯提高線上QPS,減少服務(wù)資源,效率提升會(huì)比較大;但是,有可能推薦質(zhì)量比線上的大模型會(huì)有下掉。所以,業(yè)務(wù)場(chǎng)景是否接受這種指標(biāo)的臨時(shí)下降?這個(gè)問題的答案決定了不同的選擇,在有些業(yè)務(wù)場(chǎng)景下,這是需要好好考慮考慮的。不同業(yè)務(wù)環(huán)境可能會(huì)作出不同的選擇。

          2. 模型召回以及粗排采用知識(shí)蒸餾

              在模型召回環(huán)節(jié),或者粗排環(huán)節(jié),采取知識(shí)蒸餾的方案,是非常自然的一個(gè)想法拓展,而且非常合算。目前,這塊基本看不到完全公開細(xì)節(jié)的技術(shù)資料,所以本文我重點(diǎn)談?wù)勗谶@塊可能采用的技術(shù),和幾位同學(xué)討論出若干可能的方案會(huì)列在后面,感興趣的同學(xué)可以嘗試一下,在這里是很容易作出收益的,所以特別值得關(guān)注與嘗試,相信這塊用好了,會(huì)對(duì)完成你的KPI有幫助。
          這里所謂的合算,怎么理解呢?
              因?yàn)檎倩鼗蛘叽峙怒h(huán)節(jié),作為精排的前置環(huán)節(jié),有自己承擔(dān)的獨(dú)特職責(zé),需要在準(zhǔn)確性和速度方面找到一個(gè)平衡點(diǎn),在保證一定推薦精準(zhǔn)性的前提下,對(duì)物品進(jìn)行粗篩,減小精排環(huán)節(jié)壓力。所以,這兩個(gè)環(huán)節(jié)本身,從其定位來說,并不追求最高的推薦精度,就算模型效果比精排差些,這也完全不成問題,畢竟在這兩個(gè)環(huán)節(jié),如果準(zhǔn)確性不足可以靠返回物品數(shù)量多來彌補(bǔ)。而模型小,速度快則是模型召回及粗排的重要目標(biāo)之一。這就和知識(shí)蒸餾本身的特點(diǎn)對(duì)上了,所以在這里用是特別合算的。
          那么,召回或者粗排怎么用蒸餾呢?
              如果我們?nèi)缟蠄D所示,用復(fù)雜的精排模型作為Teacher,召回或粗排模型作為小的Student,比如FM或者雙塔DNN模型等,Student模型模擬精排環(huán)節(jié)的排序結(jié)果,以此來指導(dǎo)召回或粗排Student模型的優(yōu)化過程。這樣,我們可以獲得滿足如下特性的召回或者粗排模型:
              首先,推薦效果好,因?yàn)镾tudent經(jīng)過復(fù)雜精排模型的知識(shí)蒸餾,所以效果雖然弱于,但是可以非常接近于精排模型效果;
              其次,Student模型結(jié)構(gòu)簡(jiǎn)單,所以速度快,滿足這兩個(gè)環(huán)節(jié)對(duì)于速度的要求;
              再次,通過Student模型模擬精排模型的排序結(jié)果,可以使得前置兩個(gè)環(huán)節(jié)的優(yōu)化目標(biāo)和推薦任務(wù)的最終優(yōu)化目標(biāo)保持一致,在推薦系統(tǒng)中,前兩個(gè)環(huán)節(jié)優(yōu)化目標(biāo)保持和精排優(yōu)化目標(biāo)一致,其實(shí)是很重要的,但是這點(diǎn)往往在實(shí)做中容易被忽略,或者因條件所限無法考慮這一因素,比如非模型召回,從機(jī)制上是沒辦法考慮這點(diǎn)的。這里需要注意的一點(diǎn)是:如果召回模型或者粗排模型的優(yōu)化目標(biāo)已經(jīng)是多目標(biāo)的,對(duì)于新增的模型蒸餾來說,可以作為多目標(biāo)任務(wù)中新加入的一個(gè)新目標(biāo),當(dāng)然,也可以只保留單獨(dú)的蒸餾模型,完全替換掉之前的多目標(biāo)模型,貌似這兩種思路應(yīng)該都是可以的,需要根據(jù)具體情況進(jìn)行斟酌選擇。
              由以上分析,可見,召回或粗排環(huán)節(jié)的知識(shí)蒸餾方案,看上去貌似是為召回和粗排環(huán)節(jié)量身定制的推薦系統(tǒng)優(yōu)化技術(shù)選項(xiàng),對(duì)于召回或者粗排優(yōu)化來說,應(yīng)該是必試的一個(gè)技術(shù)選項(xiàng)。
              下面我們討論下在推薦系統(tǒng)里,在各個(gè)環(huán)節(jié)采用知識(shí)蒸餾的可能的具體方法。精排蒸餾有三篇公開文獻(xiàn)可供參考,而召回或粗排方面的蒸餾技術(shù),很少見相關(guān)公開資料,所以后面列的多數(shù)是我和幾位同學(xué)討論的方案,除個(gè)別方法有實(shí)踐結(jié)果外,大多方法仍處于設(shè)想階段,目前并未落地,所以不能保證有效性,這點(diǎn)還需要注意。
          精排環(huán)節(jié)蒸餾方法

              目前推薦領(lǐng)域里,在精排環(huán)節(jié)采用知識(shí)蒸餾,主要采用TeacherStudent聯(lián)合訓(xùn)練(Joint Learning)的方法,而目的是通過復(fù)雜Teacher來輔導(dǎo)小Student模型的訓(xùn)練,將Student推上線,增快模型響應(yīng)速度。
              如上圖所示,所謂聯(lián)合訓(xùn)練,指的是在離線訓(xùn)練Student模型的時(shí)候,增加復(fù)雜Teacher模型來輔助Student,兩者同時(shí)進(jìn)行訓(xùn)練,是一種訓(xùn)練過程中的輔導(dǎo)。從網(wǎng)絡(luò)結(jié)構(gòu)來說,Teacher和Student模型共享底層特征Embedding層,Teacher網(wǎng)絡(luò)具有層深更深、神經(jīng)元更多的MLP隱層,而Student則由較少層深及神經(jīng)元個(gè)數(shù)的MLP隱層構(gòu)成,兩者的MLP部分參數(shù)各自私有。對(duì)于所有訓(xùn)練數(shù)據(jù),會(huì)同時(shí)訓(xùn)練Teacher和Student網(wǎng)絡(luò),對(duì)于Teacher網(wǎng)絡(luò)來說,就是常規(guī)的訓(xùn)練過程,以交叉熵作為Teacher的損失函數(shù)。而對(duì)于Student網(wǎng)絡(luò)來說,損失函數(shù)由兩個(gè)部分構(gòu)成,一個(gè)子項(xiàng)是交叉熵,這是常規(guī)的損失函數(shù),它促使Student網(wǎng)絡(luò)去擬合訓(xùn)練數(shù)據(jù);另外一個(gè)子項(xiàng)則迫使Student輸出的Logits去擬合Teacher輸出的Logits,所謂蒸餾,就體現(xiàn)在這個(gè)損失函數(shù)子項(xiàng),通過這種手段讓Teacher網(wǎng)絡(luò)增強(qiáng)Student網(wǎng)絡(luò)的模型泛化能力。也即:

              H是交叉熵?fù)p失函數(shù),  是Student模型的映射函數(shù),  是Ground Truth Label,  是Teacher的Logits,  是Student的Logits,  用于調(diào)節(jié)蒸餾Loss的影響程度。
              這個(gè)模型是阿里媽媽在論文“Rocket Launching: A Universal and Efficient Framework for Training Well-performing Light Net”中提出的,其要點(diǎn)有三:其一兩個(gè)模型同時(shí)訓(xùn)練;其二,Teacher和Student共享特征Embedding;其三,通過Logits進(jìn)行知識(shí)蒸餾。對(duì)細(xì)節(jié)部分感興趣的同學(xué)可以參考原始文獻(xiàn)。
              愛奇藝在排序階段提出了雙DNN排序模型,可以看作是在阿里的rocket launching模型基礎(chǔ)上的進(jìn)一步改進(jìn)。如上圖所示,Student和Teacher共享特征Embedding參數(shù)層,Student模型在損失函數(shù)中加入了擬合Teacher輸出階段的Logits子項(xiàng),這兩點(diǎn)和rocket launching是類似的。
              主要改進(jìn)有兩點(diǎn):首先,為了進(jìn)一步增強(qiáng)student的泛化能力,要求student的隱層MLP的激活也要學(xué)習(xí)Teacher對(duì)應(yīng)隱層的響應(yīng),這點(diǎn)同樣可以通過在student的損失函數(shù)中加子項(xiàng)來實(shí)現(xiàn)。但是這會(huì)帶來一個(gè)問題,就是在MLP隱層復(fù)雜度方面,Student和Teacher是相當(dāng)?shù)?,我們說過,一般知識(shí)蒸餾,老師要比學(xué)生博學(xué),那么,在這個(gè)結(jié)構(gòu)里,Teacher相比student,模型復(fù)雜在哪里呢?這引出了第二點(diǎn)不同:雙DNN排序模型的Teacher在特征Embedding層和MLP層之間,可以比較靈活加入各種不同方法的特征組合功能,通過這種方式,體現(xiàn)Teacher模型的較強(qiáng)的模型表達(dá)和泛化能力。
              愛奇藝給出的數(shù)據(jù)對(duì)比說明了,這種模式學(xué)會(huì)的student模型,線上推理速度是Teacher模型的5倍,模型大小也縮小了2倍。Student模型的推薦效果也比rocket launching更接近Teacher的效果,這說明改進(jìn)的兩點(diǎn)對(duì)于Teacher傳授給Student更強(qiáng)的知識(shí)起到了積極作用。更多信息可參考:雙 DNN 排序模型:在線知識(shí)蒸餾在愛奇藝推薦的實(shí)踐
          召回&粗排環(huán)節(jié)蒸餾方法


              上面介紹了阿里和愛奇藝在精排方面的兩個(gè)知識(shí)蒸餾應(yīng)用工作,目前知識(shí)蒸餾應(yīng)用在推薦領(lǐng)域的公開資料很少,雖說上面兩個(gè)工作是應(yīng)用在精排,目的是加快線上模型推理速度,但是稍微改進(jìn)一下,也可以應(yīng)用在召回模型以及粗排模型。

              假設(shè)我們打算使用上述方案改造召回或者粗排模型,一種直觀的想法是:我們基本可以直接參照rocket launching的方案稍作改動(dòng)即可。對(duì)于粗排或者召回模型來說,一般大家會(huì)用DNN雙塔模型建模,只需要將粗排或召回模型作為Student,精排模型作為Teacher,兩者聯(lián)合訓(xùn)練,要求Student學(xué)習(xí)Teacher的Logits,同時(shí)采取特征Embedding共享。如此這般,就可以讓召回或粗排模型學(xué)習(xí)精排模型的排序結(jié)果??焓衷?jīng)在AICon分享過在粗排環(huán)節(jié)采取上面接近rocket launching的蒸餾技術(shù)方案,并取得了效果。
              因雙塔結(jié)構(gòu)將用戶側(cè)和物品側(cè)特征分離編碼,所以類似愛奇藝技術(shù)方案的要求Student隱層學(xué)習(xí)Teacher隱層響應(yīng),是很難做到的。粗排尚有可能,設(shè)計(jì)簡(jiǎn)單網(wǎng)絡(luò)DNN結(jié)構(gòu)的時(shí)候不采取雙塔結(jié)構(gòu)即可,召回環(huán)節(jié)幾無可能,除非把精排模型也改成雙塔結(jié)構(gòu),可能才能實(shí)現(xiàn)這點(diǎn),但這樣可能會(huì)影響精排模型的效果。
              但是,問題是:我們有必要這么興師動(dòng)眾,為了訓(xùn)練召回或粗排的蒸餾模型,去聯(lián)合訓(xùn)練精排模型么?貌似如果這樣,召回模型對(duì)于排序模型耦合得過于緊密了,也有一定的資源浪費(fèi)。其實(shí)我們未必一定要兩者聯(lián)合訓(xùn)練,也可以采取更節(jié)省成本的兩階段方法。

          1. 召回蒸餾的兩階段方法

              在專門的知識(shí)蒸餾研究領(lǐng)域里,蒸餾過程大都采取兩階段的模式,就是說第一階段先訓(xùn)練好Teacher模型,第二階段是訓(xùn)練Student的過程,在Student訓(xùn)練過程中會(huì)使用訓(xùn)練好Teacher提供額外的Logits等信息,輔助Student的訓(xùn)練。
              私以為,精排環(huán)節(jié)貌似還是聯(lián)合訓(xùn)練比較好,而召回或粗排環(huán)節(jié)采取兩階段模式估計(jì)更有優(yōu)勢(shì)。為什么這么說呢?你可以這么想:如果我們的目的是希望訓(xùn)練一個(gè)小的Student精排模型,貌似沒有太大的必要采取兩階段訓(xùn)練過程,因?yàn)闊o論是聯(lián)合訓(xùn)練也好,還是兩階段訓(xùn)練也好,反正一大一小兩個(gè)模型都需要完整訓(xùn)練一遍,消耗的資源類似。而如果聯(lián)合訓(xùn)練,則還可以應(yīng)用特征embedding共享、隱層響應(yīng)學(xué)習(xí)等更多可選的技術(shù)改進(jìn)方案。所以貌似沒有太大必要改成兩階段的模式。
              但是,如果是召回模型或粗排模型作為Student,則情況有所不同。首先,比如隱層響應(yīng)等技術(shù)手段,本來召回或粗排Student模型就無法使用(粗排如果不用雙塔,而是簡(jiǎn)單DNN模型,還是可以的),所以聯(lián)合訓(xùn)練相對(duì)兩階段訓(xùn)練增加的好處不明顯。
              至于Student和Teacher特征Embedding共享,如果是在兩階段模式下,則可以改為使用Teacher訓(xùn)練好的特征Embedding初始化Student的特征,這樣貌似損失也不大,所以兩階段模式相對(duì)聯(lián)合訓(xùn)練模式,在效果方面并無明顯劣勢(shì)。另外,因?yàn)槲覀兿M倩鼗蛘叽峙拍P蛯W(xué)習(xí)精排模型,而一般而言,我們能夠拿到一個(gè)已經(jīng)訓(xùn)練好的精排模型,比如最近上線的精排模型,既然這樣,我們可以直接用當(dāng)前已訓(xùn)練好的精排模型,讓它把用于召回模型的訓(xùn)練數(shù)據(jù)跑一遍,給每個(gè)訓(xùn)練數(shù)據(jù)打上Logits信息,然后,就可以按照與聯(lián)合訓(xùn)練完全一樣的方式去訓(xùn)練召回蒸餾模型了,優(yōu)化目標(biāo)是Ground Truth子目標(biāo)和Logits蒸餾子目標(biāo)。
              上圖展示了這一過程。這樣做,明顯我們節(jié)省了精排Teacher的聯(lián)合訓(xùn)練迭代成本。不過,這種方法是否有效不確定,感興趣的同學(xué)可以嘗試一下,不過推論起來應(yīng)該是能保證效果的。
              上面的方法,還是模仿精排蒸餾方式,無非改成了相對(duì)節(jié)省資源的兩階段模式。這里我們關(guān)心另外一個(gè)問題:對(duì)于召回蒸餾Student模型來說,是否一定要優(yōu)化那個(gè)Ground Truth子目標(biāo)?這可能要分情況看。按理說,蒸餾模型帶上Ground Truth優(yōu)化目標(biāo)肯定效果要好于不帶這個(gè)子目標(biāo)的模型。如果我們的召回模型或者粗排模型是單目標(biāo)的,比如就優(yōu)化點(diǎn)擊,那么明顯還是應(yīng)該帶上Ground Truth優(yōu)化目標(biāo)。但是,事實(shí)上,很可能我們手上的召回模型或粗排模型已經(jīng)是多目標(biāo)的了,那么這種情況下,其實(shí)蒸餾Student模型就沒有太大必要帶Ground Truth優(yōu)化目標(biāo),因?yàn)槎嗄繕?biāo)已經(jīng)各自做了這個(gè)事情了。這種情況下,獨(dú)立優(yōu)化蒸餾目標(biāo),然后將其作為多目標(biāo)的一個(gè)新目標(biāo)加入召回或粗排模型比較合適。
              所以,我們下面介紹的方案,就拋掉Ground Truth優(yōu)化目標(biāo),單獨(dú)優(yōu)化蒸餾目標(biāo)。如果根據(jù)蒸餾Student模型是否需要參考Teacher提供的Logits信息來對(duì)方法進(jìn)行分類,又可以進(jìn)一步劃分為參考Logits信息的方案,和不參考Logits信息的方案。按理說,參考Logits信息效果應(yīng)該好些,但是,這樣Student仍然對(duì)Teacher有依賴,而不參考Logits信息的方案比較獨(dú)立,基本不需要精排模型的直接介入,所需信息直接可以在常規(guī)的推薦系統(tǒng)Log里拿到,實(shí)現(xiàn)起來更具簡(jiǎn)單和獨(dú)立性。而且,如果精排模型已經(jīng)是多目標(biāo)的,可能很難獲得那個(gè)Logits數(shù)值,但是我們能夠拿到精排模塊的排序結(jié)果,這意味著Student在優(yōu)化蒸餾目標(biāo)的時(shí)候,就已經(jīng)朝著多目標(biāo)進(jìn)行優(yōu)化了,是一種在召回或粗排進(jìn)行非精細(xì)化多目標(biāo)方向優(yōu)化的一種簡(jiǎn)潔手段,所以有額外的好處。如果出于上述目的,此時(shí)明顯用非Logits方案更從容。綜合而言,從效果考慮,應(yīng)該考慮引入Logits,從獨(dú)立性和簡(jiǎn)潔性角度,可以參考非Logits方案。這可能與現(xiàn)實(shí)場(chǎng)景相關(guān)。

          2. Logits方案

              在召回或者精排采用知識(shí)蒸餾,此時(shí),精排模型其實(shí)身兼二職:主業(yè)是做好線上的精準(zhǔn)排序,副業(yè)是順手可以教導(dǎo)一下召回及粗排模型。所以,其實(shí)我們?yōu)榱俗孴eacher能夠教導(dǎo)Student,在訓(xùn)練Student的時(shí)候,并不需要專門訓(xùn)練一遍Teacher精排模型,因?yàn)樗驮诰€上跑著呢。而且我們拋開了Ground Truth優(yōu)化子目標(biāo),所以不需要Teacher對(duì)訓(xùn)練數(shù)據(jù)都過一遍,而只需要多做一件事情:線上精排模型在輸出排序結(jié)果的時(shí)候,對(duì)于當(dāng)前判斷<User,Item,Context>實(shí)例,除了給出是否點(diǎn)擊等判斷外,只要把對(duì)應(yīng)優(yōu)化目標(biāo)的Logits數(shù)值輸出,并計(jì)入Log即可。這樣,召回或粗排模型可以直接使用訓(xùn)練數(shù)據(jù)中記載的Logits,來作為Student的訓(xùn)練數(shù)據(jù),訓(xùn)練蒸餾模型,上圖展示了這一過程。所以,綜合看,這種Logits方案,是更節(jié)省計(jì)算資源的方案。當(dāng)然,上述都是我的個(gè)人推論,實(shí)際效果如何,還需要做對(duì)比實(shí)驗(yàn)才能說明問題。



          3. Without-Logits方案

              另外一類方法可以進(jìn)一步減少Student對(duì)Teacher的依賴,或適用于無法得到合理Logits信息的場(chǎng)合,即Student完全不參考Logits信息,但是精排作為Teacher,怎么教導(dǎo)Student呢?別忘了,精排模型的輸出結(jié)果是有序的,這里面也蘊(yùn)含了Teacher的潛在知識(shí),我們可以利用這個(gè)數(shù)據(jù)。也就是說,我們可以讓Student模型完全擬合精排模型的排序結(jié)果,以此學(xué)習(xí)精排的排序偏好。我們知道,對(duì)于每次用戶請(qǐng)求,推薦系統(tǒng)經(jīng)過幾個(gè)環(huán)節(jié),通過精排輸出Top K的Item作為推薦結(jié)果,這個(gè)推薦結(jié)果是有序的,排在越靠前的結(jié)果,應(yīng)該是精排系統(tǒng)認(rèn)為用戶越會(huì)點(diǎn)擊的物品。
              那么,我們其實(shí)可以不用Logits,粗排或者召回環(huán)節(jié)的Student的學(xué)習(xí)目標(biāo)是:像精排模型一樣排序。這時(shí),精排模型仍然是Teacher,只是傳給召回或粗排模型的知識(shí)不再是Logits,而是一個(gè)有序的列表排序結(jié)果,我們希望Student從這個(gè)排序結(jié)果里面獲取額外的知識(shí)。如果這樣的話,對(duì)于目前的線上推薦系統(tǒng),不需要做任何額外的工作,因?yàn)榕判蚪Y(jié)果是會(huì)記在Log里的(也可以用推薦系統(tǒng)在精排之后,經(jīng)過Re-ranker重排后的排序結(jié)果,這樣甚至可以學(xué)習(xí)到一些去重打散等業(yè)務(wù)規(guī)則),只要拿到Log里的信息,我們就可以訓(xùn)練召回或粗排的Student蒸餾模型。
              也就是說,對(duì)于召回或者粗排模型來說,它看到了若干精排的排序結(jié)果列表,精排模型的知識(shí)就蘊(yùn)含在里面,而這可以作為Student模型的訓(xùn)練數(shù)據(jù)來訓(xùn)練蒸餾模型。很明顯,這是一個(gè)典型的Learning to Rank問題。我們知道,對(duì)于LTR問題,常見的優(yōu)化目標(biāo)包括三種:Point Wise、Pair Wise和List Wise。于是,我們可以按照這三種模式來設(shè)計(jì)召回模型或粗排模型的蒸餾學(xué)習(xí)任務(wù)。其中,下面文中提到的Point Wise方式我們已親試有效,至于Pair Wise和List Wise蒸餾,仍需實(shí)驗(yàn)才能證明是否有效。
          Point Wise蒸餾

              在Point Wise優(yōu)化目標(biāo)下理解召回模型蒸餾,就是說,我們把精排模型的有序輸出結(jié)果作為訓(xùn)練數(shù)據(jù),把學(xué)習(xí)目標(biāo)看作一個(gè)二分類問題,通過這種方式試圖學(xué)習(xí)精排模型的排序偏好。這種情況下,分類模型的正負(fù)例如何設(shè)定呢?我們不能把精排模型輸出結(jié)果列表里用戶行為過的Item作為正例,因?yàn)檫@樣你等于在學(xué)比如點(diǎn)擊或者互動(dòng)等用戶行為模型,而不是在學(xué)精排模型的排序偏好。一般而言,可以這么做:假設(shè)精排每次返回N個(gè)結(jié)果,我們?nèi)×斜砬癟op K的排序靠前的結(jié)果,將其指定為正例,位置K之后的例子,作為負(fù)例。意思是通過排名最高的一部分?jǐn)?shù)據(jù),來學(xué)習(xí)精排模型的排序偏好。這樣,我們就可以拿這些非標(biāo)注的排序結(jié)果來訓(xùn)練召回模型。當(dāng)然,這里的K是個(gè)超參,怎么定更合理,可能需要實(shí)驗(yàn)來確定。上圖展示了這一做法。
              通過這種方式,我們就可以讓召回模型從精排模型的排序列表中學(xué)到排序偏好知識(shí),達(dá)成知識(shí)蒸餾的目標(biāo)。這種做法,有個(gè)可以改進(jìn)的點(diǎn):上述切分正負(fù)例的方法,并未強(qiáng)調(diào)物品排序位置。比如假設(shè)K值取5,就是排名前5的物品作為正例,之后的作為負(fù)例。正例中排名Rank 1的物品,和排名Rank 4的物品,都各自作為一條正例,沒有差別。但是,我們知道,Rank 1應(yīng)該排名比Rank 4更高,但模型訓(xùn)練過程并沒有利用這個(gè)信息。我們可以通過對(duì)正例引入Loss Weight的簡(jiǎn)單處理方法來引入這一信息,比如引入一個(gè)跟位置相關(guān)的Weight函數(shù):

              其中,Rank Position是Item的排名名次,將其作為變量引入函數(shù),以此映射函數(shù)的數(shù)值作為正例的Loss Weight,負(fù)例Loss Weight權(quán)重與常規(guī)訓(xùn)練一樣,可認(rèn)為缺省Loss Weight權(quán)重為1。在具體設(shè)計(jì)這個(gè)函數(shù)的時(shí)候,指導(dǎo)思想是:希望這個(gè)函數(shù)能做到,排名越靠前的正例,對(duì)應(yīng)的Loss Weight越大。將這個(gè)Loss Weight引入損失函數(shù)中,就可以讓模型更關(guān)注排名靠前的物品。比如,我們可以這么定義函數(shù):

              這里,Position是排名位置,比如Rank Position=1,則Position=1;Rank Position=4,則Position=4;通過這種定義,就能使得排名靠前的正例,對(duì)應(yīng)的Loss Weight越大,而a可以作為調(diào)節(jié)權(quán)重,來放大或者縮小排名位置的影響。當(dāng)然,這里還可以引入其它各種花樣的Loss Weight定義方法。
              熱門微博嘗試了上述思路FM版本的蒸餾召回模型(多目標(biāo)召回模型基礎(chǔ)上增加蒸餾召回目標(biāo)),線上AB測(cè)試效果,在時(shí)長(zhǎng)、點(diǎn)擊、互動(dòng)等多個(gè)指標(biāo)都有2+%到6+%之間的不同程度的提升作用,目前正在嘗試更多變體模型。
          Pair Wise蒸餾

              如果我們用Pair Wise Loss的方式來看待召回模型優(yōu)化問題,可以這么思考:精排的排序結(jié)果是有序列表,在列表內(nèi)隨機(jī)任意抽取兩個(gè)Item,都能維持序關(guān)系。那么很明顯,我們可以構(gòu)造成對(duì)的訓(xùn)練數(shù)據(jù),以Item為正例,以排在Item后面任意某個(gè)Item作為負(fù)例,以此方式構(gòu)造訓(xùn)練數(shù)據(jù)來訓(xùn)練模型。在推薦領(lǐng)域,最常用的Pair Wise Loss是BPR損失函數(shù),于是我們可以如法炮制,如上圖所示,假設(shè)對(duì)于排在第三位的Item作為正例,可以抽取排名在其之后的Item,構(gòu)造足夠多的成對(duì)訓(xùn)練數(shù)據(jù),以此目標(biāo)來優(yōu)化召回模型,使得模型可以學(xué)會(huì)Item間的序列關(guān)系。


              對(duì)<Pos,Neg>成對(duì)的訓(xùn)練數(shù)據(jù),BPR損失函數(shù)希望某個(gè)預(yù)測(cè)系統(tǒng)能夠?qū)φ牡梅忠哂谪?fù)例的得分,具體計(jì)算方法如上圖所示,因?yàn)槭莻€(gè)基礎(chǔ)概念,此處不展開介紹。
              論文Ranking Distillation: Learning Compact Ranking Models With High Performance for Recommender System 提出了使用Point Wise和Pair Wise Loss來使用Teacher的輸出結(jié)果訓(xùn)練Student的方法,文中說貌似上面這種BPR的Loss會(huì)導(dǎo)致Student訓(xùn)練不穩(wěn)定有時(shí)不收斂,所以這種模式還需要進(jìn)一步探索成功路徑。Ranking Distillation里采用的Point Wise Loss方式是比較成功的,不過和上文介紹的Point Wise有個(gè)區(qū)別:對(duì)于Teacher輸出的結(jié)果,選擇Top K的Item作為正例,沒有選取負(fù)例;另外Student引入了Ground Truth作為L(zhǎng)oss子項(xiàng)。文中還提出了幾種比較有意思的Position Loss Weight方法。對(duì)具體細(xì)節(jié)感興趣的同學(xué)可以參考。
          List Wise蒸餾

              Point Wise Loss將學(xué)習(xí)問題簡(jiǎn)化為單Item打分問題,Pair Wise Loss對(duì)能夠保持序關(guān)系的訓(xùn)練數(shù)據(jù)對(duì)建模,而List Wise Loss則對(duì)整個(gè)排序列表順序關(guān)系建模。List Wise Loss經(jīng)常被用在排序問題中,但是有個(gè)現(xiàn)實(shí)困難是訓(xùn)練數(shù)據(jù)不好做,因?yàn)榕判蛄斜砝锩總€(gè)Item的價(jià)值需要人工標(biāo)注。

              我們來考慮下召回蒸餾模型的List Wise Loss優(yōu)化目標(biāo)怎么做的問題。既然我們能拿到大量精排給出的有序列表,貌似我們是不缺訓(xùn)練數(shù)據(jù)的,但是這里隱藏著個(gè)潛在的問題,問題等會(huì)我們?cè)僬f。我們先說個(gè)應(yīng)用案例,Instagram的推薦系統(tǒng)在初排階段采用知識(shí)蒸餾的方法,使用精排作為Teacher來指導(dǎo)Student的優(yōu)化,Student的優(yōu)化目標(biāo)用的是NDCG,這是一種非常常用的List Wise Loss函數(shù),對(duì)Instagram推薦系統(tǒng)感興趣的同學(xué)可以參考文章:Instagram 推薦系統(tǒng):每秒預(yù)測(cè) 9000 萬個(gè)模型是怎么做到的?
              不過遺憾的是,上述文章并未說明是具體怎么做的,只能靠我們自己來摸索一下。其實(shí)細(xì)想一下,在這里用NDCG來學(xué)習(xí)精排輸出的有序列表,這面臨待解決的問題:用NDCG是有前提條件的,有序列表中的每個(gè)Item,都需要帶有一個(gè)價(jià)值分。比如對(duì)于搜索排序來說,最相關(guān)Item是5分,次相關(guān)Item是4分,類似這種分?jǐn)?shù),這一般是人工標(biāo)注上的,而List Wise Loss就希望排序系統(tǒng)能夠?qū)⒘斜碚w獲得的價(jià)值分最大化。上面我們提到存在的問題就是:精排系統(tǒng)只給出了Item之間的排序關(guān)系,每個(gè)Item并沒有提供對(duì)應(yīng)的價(jià)值分。

              那么,如果想用NDCG或者類似的其它List Wise 損失函數(shù),怎樣才能得到列表內(nèi)每個(gè)Item的價(jià)值分呢?人工打標(biāo)注顯然是不現(xiàn)實(shí)的。這里,感覺可以利用一下精排系統(tǒng)輸出的Logits信息,假設(shè)我們可以設(shè)計(jì)一個(gè)函數(shù):

              這個(gè)函數(shù)以Logits分?jǐn)?shù)為輸入變量,將其映射到比如1分到5分幾檔上,Logits得分越大,則對(duì)應(yīng)檔次分越高。如果我們能做到這點(diǎn),就可以使用List Wise損失函數(shù)來訓(xùn)練召回或粗排模型了。這個(gè)函數(shù)定義有各種可能的方法,這里不展開,各位有興趣的同學(xué)可以試試。
              如果我們想更簡(jiǎn)單點(diǎn),不用Logits分?jǐn)?shù),那么有更加簡(jiǎn)單粗暴的方法,比如強(qiáng)行將有序列表排在Top 5的Item設(shè)置成5分,排在6到10位置的Item賦予4分…..類似這種。這等價(jià)于這么定義F函數(shù)的:

              這個(gè)公式充分展示了工業(yè)界的簡(jiǎn)單暴力算法美學(xué),我相信類似的公式充斥于各大公司的代碼倉庫角落里。
          聯(lián)合訓(xùn)練召回、粗排及精排模型的設(shè)想
              如果我們打算把知識(shí)蒸餾這個(gè)事情在推薦領(lǐng)域做得更徹底一點(diǎn),比如在模型召回、粗排以及精排三個(gè)環(huán)節(jié)都用上,那么其實(shí)可以設(shè)想一種“一帶三”的模型聯(lián)合訓(xùn)練方法。


              如上圖所示,我們可以設(shè)計(jì)一個(gè)很復(fù)雜但是效果很好的排序模型作為Teacher,然后和召回、粗排、精排三個(gè)Student聯(lián)合訓(xùn)練,精排Student可以使用Logits以及隱層特征響應(yīng)等各種手段優(yōu)化,追求效果好前提下的盡可能速度快,召回和粗排Student則追求在模型小的前提下追求效果盡可能好。因?yàn)榕判騎eacher比較復(fù)雜,所以能夠提供盡可能好的模型效果,通過它來帶動(dòng)三個(gè)環(huán)節(jié)蒸餾模型的效果,而模型速度快則是蒸餾方法的題中應(yīng)有之意。
              這樣做有不少好處,比如可以一次訓(xùn)練,多環(huán)節(jié)收益;再比如可以最大程度上保持推薦系統(tǒng)各個(gè)環(huán)節(jié)的目標(biāo)一致性等;做起來又不太難,所以看上去是個(gè)可行的方案。
              最后,歸納下全文,推薦系統(tǒng)在各個(gè)環(huán)節(jié)采取知識(shí)蒸餾方法,是可能達(dá)到提升推薦質(zhì)量的同時(shí),提高推薦系統(tǒng)速度的,一舉兩得,比較容易產(chǎn)生效益,所以是值得深入探索及應(yīng)用的。

          致謝:上面列的很多想法是在和幾位同學(xué)的討論中形成或完善的,感謝微博機(jī)器學(xué)習(xí)佘青云、王志強(qiáng)等同學(xué)提出的思路和建議。

          參考資料
          • 知乎:https://zhuanlan.zhihu.com/p/143155437


          國(guó)產(chǎn)小眾瀏覽器因屏蔽視頻廣告,被索賠100萬(后續(xù))

          年輕人“不講武德”:因看黃片上癮,把網(wǎng)站和786名女主播起訴了

          中國(guó)聯(lián)通官網(wǎng)被發(fā)現(xiàn)含木馬腳本,可向用戶推廣色情APP

          張一鳴:每個(gè)逆襲的年輕人,都具備的底層能力


          關(guān)


          ,學(xué),西學(xué)學(xué)運(yùn)營(yíng)護(hù)號(hào),質(zhì),結(jié)識(shí),關(guān)[],學(xué)習(xí)進(jìn)!


          瀏覽 54
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧美大香蕉性爱 | 香蕉视频18 | 亚洲小学生妹三级毛片视频大全 | 日韩一区二区三区无码视频 | 青青草国产成人AV片免费 |