TIANCHI天池-OGeek算法挑战赛-完整方案及代码(亚军)
首先很幸運拿到TIANCHI天池-OGeek算法挑戰賽大賽的亞軍,同時非常感謝大佬隊友的帶飛,同時希望我的分享與總結能給大家帶來些許幫助,并且一起交流學習。(作者:王賀,知乎:魚遇雨欲語與余)
賽題鏈接:
https://tianchi.aliyun.com/competition/entrance/231688/introduction
Github鏈接:
https://github.com/fanfanda/OGeek-Competition
本文目錄
賽題分析
數據分析
賽題難點
特征工程
算法模型
思考總結
1. 賽題分析
此次賽題來自OPPO手機搜索排序優化的一個子場景,并做了相應的簡化,意在解決query-title語義匹配的問題。簡化后,本次題目內容主要為一個實時搜索場景下query-title的ctr預估問題。
賽題特征:prefix(用戶輸入,query前綴),query_prediction(根據當前前綴,預測的用戶完整需求查詢詞,最多10條;預測的查詢詞可能是前綴本身,數字為統計概率),title(文章標題),tag(文章內容標簽)
提供數據:初賽復賽一致, 訓練數據:200萬 驗證數據:5萬 測試數據1:5萬 測試數據2:25萬
評估指標:本次競賽的評價標準采用F1 score 指標,正樣本為1,公式如下:
2. 數據分析
這一部分將會對部分數據進行分析,另外獲取部分特征的點擊率分布情況判斷特征效果,看分布可以有一個很好的初步驗證作用。
這四個圖是prefix在各自數據集的百分比統計,并以訓練集中出現頻次top10的prefix畫出了每個數據集的占比情況,可以發現valid與testa和testb的分布相似,說明valid與testa和testb的查詢時間比較接近,作為驗證集線下比較可信。
此處更近一步分析了train和testa、testb有較大的差異性。
我們對數據特點進行了分析。發現,
1.用戶有可能會拼錯prefix,如‘抖音’拼寫成‘枓音’,分析發現,使用prefix的pinying會比中文大幅度減少不同值的出現次數,當然也有一部分不是拼寫錯誤的,如痘印,所以最后我們中文和拼音的兩部分特征都使用了。
2.由于這是實時性比較強的搜索場景,分析發現,測試集中會有很大一部分prefix和title未在訓練集中出現過。
除基礎數據分析外,我們還分析了部分特征,比如prefix的長度特征,其用戶輸入prefix越詳細,整體CTR也隨之提高,其他特征的長度也有類似的趨勢。
另外,相似度特征是非常重要的特征,prefix和title越相似度,點擊的可能就越高。
3. 賽題難點
經過上面的分析以及對業務的理解,本賽題有什么難點呢?對此我們總結了五點:
沒有用戶/沒有時間的信息,因此無法對用戶建模,對于同一個query,不同人不同時間段都會有不同的反應。
實事熱點轉移快,訓練集中點擊率高的,測試集中不一定高。
訓練集和測試集的分布不是單純的按照時間,因為一些明顯的熱搜詞訓練集中沒有,但是驗證集和測試集里面大量存在。這顯然不合理的,所以我們認為,主辦方數據抽樣的時候,過濾了該詞語。
因為是實時性比較強的搜索場景,因此面對新出現的title如何處理?由于同樣的query-title,最終都會被模型預測成相同的標簽,模型對于高頻新詞的點擊率均值的把握,成為了關鍵點。
用戶的明顯拼寫錯誤query,例如劉覽器這種如何處理?
4. 特征工程
這里對CountVector的特征構造進行展示,CountVector特征在復賽提升也是非常大的。
# CountVectorizer data = data_df[['prefix', 'query_prediction', 'title', 'label']] data.replace('nan',np.nan,inplace=True) data['query_prediction'].fillna('{}',inplace=True) data['title'].fillna('-1',inplace=True) # prefix,title,query_prediction jieba分詞 def get_cv_feature(dt):df = pd.DataFrame()for item in ['prefix', 'title']:print(item)stat = pd.DataFrame()stat[item] = dt[item].drop_duplicates().valuesstat[item+'_jieba'] = stat[item].apply(lambda x:' '.join(jieba.cut(str(x), cut_all=False)))df[item+'_jieba'] = pd.merge(dt,stat,how='left',on=item)[item+'_jieba']stat = pd.DataFrame()item = 'query_prediction'print(item)stat[item] = dt[item].drop_duplicates().valuesdef getFeature(x):dct = json.loads(x)lst = []for k in dct.keys():lst.extend(jieba.cut(k,cut_all=False))return ' '.join(lst)stat['query_prediction_jieba'] = stat['query_prediction'].apply(getFeature)df[item+'_jieba'] = pd.merge(dt,stat,how='left',on=item)[item+'_jieba']return df df = get_cv_feature(data) from sklearn.feature_extraction.text import CountVectorizer from scipy import sparse cntv=CountVectorizer() data['label'] = data['label'].astype(int) vector_feature = ['prefix_jieba','query_prediction_jieba','title_jieba'] train_index = data[data['label']>=0].index.tolist() test_index = data[data['label']==-1].index.tolist() train_sp = pd.DataFrame() test_sp = pd.DataFrame() for feature in vector_feature:print(feature)cntv.fit(df[feature])train_sp = sparse.hstack((train_sp,cntv.transform(df.loc[train_index][feature]))).tocsr()test_sp = sparse.hstack((test_sp,cntv.transform(df.loc[test_index][feature]))).tocsr() print(train_sp.shape) print(test_sp.shape)相似度特征:prefix,title分別構造與query_prediction中每個key的相似度),并統計max,std,mean相似度。更進一步,統計top3,top5相似度的max,std,mean。
這些也是CTR問題傳統特征,同時對于這些特征的構造也是直接照辦之前的開源
魚遇雨欲語與余:2018騰訊廣告算法大賽總結/0.772229/Rank11
鏈接:https://zhuanlan.zhihu.com/p/38034501
由于賽題的特殊性,給了我們驗證集,通過觀察訓練集和驗證集的數據,我們發現存在熱點轉移的情況,例如關于某個明星,title 1是高熱點轉換網頁,可是到了驗證集中,這位明星的高熱點title是另外的一些網頁,說明實時熱點性比較強。因此我們對CTR的使用方法進行如下調研。
我們這邊采用了多種方式來防止過擬合,分別是多折交叉提取特征,平滑,以及采樣。
從表格中(5)可以看出,不使用五折交叉提取特征,訓練集的auc比驗證集的auc高很多,這就非常容易過擬合,導致線上結果很差,
(2)->(3)的過程就是相差了一個平滑,從而導致訓練集和驗證集上的auc都有所下降;此外,在我們的方法中加入了0.5的采樣,是為了使得訓練集和驗證集結果都不會過擬合。
上表(4)所示,對訓練集和驗證集均加入0.5的采樣之后,訓練集和驗證集的auc都會有所降低,當然對非常近的數據可能不利,但是對訓練集和測試集相隔比較遠的數據,隨熱點的轉移,CTR也會有所改善。
經過調研,我們使用0.5sample構造CTR特征,主要目的是目的是為了削弱ctr的特征重要度。
5. 算法模型
對于此次比賽我們對傳統機器學習模型以及深度模型都進行了嘗試。
TextCNN是經典的文本特征提取網絡,TextCNN Concat模型 輸入是tag,prefix,title,query_prediction(query_prediction對其進行拆分成10條,查詢詞為文本,查詢詞概率為權重)+特征工程中的統計特征, 接著將所有基礎的文本特征通過TextCNN來提取,非文本特征通過全連接層來提取,上述幾部分結合作為最終的特征層。由于模型過于簡單,并沒有特征之間(title,prefix)的深層次關聯,導致效果很一般。
因為只用TextCNN結構的網絡缺少prefix和title之間相似度的衡量,所以另外加了孿生網絡或偽孿生網絡來度量prefix和title之間相似度,以及prefix和query,title和query之間的相似度,并同樣加入統計概率作為權重
實驗結果發現,由于prefix和title的長度有一些差別,反而用偽孿生網絡比孿生網絡取得了更好一些的效果,所以在上述模型中,prefix,title和query_prediction中并沒有用共享權值(偽孿生網絡)。該模型結合了TextCNN,DeepFM,AFM等相關操作。
具體流程如下: 輸入分為兩部分,對于prefix,title和query_prediction進行TextCNN操作提取文本特征,tag和統計特征通過全連接層獲取對應的Embedding特征。
接著一部分是DeepFM模型,來獲取淺層特征和交叉特征,其中query_prediction的統計概率作為query文本向量的權重。
另外一部分是AFM相關操作,就是Bi-Interaction Pooling && Attention,對每兩兩Field的文本特征向量進行交叉,由于不同文本向量交叉的特征重要性不同,所以此處加入Attention,簡單來說就是對不同文本向量交叉的特征加權平均得到向量再放入Deep層進行更深層次的訓練。
主要進行了以上幾種深度學習模型,經過試驗對比,嘗試3能取得最好的效果,但由于數據量不是特別大,并沒有取得比LightGBM模型更好的效果,雖然該模型與LightGBM模型融合有所提高,但是作為NN模型在200萬規模的數據集上穩定性不夠強,結果值會產生一定的波動,且模型受限于2個,所以最終提交的成績并沒有使用該模型。
我們最終融合方案也比較簡單,主要進行加權融合,權重的確定看的是線下分數。
6. 思考總結
優點:
能夠對數據和業務經過細致的分析,挖掘更深層次的特征,更好的描述實體關系。
在模型方面僅使用穩定性比較高的LightGBM,并且具有很好的解釋性。
從特征提取到模型訓練僅使用三個小時完成,可以更高效的生成結果。
單模型取得top2的成績,從特征提取到模型訓練可以短時間完成。
不足:
為了保證模型的泛化性沒有對特征集合進行精細選擇,從而損失一定的準確性。
沒有構造出較大差異性的第二模型,導致最終成績在單模0.7486的成績上未能
獲得很大的提升。
歡迎指正與交流,有問題直接加作者qq418811687。
Github鏈接:
https://github.com/fanfanda/OGeek-Competition
可以“閱讀原文”進入作者知乎查看。
請關注和分享↓↓↓?
機器學習初學者
QQ群:727137612
(注意:本站有7個qq群,加入過任何一個的不需要再加)
本站的知識星球ID:92416895
往期精彩回顧
良心推薦:機器學習入門資料匯總及學習建議(2018版)
黃海廣博士的github鏡像下載(機器學習及深度學習資源)
吳恩達老師的機器學習和深度學習課程筆記打印版
機器學習小抄-(像背托福單詞一樣理解機器學習)
首發:深度學習入門寶典-《python深度學習》原文代碼中文注釋版及電子書
科研工作者的神器-zotero論文管理工具
機器學習的數學基礎
機器學習必備寶典-《統計學習方法》的python代碼實現、電子書及課件
吐血推薦收藏的學位論文排版教程(完整版)
機器學習入門的百科全書-2018年“機器學習初學者”公眾號文章匯總
Python環境的安裝(Anaconda+Jupyter notebook+Pycharm)
總結
以上是生活随笔為你收集整理的TIANCHI天池-OGeek算法挑战赛-完整方案及代码(亚军)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: NLP研究方向的「情感分析领域」的简单调
- 下一篇: 深入了解数据人才 | 中国数据人才白皮书