零基础入门NLP之新闻文本分类_Task3

	在自然语言领域中,文本是不定长度的。文本表示成计算机能够运算的数字或向量的方法一般称为词嵌入方法。词嵌入将不定长的文本转换到定长的空间内,是文本分类的第一步。

1.One-hot

	将所有句子的字进行索引,然后每个字转换成稀疏向量,即将每一个单次用一个离散的向量表示。

2.Bag of Words

	词袋表示,也称为Count Vectors。即每个文档的字或词可以使用出现次数来进行表示。

3.N-gram

	与CountVectors类似,不过加入了相邻单词组合成为了新的单词,并进行计数。

4.TF-IDF

	由两部分组成。第一部分是词语频率,第二部分是逆文档频率。

5.以下为本任务的代码部分,分别说明了各种分词方法搭配机器学习模型的效果

5.1导入第三方模块

import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.linear_model import RidgeClassifier
from sklearn.metrics import f1_score
from sklearn.ensemble import RandomForestClassifier

5.2 导入训练数据集

train_df = pd.read_csv(r'D:\Users\Felixteng\Documents\Pycharm Files\Nlp\data\train_set.csv', sep='\t')

5.3 Count Vectors + RidgeClassifier

	利用sklearn中的CountVectorizer来实现统计每个字出现的次数这一步骤。
vectorizer = CountVectorizer(max_features=3000)     # 创建一个词袋分类实例
'''
CountVectorizer参数详解
    encodeing:默认编码为uft-8,分析器会以utf-8解码raw document
    ngram_range:词组切分的长度范围
    lowercase:过滤规则,标识token的正则表达式,需要设置analyzer == 'word',默认的正则表达式选择2个及以上的字母或数字
                作为token,标点符号默认当做token分隔符,而不会被当做token
    max_df:可以设置成范围0~1的浮点数(词出现次数与语料库文档数的百分比),也可以设置为没有范围限制的整数(词出现的次数)。
            它被当做一个阈值,当构造语料库关键词集的时候,如果某个词的document frequence大于max_df,这个词不会被当做关键词。
            如果参数给定了vocabulart,则max_df参数无效
    min_df:可以设置成范围0~1的浮点数(词出现次数与语料库文档数的百分比),也可以设置为没有范围限制的整数(词出现的次数)。
            它被当做一个阈值,当构造语料库关键词集的时候,如果某个词的document frequence小于min_df,这个词不会被当做关键词。
            如果参数给定了vocabulart,则min_df参数无效
    max_features:默认为None,可设为整数,对所有关键词的term frequency进行降序排序,只取前max_feature个作为关键词集
    vocabulary:默认为None,自动从输入文档中构建关键词集,也可以是一个字典或可迭代对象
    binary:默认为False,一个关键词在一篇文档中可能出现n次,如果binary=True,非零的n将全部置为1。
            适用于需要布尔值输入的离散概率模型
    dtype:使用CountVectorizer类的fit_transform()或transform()将得到一个文档词频矩阵,
            dtype可以设置这个矩阵的数值类型
'''
train_text = vectorizer.fit_transform(train_df['text'])

	可以看出,train_text返回了一个20W行3K列的稀疏矩阵,包含了每个句子是否含有3K高频词汇的信息,以压缩稀疏行格式存储55724165个元素。

5.4 创建岭回归分类模型的实例

clf = RidgeClassifier()
'''
使用岭回归应该是为了防止过拟合。
过程中通常都倾向于让权值尽可能小,最后构造一个所有参数都比较小的模型。
因为一般认为参数值小的模型比较简单,能适应不同的数据集,也在一定程度上避免了过拟合现象。
'''
	使用1W个训练集样本进行训练
clf.fit(train_text[:10000], train_df['label'].values[:10000])
	使用其余样本当测试集
val_pred = clf.predict(train_text[10000:])

5.5 使用f1_score作为预测评价标准

print(f1_score(train_df['label'].values[10000:], val_pred, average='macro'))
'''
f1_score:精确率和召回率的调和平均数,最大为1,最小为0
        TP(True Positive) - 判断为本类,实际是本类;
        TN(True Negative) - 判断为其他类,实际是其他类;
        FP(False Positive) - 判断为本类,实际是其他类;
        FN(False Negative) - 判断为其他类,实际是本类;
    精准度/查准率:指被分类器判断为正例中正样本的比重
        precision = TP / (TP + FP)
    召回率/查全率:指被分类器判断为正例的正样本占总的正样本的比重
        recall = TP / (TP + FN)
    准确率:指分类器对整个样本判断是否正确的比重
        accuracy = (TP + TN) / (TP + TN + FP + FN)
    f1_score认为精准率和召回率一样重要
        f1_score = (2 * precision * recall) / (precision + recall)

macro:分别计算每个类别的F1,然后做平均(各类别F1的权重相同),也即宏f1。
        当小类很重要时会出问题,因为该macro-averging方法是对性能的平均。
        另一方面,该方法假设所有分类都是一样重要的,因此macro-averaging方法会对小类的性能影响很大
'''

