NLP学习|NLP学习 Task 3 基于机器学习的文本分类 笔记

1. 文本表示方法 ??在自然语言领域,文本是不定长度的。文本表示成计算机能够运算的数字或向量的方法一般称为词嵌入(Word Embedding)方法。词嵌入将不定长的文本转换到定长的空间内,是文本分类的第一步。
(1)One - hot ??将每一个字使用一个离散的向量表示。具体步骤:对每个字/词编码一个索引,然后根据索引对向量内的对应位置进行赋值。

句子1:我 爱 北 京 天 安 门 句子2:我 喜 欢 上 海{ '我': 1, '爱': 2, '北': 3, '京': 4, '天': 5, '安': 6, '门': 7, '喜': 8, '欢': 9, '上': 10, '海': 11 }我:[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 爱:[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] ... 海:[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]

(2)Bag of Words,也称为 Count Vectors ??Bag of Words(词袋表示),每个文档的字/词可以使用其出现次数来进行表示。
句子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()

(3)N-gram ??N-gram与Count Vectors类似,不过加入了相邻单词组合成为新的单词,并进行计数。如果N取值为2,则句子1和句子2就变为:
句子1:我爱 爱北 北京 京天 天安 安门 句子2:我喜 喜欢 欢上 上海

(4)TF - IDF ??TF-IDF 分数由两部分组成:第一部分是词语频率(Term Frequency),第二部分是逆文档频率(Inverse Document Frequency)。其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。
TF(t)= 该词语在当前文档出现的次数 / 当前文档中词语的总数 IDF(t)= log_e(文档总数 / 出现该词语的文档总数)

2. 基于机器学习的文本分类 【NLP学习|NLP学习 Task 3 基于机器学习的文本分类 笔记】对比不同文本表示算法的精度,通过本地构建验证集计算 f1 得分。
(1)Count Vectors + RidgeClassifier
# Count Vectors + RidgeClassifierimport pandas as pd from sklearn.feature_extraction.text import CountVectorizer from sklearn.linear_model import RidgeClassifier from sklearn.metrics import f1_scorepath_train_data = https://www.it610.com/article/r'D:\DataWhale\DW_NLP\Competition_Data\train_set.csv' train_df = pd.read_csv(path_train_data, sep='\t', nrows=15000)# pandas读取数据# CountVectorizer会将文本中的词语转换为词频矩阵,它通过fit_transform函数计算各个词语出现的次数。 # max_features:默认为None,可设为int,对所有关键词的词频进行降序排序,只取前max_features个作为关键词集 vectorizer = CountVectorizer(max_features=3000) train_test = vectorizer.fit_transform(train_df['text'])clf = RidgeClassifier() # fit(self, x, y, sample_weight=None)拟合岭分类器模型 # x训练数据集,y标签值,sample_weight每个样本的单独权重 clf.fit(train_test[:10000], train_df['label'].values[:10000]) # 前10000个样本# clf.predict(X):Predict class labels for samples in X.(预测X中样本的类别标签) val_pred = clf.predict(train_test[10000:]) print(f1_score(train_df['label'].values[10000:], val_pred, average='macro')) # 0.7406241569237678

F1分数(F1-score)是分类问题的一个衡量指标。一些多分类问题的机器学习竞赛,常常将F1-score作为最终测评的方法。它是精确率和召回率的调和平均数,最大为1,最小为0。
F1 = 2 x(precision x recall)/(precision + recall)
f1_score(val_true, val_pred, labels=None, pos_label=1, average='binary', sample_weight=None)
val_true :目标的真实类别。
val_pred :分类器预测得到的类别。
average :[None, ‘binary’(default), ‘micro’, ‘macro’, ‘samples’, ‘weighted’] 如果是二分类问题则选择 binary;如果考虑类别的不平衡性,需要计算类别的加权平均,则使用 weighted;如果不考虑类别的不平衡性,计算宏平均,则使用 macro。
(2)TF-IDF + RidgeClassifier
# TF-IDF + RidgeClassifierimport pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import RidgeClassifier from sklearn.metrics import f1_scorepath_train_data = https://www.it610.com/article/r'D:\DataWhale\DW_NLP\Competition_Data\train_set.csv' train_df = pd.read_csv(path_train_data, sep='\t', nrows=15000)# pandas读取数据# 要提取的n-gram的n-values的下限和上限范围,在min_n(1) <= x <= max_n(3)区间的n的全部值,即1,2,3 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

关于TfidfVectorizer的参数的参考文章:https://blog.csdn.net/laobai1015/article/details/80451371
3. 补充 (1)尝试改变TF-IDF的参数,并验证精度 NLP学习|NLP学习 Task 3 基于机器学习的文本分类 笔记
文章图片

数据量越大,训练效果越好。max_feature越大,效果越好,但是达到一定程度,效果增加的不够明显。对于停用词,从结果来看,3750的最好,其次是648,最后是900,但其实648和900效果基本没什么差别。
(2)尝试使用其他机器学习模型,完成训练和验证 关于SVM参数的参考文章:https://blog.csdn.net/nc514819873/article/details/89331088
NLP学习|NLP学习 Task 3 基于机器学习的文本分类 笔记
文章图片

SVM和XGBoost的训练比较慢,但是效果比较好。

    推荐阅读