基于Kaggle数据的词袋模型文本分类教程



基于Kaggle数据的词袋模型文本分类教程

发表于 23小时前| 454次阅读| 来源 FastML| 0 条评论| 作者 Zygmunt Z
width="22" height="16" src="http://hits.sinajs.cn/A1/weiboshare.html?url=http%3A%2F%2Fwww.csdn.net%2Farticle%2F2015-09-23%2F2825782&type=3&count=&appkey=&title=%E6%9C%AC%E6%95%99%E7%A8%8B%E5%B1%95%E7%A4%BA%E4%BA%86%E6%94%B9%E5%96%84%E6%96%87%E6%9C%AC%E5%88%86%E7%B1%BB%E7%9A%84%E6%96%B9%E6%B3%95%EF%BC%8C%E5%8C%85%E6%8B%AC%EF%BC%9A%E5%81%9A%E4%B8%80%E4%B8%AA%E9%AA%8C%E8%AF%81%E9%9B%86%EF%BC%8C%E4%B8%BAAUC%E9%A2%84%E6%B5%8B%E6%A6%82%E7%8E%87%EF%BC%8C%E7%94%A8%E7%BA%BF%E6%80%A7%E6%A8%A1%E5%9E%8B%E4%BB%A3%E6%9B%BF%E9%9A%8F%E6%9C%BA%E6%A3%AE%E6%9E%97%EF%BC%8C%E4%BD%BF%E7%94%A8TF-IDF%E6%9D%83%E8%A1%A1%E8%AF%8D%E6%B1%87%EF%BC%8C%E7%95%99%E4%B8%8B%E5%81%9C%E7%94%A8%E8%AF%8D%EF%BC%8C%E5%8A%A0%E4%B8%8A%E4%BA%8C%E5%85%83%E6%A8%A1%E5%9E%8B%E6%88%96%E8%80%85%E4%B8%89%E5%85%83%E6%A8%A1%E5%9E%8B%E7%AD%89%E3%80%82&pic=&ralateUid=&language=zh_cn&rnd=1443098883312" frameborder="0" scrolling="no" allowtransparency="true"> 摘要:本教程展示了改善文本分类的方法,包括:做一个验证集,为AUC预测概率,用线性模型代替随机森林,使用TF-IDF权衡词汇,留下停用词,加上二元模型或者三元模型等。

有一个Kaggle的训练比赛,你可以尝试进行文本分类,特别是电影评论。没有其他的数据——这是使用文本分类做一些实验的绝佳机会。

Kaggle有一个关于本次比赛的tutorial,它会带你走进流行的词袋方法以及word2vec。本教程几乎代表了最佳实践,最有可能让参赛选手的优化变得很容易。而这正是我们要做的。

验证

验证是机器学习的基石。这是因为我们之后会推广到未知的测试实例。通常,评估一个模型推广的唯一明智方式是使用验证:如果你有足够的例子,你可以进行单一训练、验证分割;又或者如果你有几个训练点,你可以进行计算上更昂贵但却很有必要的交叉验证。

一点题外话:在不少Kaggle比赛,来自不同分布而不是训练集的一组测试,意味着它甚至很难成为代表性的验证集。这是一个挑战还是愚蠢的行为,取决于你的观点。

为了激励验证的需求,让我们回顾百度团队参加ImageNet比赛的情况。这些人显然不理解验证,所以他们不得不求助于排行榜来评估自己的努力。ImageNet每周只允许两次提交,所以他们创造了许多假账户来拓展他们的带宽。不幸的是,主办方不喜欢这样的方法,而百度也因此陷入尴尬。

验证分割

我们的第一个步骤是通过启用验证来修改原始教程代码。因此,我们需要分割训练集。既然我们有25,000个训练例子,我们将取出5,000个进行测试,并留下20,000个进行培训。一种方法是将一个培训文件分割成两个——我们从phraug2中使用split.py脚本:

python split.py train.csv train_v.csv test_v.csv -p 0.8 -r dupa

使用随机种子“Dupa”来实现再现。Dupa是用于这样场合的波兰码字。我们下面报告的结果是基于这种分割。

训练集是相当小的,所以另一种方式是加载整个训练文件到内存中并把它分割,然后,使用scikit-learn为此类任务提供的好工具:

from sklearn.cross_validation import train_test_split
train, test = train_test_split( data, train_size = 0.8, random_state = 44 )

我们提供的脚本使用这种机制以便使用,而不是单独的训练、测试文件。我们需要使用索引因为我们正在处理Pandas框架,而不是Numpy数组:

all_i = np.arange( len( data ))
train_i, test_i = train_test_split( all_i, train_size = 0.8, random_state = 44 )

train = data.ix[train_i]
test = data.ix[test_i]

度量标准

竞争的度量标准是AUC,它需要概率。出于某种原因,Kaggle教程只预测0和1。这是很容易解决:

p = rf.predict_proba( test_x )
auc = AUC( test_y, p[:,1] )

而且我们看到,随机森林成绩大约为91.9%。

词袋的随机森林?不