5.6 TF-IDF + RidgeClassifier

tfidf = TfidfVectorizer(ngram_range=(1, 3), max_features=3000)
'''
ngram_range为词组切分的长度范围,max_features为关键词集的个数
    具体可参考http://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction

TfidVectorizer类封装了CountVectorizer和TfidTransformer这两个类,同时具备这两个类的功能
    CountVectorizer类会将文本中的词语转化为词频矩阵,从而实现统计每个字出现的次数
    TfidTransformer类用于统计Vectorizer中每个词语的TFIDF值
        TF:Term Frequency - 词语频率
            TF(t) = 该词语在当前文档出现的次数 / 当前文档中词语的总数
        IDF:Inverse Document Frequency - 逆文档频率
            IDF(t) = log_e(语料库中文档的总数 / 出现该词语的文档总数)
'''
	用法和CountVectorizer一样
train_test = tfidf.fit_transform(train_df['text'])
'''
我这一步是在台式机上训练的,笔记本报内存不足错误
'''
	再创建一个岭回归分类器实例
clf2 = RidgeClassifier()
	同样,训练前1W个样本
clf2.fit(train_test[:10000], train_df['label'].values[:10000])

# 用剩余样本预测,并返回f1_score
val_pred_2 = clf2.predict(train_test[10000:])
print(f1_score(train_df['label'].values[10000:], val_pred_2, average='macro'))
'''
f1_score得分为0.875,比直接使用CountVectorizer提高了10分左右
'''
	为了可以在笔记本上运行,我调低了训练样本数量为15000个
train_df_small = pd.read_csv(r'D:\Users\Felixteng\Documents\Pycharm Files\Nlp\data\train_set.csv',
                             sep='\t', nrows=15000)
tfid_small = TfidfVectorizer(ngram_range=(1, 3), max_features=3000)
train_test_small = tfid_small.fit_transform(train_df_small['text'])
clf3 = RidgeClassifier()
clf3.fit(train_test_small[:10000], train_df_small['label'].values[:10000])
val_pred3 = clf3.predict(train_test_small[10000:])
print(f1_score(train_df_small['label'].values[10000:], val_pred3, average='macro'))
'''
分数为0.872%
'''
	尝试改变TF-IDF的参数,并验证精度
tfid_try_1 = TfidfVectorizer(ngram_range=(1, 2), max_features=3000)
train_try_1 = tfid_try_1.fit_transform(train_df_small['text'])
clf_try_1 = RidgeClassifier()
clf_try_1.fit(train_try_1[:10000], train_df_small['label'].values[:10000])
val_pred_try_1 = clf_try_1.predict(train_try_1[10000:])
print(f1_score(train_df_small['label'].values[10000:], val_pred_try_1, average='macro'))
	分数为0.872%,变化不大,尝试改变一下max_feature
tfid_try_2 = TfidfVectorizer(ngram_range=(1, 3), max_features=4000)
train_try_2 = tfid_try_2.fit_transform(train_df_small['text'])
clf_try_2 = RidgeClassifier()
clf_try_2.fit(train_try_2[:10000], train_df_small['label'].values[:10000])
val_pred_try_2 = clf_try_2.predict(train_try_2[10000:])
print(f1_score(train_df_small['label'].values[10000:], val_pred_try_2, average='macro'))
	分数为0.875,和全量样本跑出来一样,看来max_feature适当调大可以增加f1_score。
	试试再调大max_feature
tfid_try_3 = TfidfVectorizer(ngram_range=(1, 3), max_features=5000)
train_try_3 = tfid_try_3.fit_transform(train_df_small['text'])
clf_try_3 = RidgeClassifier()
clf_try_3.fit(train_try_3[:10000], train_df_small['label'].values[:10000])
val_pred_try_3 = clf_try_3.predict(train_try_3[10000:])
print(f1_score(train_df_small['label'].values[10000:], val_pred_try_3, average='macro'))
'''果然,分数又增高了,0.885'''
	换随机森林模型试试
rf1 = RandomForestClassifier()
rf1.fit(train_try_3[:10000], train_df_small['label'].values[:10000])
val_pred_rf = rf1.predict(train_try_3[10000:])
print(f1_score(train_df_small['label'].values[10000:], val_pred_rf, average='macro'))
'''
随机森林f1_score为80%左右,参数均为默认参数
'''

这里可以多尝试几种机器学习算法,如svm,xgboost等
下一章节将涉及深度学习文本分类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值