本项目将会是自然语言处理相关方法的实践,数据集是Kaggle上关于句子相似度匹配的竞赛。涉及到文本类信息的数据清洗和特征工程,在模型方法上将会使用XGBoost。XGBosst方法是一类集成方法,将多个弱分类器集成为一个强大的模型。鉴于本次项目竞赛已经结束,所以最终的训练效果无从验证,本项目重点讨论文本特征的提取和XGBoost模型如何使用及调参。
本项目是一个句子相似度匹配的任务,数据集由Quora发布在kaggle上。Quora是海外的一个问答SNS网站,积累了大量的用户问答信息。Quora一个重要的产品原则是,每个逻辑上不同的问题应该有一个单独的页面,用户的提问将会首先匹配这些已经存在的页面,来优化知识获取途径。训练数据集是包含潜在相似的问题对以及对应Ground-truth标签的csv表格文件,这些问题对可以看做是用户的输入是一句话的文本。本项目面临的问题如下:
如何处理英文文本数据。英文由26个字符组成,在处理方式上天生比中文文本处理简单。在计算机领域,文本处理技术已经相当成熟,本项目将会使用适合机器学习的处理办法,这类方法的特点就是计算量巨大,以至于需要云服务器+GPU的算力才能在理想的时间内有效运算。具体到本项目中的方法就是将文本进行词义转换、词形还原、提取词根、提取词干,这一步可以理解为令牌化(Word Tokenize)。然后对令牌化的文本进行分析,例如:对单词的数量进行统计就会得到词频(Term Frequency),对语言整体的词分布进行描述的就是词向量(Word Vector),对句子中疑问副词的划分可以得到语义的一些信息,对整体语境的描述甚至可以得到感情色彩评分等等。这一步也叫作特征工程(Feature Engineering)。
如何建立模型。是的机器学习办法就是对数据建模的过程,建模可以采用深度模型(Deep Learning)或者非深度模型。其中深度模型也就是常说的神经网络,适合文本的神经网络模型有长短期记忆(Long short-term memory, LSTM)模型、孪生卷积网络(Siamese CNN);而非深度模型说的就是传统的机器学习办法,例如梯度提升树(eXtremeGradientBoosting,XGBoost)算法、随机森林(RandomForest)算法。本篇将采用XGBoost简历模型,它是由著名学者陈天奇(华盛顿大学博士)于2014年提出,XGBoost属于集成算法,将多个弱分类器集成为一个强分类器,其中分类器可以理解为树,那么分类的节点就是叶子。
另外本篇的难点是,训练集有40万行,测试集有200万行,所以一个首要的任务如何预防训练的模型过拟合(Over Fitting),过拟合就是模型在训练时表现很好而在实际数据中并没有达到预期的效果。与过拟合相对就是欠拟合(Under Fitting),而XGBoost是一种树模型,天然的会产生过拟合。由此带来的问题就是在项目的调参阶段比较不容易发现模型在损失上有较明显的改善,反而是模型在早停方面得到了改善,树的数量有了很大的增长,最后的结论也认为这对模型应用在大数据集上是有帮助。
本次项目用的评价指标为损失函数,损失函数就是用来表现预测与实际数据的差距程度。本项目中使用的是XGBoost自带的损失函数logloss,但是在训练过程有所不同,原因是观察到训练集的正负样本不均衡。为了消除这种影响需要设置scale_pos_weight参数。
虽然训练时logloss的计算的却会根据scale_pos_weight有所调整,也就是说scale_pos_weight参数的确可以影响到XGBoost的训练过程,但对于验证过程,用于交叉验证的xgb.cv函数却没有这样的效果,该函数的交叉验证logloss仍然是根据正负例等权重的方法计算得到。
因此在CV环节重新定义了一个加权对数损失函数,输入给xgb.cv函数的feval参数用于交叉验证的损失计算,而训练过程中的损失函数则无需自定义计算。计算方法如下:
这一部分我们将对部分文本特征进行可视化探索,观察文本是如何转变为特征。
测试集预览:
训练集预览:
- 训练集:train.csv,63.4MB, 样本shape:(404290, 6)
- 测试集:test.csv,314.02MB, 样本shape:(2345796, 3)
训练集正例的百分比: 36.92%
字符数量统计:
横轴是句子中包含的字符的数量,纵轴是相应的概率。将训练集和测试集用相同的标准进行缩放后进行比较:首先分布图的形状基本能保持一致,在峰值部分稍微有些不同;在150-160的部分有明显区别,看起来训练集这这一区域数据量较少。
word数量统计:
横轴是句子中包含word的数量,纵轴是相应的概率。将训练集和测试集用相同的标准进行缩放后进行比较:看起来和字符的统计图很像,10个word的句子是最常见的;测试集和训练集在word数量的形态上是一致的。
问题重复频次:
question1和question2中有相当一部分的问题是被复用了:从qid来看不重复问题的数量:537933;复用的问题频数合计: 111780。
图中横轴代表问题重复使用的次数,纵轴代表相应次数内包含了多少个问题。大多数问题只出现了一次,部分问题出现了很多次,还有的问题出现了将近160次,可以认为它是离群值。主观来看重复问题的分布对词袋模型、TF-IDF等需要计算词频的诸多特征是有影响的,但这正是适合机器学习方法解决的问题。
词云:
词云显示了最常出现的单词,单词出现次数越多在图中显示越大,可以发现出现次数最多的单词是difference,随后可能是best、way、will、good等,这些词可能对话、新闻、网络等多种场合都是最常用。
几个有意思的特征:
- 带有问号标记: 99.87%
- 带有[math]标记的: 0.12%
- 带句号的: 6.31%
- 首字符大写的: 99.81%
- 包含大写字符的: 99.95%
- 包含数字的: 11.83%
文本数据的特征工程是比较繁琐,不同元素的组合都可能构成新的特征。
word share feature:
共享词用来衡量文本相似度是个不错的度量,如果两个句子共享词很多那么很有可能相同的问题。
横轴中的0代表问题对中没有共享词,其它代表有共享词,计算公式为:
本例中用到的是敏感词是疑问副词,通过计数是否包含疑问副词得出共享词
(图片可以放大了看)
上图显示的是对预测为“不相似”标注为相似数据的随机抽样,同时输出了文本的清洗中间过程。以编号为327911的句子为例,q1”Can a man love multiple women?”,q2“Is it possible for a man to love two women sincerely?”,这两个问题在语义上可以视为同一个问题,但是经过处理后在lem一栏可以看出,两个问题不相同的单词明显很多,由此判定为“不相似”也是有可能的,说明共现词对在模型中发挥了重要作用。再看其他的实例也是同样的问题,反应出的是模型在语义特征方面的欠缺。
上图是预测为“相似”,标注为“不相似”的抽样,首先来看编号为236250的句子,q1“If you were a farmer what would you grow?” ,q2“If you were a farmer, what would you grow?”,这两个句子是同样的问题,但是标注的却是‘不相似’,这是一个明显的标注错误。编号为21938的例子,q1和q2仅有一个单词不同,从语义上来说确实是“不相似”,但是模型是有可能判断为“相似”。
然后,我们对测试集的预测结果进行抽样,其中抽样了三类数据,一类是预测为“相似”,一类是预测为“不相似”,还有预测值在0.5附近区域的数据。通过对比发现,三类数据的划分是有意义的,可以被接受的,问题可能还是特征的重要程度对模型的影响。
上图是重要特征排序,GloVe和word2vec产出的特征质量还是不错的,尤其是余弦距离看来是一个很突出的特征,意外的是share_words_rate_orig在重要性中是最高,但是其他的共享词特征的排序并不是很突出。值得注意的是share_words_rate_orig、share_words_rate_stop、share_words_rate_stem、share_words_rate_lem在算法上是一致的,区别是数据集的处理方式不同。
通过实战演练,确实能够体会到机器学习算法的威力,机器学习算法在效率上远超人类一个量级。特征工程方面可能是最耗费时间和经历的部分,需要对文本处理方式有一个全面的认识。在调参过程中期望可以应用网格搜索自动发现最优解,但是试验过程中由于运行时间比较长,kernal会被打断。除了理论和技术上需要学习,在工程能力上还需要努力进步。
特征的数量还是少了,如果特征很多的话需(例如几百个)要进行特征选择,使用的方法Filter特征过滤或者Embedded特征嵌入,本例后期增加了word2vec做的距离特征,得分成绩提高了1个千分点
在特征足够的基础上可以使用模型融合技术,将多个模型的结果融合在一起,获得更强的分类结果。
项目地址:https://github.com/cyber-pixel/udacity-submit-repo/tree/master/毕业项目