随机森林是一个强大的通用方法,但它不是万能的,对于高维稀疏数据并不是最好的选择。而BoW表示是高维稀疏数据的一个很好例子。

此前我们覆盖了词袋,例如A bag of words and a nice little network。在那篇文章中,我们使用了神经网络进行分类,但事实是简约的线性模型往往是首选。我们将使用逻辑回归,因为现在留下超参数作为默认值。

逻辑回归的验证AUC是92.8%,并且它比随机森林的训练快得多。如果你打算从这篇文章学点东西:对于高维稀疏数据使用线性模型,如词袋。

TF-IDF

TF-IDF即“术语频率/倒排文档频率(term frequency / inverse document frequency)”,是这样一种方法:用于强调给定文档中的高频词汇,而不再强调出现在许多文档中的高频词汇。

我们TfidfVectorizer和20,000个特征的得分是95.6%,有很大的改进。

停用词和N-grams

Kaggle教程的作者认为有必要去除停用词(Stopwords)。停用词即commonly occuring words,比如“this”,“that”,“and”,“so”,“on”。这是一个很好的决定吗?我们不知道,我们需要检验,我们有验证集,还记得吗?留下停用词的得分为92.9%(在TF-IDF之前)。

反对移除停用词的一个更重要的原因是:我们想尝试n-grams,并且对于n-grams我们最好让所有词留在原地。我们之前涵盖了n-grams,它们由n个连续的词组合在一起,使用二元模型开始(两个词):“cat ate”,“ate my”,“my precious”,“precious homework”。三元模型由三个词组成:“cat ate my”,“ate my homework”,“my precious homework”;四元模型,等等。

为什么n-grams能够work?想想这句话:“movie not good”。它有明显的负面情绪,但是如果你把每个单词都分离,你将不会检测这一点。相反,该模型可能会了解到,“good”是一个积极的情绪,这将不利于判断。

在另一方面,二元模型可以解决问题:模型可能会了解到,“not good”有负面情绪。

使用来自斯坦福大学情感分析页面的更复杂的例子:

This movie was actually neither that funny, nor super witty.

对于这个例子,二元模型将在“that funny”和“super witty”上失败。我们需要至少三元模型来捕捉“neither that funny”和“nor super witty”,然而这些短语似乎并不太常见,所以,如果我们使用的特征数量有限,或正规化,他们可能不会让它进入到模型。因此,像神经网络一样的更复杂的模型的动因会使我们离题。

如果计算n-grams听起来有点复杂,scikit-learn量化能够自动地做到这一点。正如Vowpal Wabbit可以,但我们不会在这里使用Vowpal Wabbit。

使用三元模型的AUC得分为95.9%。

维度

每个字都是一个特征:它是否出现在文档中(0/1),或出现多少次(大于等于0的整数)。我们从教程中开始原始维数,5000。这对随机森林很有意义,这是一个高度非线性的、有表现力的、高差异的分类,需要一个配给相对比较高的例子用于维数。线性模型在这方面不太苛求,他们甚至可以在d>>n的情况下work。

我们发现,如果我们不限制维数,即使这样一个小的数据集也会使我们耗尽内存。我们可以在12 GB RAM的机器上带动大约40,000个特征。甚至引起交换。

对于初学者来说,我们尝试20,000个特征。逻辑回归分数为94.2%(在TF-IDF和n-grams之前),与5,000个特征的得分92.9%进行比较。更多的分数甚至更好:30,000个特征的得分96.0%,40,000个特征的得分96.3%(在TF-IDF和n-grams之后)。

为了解决内存问题,我们可以使用hashing vectorizer。然而,相对于之前的96.3%,它只得到了93.2%的分数,部分原因是它不支持TF-IDF。

结语

我们展示了改善文本分类的方法:

  • 做一个验证集
  • 为AUC预测概率
  • 用线性模型代替随机森林
  • 使用TF-IDF权衡词汇
  • 留下停用词
  • 加上二元模型或者三元模型

公众排行榜得分反映了验证得分:都大约是96.3%。在提交的时候,它在500名参赛者中足够进入前20名。

你可能还记得,我们留下了线性回归的超参数作为默认值。此外,向量化有它自己的参数,你可可期望更实际些。微调它们的结果有一个适量的改善,达到96.6%。

再次说明,这篇文章的代码可在Github上得到。

UPDATE:Mesnil,Mikolov,Ranzato和Bengio有一篇情感分类的paper:Ensemble of Generative and Discriminative Techniques for Sentiment Analysis of Movie Reviews (code)。他们发现,使用n-gram的线性模型优于递归神经网络(RNN)和使用句子向量的线性模型。

然而,他们使用的数据集(Stanford Large Movie Review Dataset)比较小,有25,000个训练实例。 Alec Radford 表示,在样本数量较大,大致从100,000到1000,000,RNN开始优于线性模型。


Credit: Alec Radford / Indico, Passage example

对于句子向量,作者用逻辑回归分析法。我们宁愿看到100维向量送入非线性模型随机森林。

这样,我们卑微地发现随机森林的分数只是85-86 %(奇怪……为什么?),这取决于树的数量。该paper准确地说,逻辑回归的精度大约为89%。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值