学习目标
- 学会常用的文本表示方法原理和使用
- 使用sklearn的机器学习模型完成文本分类
文本表示方法
在机器学习算法的训练过程中,假设给定
N个样本,每个样本有 M 个特征,这样组成了 N×M 的样本矩阵,然后完成算法的训练和预测。同样的在计算机视觉中可以将图片的像素看作特征,每张图片看作hight×width×3的特征图,一个三维的矩阵来进入计算机进行计算。
但是在自然语言领域,上述方法却不可行:文本是不定长度的。文本表示成计算机能够运算的数字或向量的方法一般称为词嵌入(Word Embedding)方法。词嵌入将不定长的文本转换到定长的空间内,是文本分类的第一步。
Bag of Words
Bag of Words(词袋表示),也称为Count Vectors,每个文档的字/词可以使用其出现次数来进行表示。在sklearn中可以直接CountVectorizer来实现这一步骤,举例如下:
#封装一个函数,CountVectorizer和TruncatedSVD结合实现LSI/LSA(隐含语义分析)
from sklearn.decomposition import TruncatedSVD
from sklearn.feature_extraction.text import CountVectorizer
def count2vec(input_values, output_num, output_prefix, seed=1024):
count_enc = CountVectorizer()
count_vec = count_enc.fit_transform(input_values)
svd_tmp = TruncatedSVD(n_components=output_num, n_iter=20, random_state=seed)
svd_tmp = svd_tmp.fit_transform(count_vec)
svd_tmp = pd.DataFrame(svd_tmp)
svd_tmp.columns = ['{}_countvec_{}'.format(output_prefix, i) for i in range(output_num)]
return svd_tmp
TF-IDF
定义
TF-IDF 分数由两部分组成:第一部分是词语频率(Term Frequency),第二部分是逆文档频率(Inverse Document Frequency)。其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。
使用
#构建一个计算词频(TF)的玩意儿,当然这里面不足是可以做这些
vectorizer = CountVectorizer()
#构建一个计算TF-IDF的玩意儿
transformer = TfidfTransformer()
#vectorizer.fit_transform(corpus)将文本corpus输入,得到词频矩阵
#将这个矩阵作为输入,用transformer.fit_transform(词频矩阵)得到TF-IDF权重矩阵
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus)
优势
是一种在文本挖掘中广泛使用的特征向量化方法,它可以体现一个文档中词语在语料库中的重要程度。(对比Countvectorizer,训练文本的数量越多,TF-IDF就更有优势。
Word2Vec
定义
from gensim.models import word2vec
把每一个单词表示成一个向量。来计算文档相似度计算等等。用于词向量的获取。即根据“上下文-单词”矩阵进行学习,得到融入了上下文共现特征的词向量。
使用
from gensim.models import word2vec
model=word2vec.Word2Vec(sentences,min_count=5,size=50)
#min_count,频数阈值,大于等于1的保留,默认值为5;
#size是神经网络的隐藏层单元数,默认为100;
#workers=4,default = 1 worker = no parallelization 只有在机器已安装 Cython 情况下才会起到作用。
#结果查看
model.similarity("好", "还行")#计算两个词之间的余弦距离
model.most_similar("滋润", topn=10)#计算余弦距离最接近“滋润”的10个词
#存储和加载模型 (页首)
model.save('/model/word2vec_model')
new_model=gensim.models.Word2Vec.load('/model/word2vec_model')
优缺点
-
优点:
由于Word2vec会考虑上下文,跟之前的Embedding方法相比,效果要更好;比之前的Embedding方法维度更少,所以速度更快;通用性很强,可以用在各种 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('../data/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'))
0.7422037924439758
# 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('../data/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'))
0.8721598830546126