M. Tong's Neverland

Quora ML Challenge比赛小记

| Comments

今年7月份的时候,Quora借助Hackerrank这个平台开展了一个针对机器学习的Codesprint比赛 ,sprint的跨度是8小时。我在sprint中最后的排名是第9。后来Quora在短赛程的sprint之外,又设置了一个长度为一周的加长版赛程(同一套题目)。sprint中排名较高的选手大部分在周赛中对答案做了改进,期间也有一些新的选手加入,在最后hidden test set的测试中,我的排名是第六位。 这其实是我第一次参加这类比赛,所以觉得应该记录一下。

如果对机器学习类比赛感兴趣的话,Kaggle是另一个很好的平台。KDD Cup 2013就已经放到Kaggle上举行了。同时像Facebook这类公司也通过Kaggle上举办比赛来挖掘人才,其实Quora办这个比赛也是有这个意思的。Quora在Hackerrank的这次比赛和Kaggle上的比赛还是有一些不同的地方:

  • Kaggle只需要提交你的预测结果,Hackerrank上要提交可运行的代码。因此相比来说,在Kaggle上能比较自由地使用各种工具。 这里列出了Hackerrank上支持的语言和库环境。据我观察比赛中大部分人都选择了Python。我自己选用的也是Python + sklearn 这个组合。
  • Kaggle的大部分比赛都持续好几个月。
  • Kaggle上有很多很具挑战性的题目,比如有机器视觉方面的。而这次Quora的比赛内容相对较简单,只有分类和回归方面的题目。
  • 在Hackerrank上的这次比赛还对程序运行时间进行了一定限制(是为了防止服务器挂掉吧-_-)。

好了,废话少说,直接上题目和我的答案吧 (代码已经传到Github上)。

解题方案

题1: Answered

https://www.hackerrank.com/contests/quora/challenges/quora-ml-answered

For this task, given Quora question text and topic data, predict whether a question gets an upvoted answer within 1 day.

这是一个分类问题,预测一个问题是否能在一天内获得一个得到同意票的答案。可以用到的Features有(括号内为json中的数据类型):

  • question_key (string): 问题ID。
  • question_text (string): 问题的文本内容。
  • context_topic (object): 问题所属的主要Topic,可能为空。如果有值的话,会包含Topic的名字 (string) 和Follower数 (integer)。
  • topics (array of objects): 这个问题所涉及的所有Topic,包括主要Topic。每个object的格式和context_topic相同。
  • anonymous (boolean): 问题是否是匿名的
  • __ans__ (boolean): 该问题是否在一天内获得一个得到同意票的答案。

以下是数据格式的一个例子(已人工排版):

{"question_text": "What is the gradient of the log likelihood function in  multinomial logistic regression?",
 "context_topic": {"followers": 76, "name": "Logistic Regression"},
 "topics": [{"followers": 7240, "name": "Data Mining"},
            {"followers": 76, "name": "Logistic Regression"},
            {"followers": 64668, "name": "Machine Learning"}],
 "question_key": "AAEAAPnh9/AlSw3IL2wm5WFRcjy/h/SlSYi4md7qqEQrzY7v",
 "__ans__": false,
 "anonymous": false}
  • 在训练和测试数据中,两个类别的样本基本是平衡的。一个很自然的想法是将 question_texttopics 中的 name 一起转化成Bag of words表示,然后用TF-IDF进行归一化 (sklearn中的相关函数)。在这一基础上,使用带L1惩罚(保证稀疏性)的Logistic Regression进行分类。在测试集上得到的准确率是: 0.577。
  • 还有没有其他特征可以用呢?记得自己在比赛中还进行了各种Feature Engineering。并不是胡乱组合,而是基于常识进行一些合理的假设。比如考虑是不是Follower数较多的Topic会更有可能得到回复。最终发现了一个特征有较好的预测性,就是一个问题所涵盖的Topic数目。得到这个Feature的工作量显然比Bag of Words表示小多了。单独使用这个Feature的准确率是:0.614。
  • 最后,组合Bag of Words和Topic数目两个特征,使用带L1惩罚的Logistic Regression。得到的准确率是:0.618

题2: Interest

https://www.hackerrank.com/contests/quora/challenges/quora-ml-interest

For this task, given Quora question text and topic data for questions with 0 visible answers, predict the ratio of viewers to followers.

这是一个回归问题。要预测的是一个问题被查看数和Follower数的比例。除了 __ans__ 是实数值,其他特征和题1是一样的。

衡量结果的指标是RMLSE(Root Mean Squared Logarithmic Error):即

$$ \frac{0.5}{\sqrt{\frac{1}{N} \sum_{i=1}^N (\log(\hat{y}_i + 1) - \log(y_i + 1))^2}} \times 100\% $$

其中 \(\hat{y}_i\) 是模型对第 \(i\) 个样本的预测值,\(y_i\) 是实际值。这里加上 \(\log\) 主要是为了防止一般的RMSE指标对较大 \(y\) 值的偏好。

  • 针对RMLSE这一指标,在训练和预测过程中也要进行相应的转化。即训练过程中对 __ans__ 取 \(\log(y + 1)\) ,对预测之后的结果再取 \(\exp(y) - 1\) 。
  • 其实每一题我都试了Bag of words表示,不过对题2和题3,得出的效果都不好。
  • 话说经过了一轮Feature Engineering,得到了如下特征:
    • 问题所属所有Topic的平均Follower数。
    • 问题所涵盖的Topic数目(和上题一样)。
    • 问题是否是匿名的。
  • 简单检查了一下数据,发现这些特征的组合到 \(y\) 的映射显然是非线性的。于是选用 GradientBoostingRegressor ,并调整了参数以防止过拟合。

题3: Views

https://www.hackerrank.com/contests/quora/challenges/quora-ml-views

For this task, given Quora question text, topic data, number of answers and number of people promoted to, predict the number of views per day in age of the question.

和题2一样,是回归问题;衡量的指标也是RMLSE。相对之前的两题,这题增加了几个Features:

  • num_answers (integer): 可见(未折叠)的答案数。
  • promoted_to (integer): 问题promote给了多少人。
  • 话说又是一阵Feature Engineering,得到了如下特征:
    • 问题所属所有Topic的平均Follower数(和上题一样)。
    • 问题所涵盖的Topic数目(和上题一样)。
    • num_answers
    • promoted_to

选用的模型依然是 GradientBoostingRegressor

其他