task3-基于机器学习的文本分类
学习目标
-
学会TF-IDF的原理和使用
-
使用sklearn的机器学习模型完成文本分类
文本表示方法 Part1
- One-hot
这里的One-hot与数据挖掘任务中的操作是一致的,即将每一个单词使用一个离散的向量表示。具体将每个字/词编码一个索引,然后根据索引进行赋值。
One-hot表示方法的例子如下:
句子1:我 爱 北 京 天 安 门
句子2:我 喜 欢 上 海
首先对所有句子的字进行索引,即将每个字确定一个编号:
{
‘我’: 1, ‘爱’: 2, ‘北’: 3, ‘京’: 4, ‘天’: 5,
‘安’: 6, ‘门’: 7, ‘喜’: 8, ‘欢’: 9, ‘上’: 10, ‘海’: 11
}
在这里共包括11个字,因此每个字可以转换为一个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]
- 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与Count Vectors类似,不过加入了相邻单词组合成为新的单词,并进行计数。
如果N取值为2,则句子1和句子2就变为:
句子1:我爱 爱北 北京 京天 天安 安门
句子2:我喜 喜欢 欢上 上海
- TF-IDF
TF-IDF 分数由两部分组成:第一部分是词语频率(Term Frequency),第二部分是逆文档频率(Inverse Document Frequency)。其中计算语料库中文档总数除以含有该词语的文档数量,然后再取对数就是逆文档频率。
TF(t)= 该词语在当前文档出现的次数 / 当前文档中词语的总数
IDF(t)= log_e(文档总数 / 出现该词语的文档总数)
基于机器学习的文本分类
接下来我们将对比不同文本表示算法的精度,通过本地构建验证集计算F1得分。
# 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行,前1w行进行训练,后5k行用来测试
train_df = pd.read_csv('train_set.csv', sep='\t', nrows=15000)
# 向量化
vectorizer = CountVectorizer(max_features=3000)
train_test = vectorizer.fit_transform(train_df['text'])
# 加载Ridge分类器
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.65441877581244
# 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
# 读取数据,前15000行,前1w行进行训练,后5k行用来测试
train_df = pd.read_csv('train_set.csv', sep='\t', nrows=15000)
# tf-idf 向量化
tfidf = TfidfVectorizer(ngram_range=(1,3), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])
# 加载Ridge分类器
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.8719098297954606
作业:
- 改变TF-IDF的参数,并验证精度
- 使用其他机器学习模型,完成训练和验证
- 改变tf-idf参数,ngram_range=(1,4),精确度变化不大。
# 改变tf-idf参数
tfidf = TfidfVectorizer(ngram_range=(1,4), max_features=3000)
train_test = tfidf.fit_transform(train_df['text'])
# 加载Ridge分类器
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.8736955495856327
- 使用其他模型:
# tf-idf + 朴素贝叶斯、逻辑回归、随机森林
from sklearn.naive_bayes import MultinomialNB as NB
from sklearn.linear_model.logistic import LogisticRegression as LR
from sklearn.ensemble import RandomForestClassifier as RF
def text_classifier(train_feature_list, test_feature_list, train_class_list, test_class_list, flag):
if flag == 'nb':
# 朴素贝叶斯分类器 拟合 默认拉普拉斯平滑 不指定先验概率先验概率
classifier = NB().fit(train_feature_list, train_class_list)
if flag == 'lg':
# 逻辑回归分类器 指定liblinear为求解最优化问题的算法 最大迭代数 多分类问题策略
classifier = LR(solver='liblinear',max_iter=5000, multi_class='auto').fit(train_feature_list, train_class_list)
if flag == 'rf':
# 随机森林分类器
classifier = RF(n_estimators=200).fit(train_feature_list, train_class_list)
test_accuracy = classifier.score(test_feature_list, test_class_list) # 测试准确率
return test_accuracy
def start(flag):
train_feature_list, test_feature_list, train_class_list, test_class_list = train_test[:10000], train_test[10000:], train_df['label'].values[:10000],train_df['label'].values[10000:]
if flag == 'nb':
test_accuracy = text_classifier(train_feature_list, test_feature_list, train_class_list, test_class_list, flag='nb')
if flag == 'lg':
test_accuracy = text_classifier(train_feature_list, test_feature_list, train_class_list, test_class_list, flag='lg')
if flag == 'rf':
test_accuracy = text_classifier(train_feature_list, test_feature_list, train_class_list, test_class_list, flag='rf')
print(flag + '准确度:', test_accuracy)
start('nb')
start('lg')
start('rf')
nb准确度: 0.8266
lg准确度: 0.8882
rf准确度: 0.8748
一点点想法:字符被编码了无法使用停用词表,如果自己根据词频做一个停用词表,把高频词去掉,不知道效果会不会变好。有时间试试o( ̄▽ ̄)ブ。
本文地址:https://blog.csdn.net/weixin_42517469/article/details/107579099
上一篇: 荐 基于逻辑回归预测贷款违约
下一篇: C、C++语言容易出错的几个地方
推荐阅读
-
hadoop JOB的性能优化实践 博客分类: 数据挖掘&机器学习
-
Combiner 出现的问题 博客分类: 数据挖掘&机器学习
-
hadoop JOB的性能优化实践 博客分类: 数据挖掘&机器学习
-
数据分析中的分词 博客分类: 数据挖掘&机器学习
-
Combiner 出现的问题 博客分类: 数据挖掘&机器学习
-
数据分析中的分词 博客分类: 数据挖掘&机器学习
-
tf-idf的问题 博客分类: 数据挖掘&机器学习
-
【机器学习】西瓜书_周志华,python实现基于信息熵进行划分选择的决策树算法
-
关键词抽取(keywords extraction)的相关研究 博客分类: 自然语言处理机器学习&数据挖掘 算法 关键词抽取
-
互联网时代的社会语言学:基于SNS的文本数据挖掘 博客分类: 大数据处理自然语言处理 数据挖掘互联网sns