一、一个CBOW栗子的引入
Bag of words词袋表示,又称为CountVectors或者CBOW,用它表示成对应的文本向量时,每个向量的元素对应该该维对应的词在文本中出现的次数。显然这种表示方法木有考虑词的顺序信息,没有融入上下文的信息。
下面来看下它的实现吧:
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() return_vector = vectorizer.fit_transform(corpus).toarray() """ array([[0, 1, 1, 1, 0, 0, 1, 0, 1], [0, 2, 0, 1, 0, 1, 1, 0, 1], [1, 0, 0, 1, 1, 0, 1, 1, 1], [0, 1, 1, 1, 0, 0, 1, 0, 1]], dtype=int64) """
二、N-gram模型
N-gram在CBOW基础上,加入了相邻单词组合成新单词,并进行计数。比如N=2时,初始有2个句子:
句子1:我 爱 北 京 天 安 门
句子2:我 喜 欢 上 海
处理后的2个句子变成:
句子1:我爱 爱北 北京 京天 天安 安门 句子2:我喜 喜欢 欢上 上海
三、使用 TF-IDF 提取文本特征
(Term Frequency - Inverse Document Frequency)
学习TFIDF的原理
学会使用CountVectorizer
学会使用TfidfVectorizer
TF-IDF 分数由两部分组成:
第一部分是TF词语频率(Term Frequency),
第二部分是IDF逆文档频率(Inverse Document Frequency)。
其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。
TF(t)= 该词语在当前文档出现的次数 / 当前文档中词语的总数
IDF(t)= log_e(文档总数 / 出现该词语的文档总数)即:
IDF反应了一个词在所有文本中出现的频率,如果一个词在很多的文本中出现,那么它的IDF值应该低,比如I come to China to travel中的“to”。而反过来如果一个词在比较少的文本中出现,那么它的IDF值应该高。一个极端的情况,如果一个词在所有的文本中都出现,那么它的IDF值应该为0。
# -*- coding: utf-8 -*- """ Created on Thu Nov 4 14:28:50 2021 @author: 86493 """ # 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 # 维度为(15000, 2)的训练样本,2指label列text文本列 train_df = pd.read_csv('train_set.csv', sep = '\t', nrows = 15000) # 3000是所要建立的词典的长度 vectorizer = CountVectorizer(max_features = 3000) # 实例化对象 # (15000, 3000)维度的train_test train_test = vectorizer.fit_transform(train_df['text']) # return_vector = vectorizer.fit_transform(train_df['text']).toarray() # 岭回归分类器 clf = RidgeClassifier() clf.fit(train_test[: 10000], train_df['label'].values[: 10000]) # 15000-10000=5000的测试样本 val_pred = clf.predict(train_test[10000:]) print(f1_score(train_df['label'].values[10000:], val_pred, average = 'macro')) # 打印出 0.7416952793751392
四、使用TFIDF特征和线性模型完成训练和预测
使用TFIDF提取训练集和测试集特征
使用线性模型(LR等)完成模型的训练和预测
应用起来就是换成了TfidfVectorizer类进行实例化,注意这里多个ngram_range参数,官方文档的解释是:
就是说ngram_range该参数决定选词的特点(结合刚才的N-gram思想),比如一句话’I like you’:
(1)如果ngram_range = (2, 2)表示只选取前后的两个词构造词组合 :词向量组合为:’I like‘ 和 ’like you‘ ;
(2)如果ngram_range = (1, 3) 表示选取1到3个词做为组合方式: 词向量组合为: ‘I’, ‘like’, ‘you’, ‘I like’, ‘like you’, ‘I like you’ 构成词频标签。
然后同样通过本地构建验证集(5000个测试样本)计算F1得分。
PS:下面代码注释和上面差不多。
# -*- coding: utf-8 -*- """ Created on Thu Nov 4 14:51:20 2021 @author: 86493 """ # 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('train_set.csv', sep = '\t', nrows = 15000) # 多了个ngram_range参数 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