FaceBook: Text Tag Recommendation
Text Tag Recommendation
--------2013/12/20
一: 背景
Kaggle上 facebook招聘比赛III。
任务要求是给定文本中抽取关键词。这里称作tag吧。
训练集是Stack Exchange sites上面的大量问答文本,每一个post上面有网页的title ,body, 用户打的tags。
示比例如以下:
測试集是也是相同的文本信息,可是没有tags,这次比赛的任务就是让參赛者从文本中预測出文本的tags,比方上面的java,unit-testing....
二: 评估指标
F1-score= 2*(precision *recall)/(precision+ recall)
这里的问题是 任务是没有告诉你文本的tags数量。假设你预測tags数量过多,precision就会非常低,可是,recall相对高点。这里的任务,预測tags数量也是非常重要的一方面。
三:训练集和測试集数据分布
训练集有600w+的文本,tags数量1-5,训练集合中tags数量是4w+。
測试集合大约200w+。
四: tag 预測推荐算法
1: 数据预处理
最開始时候我从文本中剔除掉停用词和对词进行词干提取。可是效果没有提升。后来,我放弃停止词和词干的处理。
在progamming中有一些停止词还是有价值的。
同一时候我把类似这种词: opt/lib/unix 分开成opt,lib, unix等等。
Title所有信息。body是抽取当中text信息。
2: cross-validation
从600w+训练样本中抽取前100w样本做cv训练集。接着从取10w样本作为cv 測试集(事实上从取1w cv測试集和10w測试集评估结果区别不大)。
3:训练模型
3.1 文本语料
从训练样本中计算词term的词频字典,term-tag共同出现频率词典。
训练样本的文本信息仅仅包括title信息,没有body信息,一方面大量训练样本已包括足够
多的文本语料,而body含有非常多噪音数据。增加训练样本中。会造成预測F1值减少。
文本语料中採用2-grams和1-grams。相对仅仅用1-grams,F1在測试集上表现能提高0.02的精度。
去除掉一些低频词,低频tag,高频词。
低频的,我们觉得不可靠。
def is_pass_record(prob_term_1,prob_target_1,prob_term_1_target_1,):
if prob_term_1_target_1 <1e-5:
return 1
if prob_term_1 < 0.00001 or prob_target_1< 0.00001 or prob_term_1 > 0.1 :
return 1
return 0
3.2 计算单词和tag的相关性得分
(1)互信息相关得分
Mutual_Score(term,.tag) = P(tag| term) -P(tag)
(2) z-score相关得分:
Z_Score(term, tag) =
(3) Ensemble 相关得分
先对Mutual_Score 和Z_Score进行归一化:
Ensemble过程中mutual score 的权重分配是0.7 和 z-score的权重是0.3。
(4)词的权重
依据训练样本。计算词的权重。不同单词,它关联的tags是否是终于预測的tag的重要程度不一样。
方法有两种:
方法1:tf-idf值作为单词的重要性值。
方法2: entropy值作为词重要性
依据上面得到词频和词-tag频值,能够计算Wj值
同一时候归一化中分母换成norm-2 :
终于採用了entropy值作为词的权重。
4: 预測模型
4.1 预測样本文本信息
预測文本信息主要是通过get_ensemble_title_and_body(title, body)函数得到的。综合利用title和body文本信息。
def extract_body(body):
body_term = body.split()
body_li = []
body_li.extend(body_term[:20])
body_li.extend(body_term[-20:-1])
text = ' '.join(body_li)
return text
def get_ensemble_title_and_body(title, body):
title_w = 5
doc = (title + ' ') * title_w + body
return doc
4.2 预測
(1)通过4.1获得每一个post的文本信息,根本文本中单词的权重和单词-tag关联性预測tags:
(2)获取得分最高的前5个tags。
pred_tags = [[tag ,w] for tag, w in pred_tags_dict.iteritems()]
pred_tags = heapq.nlargest(5, pred_tags, key=lambda x: x[1])
(3)预測终于tag数目
依据pred_tags的tag得分。把低得分的tag去掉。
Threshold设定为0.7
def get_estimate_tags_num_by_association_prob(pred_tags):
threshold = 0.7
i = 0
sum_w = 0
total = np.sum([item[1] for item in pred_tags])
for item in pred_tags:
sum_w += item[1]
i +=1
if sum_w > threshold * total:
break
return i
这一步提升非常明显,提升0.03左右。
(4)cv结果
cv 10w结果大约在0.508。
precision: 0.505054166667
recall: 0.511442333333
F1-Score: 0.508228176801
(5)最后提交
这次比赛的的測试集中大约有119w的測试样本在训练集合中出现。约占整体样本的60%。
所以,第一步从測试集中把这119w样本找出来,用训练集中相应的tag预測。剩下40%的样本用上面的说的关联预測算法来做。
找相同文档的算法:
给每一个训练集单词建立倒排索引(这次把训练样本中去除停用词和词干处理。且是binary索引,不考虑tf-idf)。
Kaggle 上leaderboard上。我是最后2周才增加的(2013/12/08提交第一次结果。2013/12/20 比赛结束)。提交了7个结果,结果为0.72,(最高是0.81)
排名是 93, 总的队伍数目是367. 大约25% 左右。这里说明下,0.72相应的的cv结果仅仅有0.39左右。
所以,我在比赛结束后的优化结果是cv是0.50,相信leaderboard上的结果会有相对较高的提升,兴许加上结果, 结果是
五:总结
这次kaggle比赛。对text挖掘有了比較不错的提高,在实验中,试验了非常多方案。比方KNN,topic model。
KNN的速度太慢,即使在建立tf-idf倒排索引的情况下。依旧满足不了需求,同一时候在这次比赛中knn精度也没什么好的表现,值得提到的是,对于类似文本的寻找算法,能够借鉴Wand算法来提升速度,这也是这个数据集兴许能够再做的地方,text去重性能计算。Topic model是一个组粒度的预測方法。对于本次样本中基本上都是program 文本,所以这种粗粒度的预測方法效果非常差。
能够总结一句话:通过实验,我们才干知道什么方法才是可行的。什么是不可行的。
六 : 參考文献:
[1] http://www.kaggle.com/c/facebook-recruiting-iii-keyword-extraction
[2] Stanley C, Byrne M D. Predicting Tags for StackOverflow Posts[J].
[3] 司宪策. 基于内容的社会标签推荐与分析研究 [D][D]. 北京: 清华大学计算机科学与技术系, 2010.
[4] Eisterlehner F, Hotho A, Jäschke R. ECML PKDD Discovery Challenge 2009 (DC09)[J]. CEUR-WS. org, 2009, 497.
posted on 2019-03-28 15:18 xfgnongmin 阅读(280) 评论(0) 编辑 收藏 举报