零基础入门NLP-新闻文本分类【Task3】
Task3 基于机器学习的文本分类
学习目标
- 学会TF-IDF的原理和使用
- 使用sklearn的机器学习模型完成文本分类
文本表示方法
在机器学习算法的训练过程中,假设给定 N N N个样本,每个样本有 M M M个特征,这样组成了 N × M N×M N×M的样本矩阵,然后完成算法的训练和预测。同样的在计算机视觉中可以将图片的像素看作特征,每张图片看作hight×width×3的特征图,一个三维的矩阵来进入计算机进行计算。
但是在自然语言领域,上述方法却不可行:文本是不定长度的。文本表示成计算机能够运算的数字或向量的方法一般称为词嵌入(Word Embedding)方法。词嵌入将不定长的文本转换到定长的空间内,是文本分类的第一步。
One-hot
One-Hot 编码,又称为一位有效编码,主要是采用 N N N位状态寄存器来对 N N N个状态进行编码,每个状态都有各自独立的寄存器位,并且在任意时候只有一位有效。
One-Hot 将将每一个单词使用一个离散的向量表示。具体将每个字/词编码一个索引,然后根据索引进行赋值。其步骤如下:
- 构造文本分词后的字典,每个分词是一个比特值,比特值为0或者1。
- 每个分词的文本表示为该分词的比特位为1,其余位为0的矩阵表示。
One-hot表示方法的例子如下:
句子1:我 爱 北 京 天 安 门
句子2:我 喜 欢 上 海
首先对所有句子的字进行索引,即将每个字确定一个编号:
{'我': 1, '爱': 2, '北': 3, '京': 4, '天': 5, '安': 6, '门': 7, '喜': 8, '欢': 9, '上': 10, '海': 11}
Bag of Words
Bag of Words(词袋表示) ,也称为Count Vectors,像是句子或是文件这样的文字可以用一个袋子装着这些词的方式表现,每个文档的字/词可以使用其出现次数来进行表示,这种表现方式不考虑文法以及词的顺序。
句子1:我 爱 北 京 天 安 门
句子2:我 喜 欢 上 海
直接统计每个字出现的次数,并进行赋值:
句子1:我 爱 北 京 天 安 门
转换为 [1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0]
句子2:我 喜 欢 上 海
转换为 [1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
在sklearn中可以直接 CountVectorizer 来实现这一步骤:
from sklearn.feature_extraction.text import CountVectorizer
corpus = [
'This is the first document.',
'This document is the second document.',
'And this is the third one.',
'Is this the first document?',
]
vectorizer = CountVectorizer()
vectorizer.fit_transform(corpus).toarray()
N-gram
N-gram 模型为了保持词的顺序,做了一个滑窗的操作,这里的 N N N表示的就是滑窗的大小,例如2-gram模型,也就是把2个词当做一组来处理,然后向后移动一个词的长度,再次组成另一组词,把这些生成一个字典,按照词袋模型的方式进行编码得到结果。
如果N取值为2,则句子1和句子2就变为:
句子1:我爱 爱北 北京 京天 天安 安门
句子2:我喜 喜欢 欢上 上海
TF-IDF
TF-IDF 是一种用于信息检索与数据挖掘的常用加权技术。分数由两部分组成:第一部分是词语频率(Term Frequency),第二部分是逆文档频率(Inverse Document Frequency)。
字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。一个词语在一篇文章中出现次数越多, 同时在所有文档中出现次数越少, 越能够代表该文章。
公式来源:NLP从词袋到Word2Vec的文本表示.
基于机器学习的文本分类
Count Vectors + RidgeClassifier
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score
train_df = pd.read_csv('../input/train_set.csv', sep='\t', nrows=15000)
vectorizer = CountVectorizer(max_features=3000)
train_test = vectorizer.fit_transform(train_df['text'])
clf = RidgeClassifier()
clf.fit(train_test[:10000], train_df['label'].values[:10000])
val_pred = clf.predict(train_test[10000:])
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
其F1得分为0.7416952793751392。
TF-IDF + RidgeClassifier
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score
train_df = pd.read_csv('../input/train_set.csv', sep='\t', nrows=15000)
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])
clf = RidgeClassifier()
clf.fit(train_test[:10000], train_df['label'].values[:10000])
val_pred = clf.predict(train_test[10000:])
print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
其F1得分为0.8719098297954606,所以 TF-IDF + RidgeClassifier 的结果优于 Count Vectors + RidgeClassifier。
本章小结
本章我们介绍了基于机器学习的文本分类方法,并完成了两种方法的对比。