sklearn 基本的文本分类

目的

其实,说白了就是人想知道这个文档是做什么的。首先给每篇文章一个标签、构建文档的特征,然后通过机器学习算法来学习特征和标签之间的映射关系,最后对未知的文本进行标签的预测。
在海量信息的互联网时代,文本分类尤其重要。sklearn作为即可学术研究,也可构建产品原型,甚至发布商用产品的机器学习包,里面封装了一些常用的文本操作的算法。这里慢慢的记录一下。

训练数据

以后有机会我爬取一些中文的文本,但现在我们先使用sklearn提供的新闻媒体的数据。
代码如下。

categories = ['alt.atheism', 'soc.religion.christian',
              'comp.graphics', 'sci.med']

from sklearn.datasets import fetch_20newsgroups
twenty_train = fetch_20newsgroups(subset='train',
    categories=categories, shuffle=True, random_state=42)
twenty_test = fetch_20newsgroups(subset='test',
    categories=categories, shuffle=True, random_state=42)

这里只取5个类别的新闻媒体(为了计算速度)。
twenty_train, twenty_test封装了文本和target(label,使用0、1、2、3表示)

构建特征BOW

Bag of Words是文本分类入门级的特征,很容易理解,后文会有简略的介绍。代码如下。

from sklearn.feature_extraction.text import CountVectorizer
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(twenty_train.data)
X_train_counts.shape

改代码的输出为:
(2257, 35788)
也就是说,共有2257篇训练文章,词典的大小为35788维。
CountVectorizer类的参数也很好理解,比较重要的几个
stop_words=,指定的停用词;
max_df=,超过这个频率的词不作为词典词,默认1.0;
min_df=,小于这个频率的词不作为次电磁,默认1(至少出现在一篇文章中);
max_features=,词典最多有多少个词,默认None,如果指定了,则通过词频来排序取舍。
vocabulary=,指定的词典。

构建TF-IDF特征

代码如下

from sklearn.feature_extraction.text import TfidfTransformer
tf_transformer = TfidfTransformer().fit(X_train_counts)
X_train_tf = tf_transformer.transform(X_train_counts)
X_train_tf.shape

简单的说,TF-IDF特征将每个词在当前文档中的重要程度给计算出来了,而且归一化。后面会有简略的介绍。

构建朴素贝叶斯分类器

from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB().fit(X_train_tf, twenty_train.target)

在测试集上的结果

predicted = clf.predict(tf_transformer.transform(count_vect.transform(twenty_test.data)))

from sklearn import metrics
print(metrics.classification_report(twenty_test.target, predicted,
    target_names=twenty_test.target_names))

结果如下所示。

                        precision    recall  f1-score   support

           alt.atheism       0.97      0.60      0.74       319
         comp.graphics       0.96      0.89      0.92       389
               sci.med       0.97      0.81      0.88       396
soc.religion.christian       0.65      0.99      0.78       398

           avg / total       0.88      0.83      0.84      1502

总结

基本的文本分类的流程基本就是这样,后续就是使用更加合适的分词、词典、特征的构建方法,使用更加合适的分类器等。具体问题具体分析。

Bag of Word

Bag of words模型最初被用在文本分类中,将文档表示成特征矢量。它的基本思想是假定对于一个文本,忽略其词序和语法、句法,仅仅将其看做是一些词汇的集合,而文本中的每个词汇都是独立的。简单说就是讲每篇文档都看成一个袋子(因为里面装的都是词汇,所以称为词袋,Bag of words即因此而来),然后看这个袋子里装的都是些什么词汇,将其分类。如果文档中猪、马、牛、羊、山谷、土地、拖拉机这样的词汇多些,而银行、大厦、汽车、公园这样的词汇少些,我们就倾向于判断它是一篇描绘乡村的文档,而不是描述城镇的。举个例子,有如下两个文档:

文档一:Bob likes to play basketball, Jim likes too.

文档二:Bob also likes to play football games.

基于这两个文本文档,构造一个词典:

Dictionary = {1:”Bob”, 2. “like”, 3. “to”, 4. “play”, 5. “basketball”, 6. “also”, 7. “football”,8. “games”, 9. “Jim”, 10. “too”}。

这个词典一共包含10个不同的单词,利用词典的索引号,上面两个文档每一个都可以用一个10维向量表示(用整数数字0~n(n为正整数)表示某个单词在文档中出现的次数):

1:[1, 2, 1, 1, 1, 0, 0, 0, 1, 1]

2:[1, 1, 1, 1 ,0, 1, 1, 1, 0, 0]

向量中每个元素表示词典中相关元素在文档中出现的次数(下文中,将用单词的直方图表示)。不过,在构造文档向量的过程中可以看到,我们并没有表达单词在原来句子中出现的次序(这是本Bag-of-words模型的缺点之一,不过瑕不掩瑜甚至在此处无关紧要)。

if-idf词频倒排索引

TFIDF的主要思想是:如果某个词或短语在一篇文章中出现的频率TF高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
在一份给定的文件里,词频(term frequency,TF)指的是某一个给定的词语在该文件中出现的频率。这个数字是对词数(term count)的归一化,以防止它偏向长的文件。(同一个词语在长文件里可能会比短文件有更高的词数,而不管该词语重要与否。)对于在某一特定文件里的词语 ti 来说,它的重要性可表示为:

sklearn 基本的文本分类
其中,分子表示单词i在文档j中出现的次数,分母表示文档j的所有单词个数。
逆向文件频率(inverse document frequency,IDF)是一个词语普遍重要性的度量。某一特定词语的IDF,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取对数得到:

sklearn 基本的文本分类
其中,分子位语料库文档总的个数;
分母为用于单词i的文档的个数。

最终,
sklearn 基本的文本分类