欢迎访问集智主站:集智,通向智能时代的引擎


回顾

上一节我们通过Scikit-learn提供的多种方法从网络以及硬盘获取到了原始的文本数据,并采用tf-idf方法成功地提取了文本特征,你可以从下面的例子中再次复习这一过程。

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer# 选取参与分析的文本类别
categories = ['alt.atheism', 'soc.religion.christian','comp.graphics', 'sci.med']
# 从硬盘获取原始数据
twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",categories=categories,load_content = True,encoding="latin1",decode_error="strict",shuffle=True, random_state=42)
# 统计词语出现次数
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(twenty_train.data)
# 使用tf-idf方法提取文本特征
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
# 打印特征矩阵规格
print(X_train_tfidf.shape)
复制代码

本节我们将在完成特征提取工作的基础上,继续完成文本信息挖掘的下一步——训练并优化分类器。

训练分类器

可以用于文本分类的机器学习算法有很多,朴素贝叶斯算法(Naïve Bayes)就是其中一个优秀代表。Scikit-learn包含了朴素贝叶斯算法的多种改进模型,最适于文本词数统计方面的模型叫做多项式朴素贝叶斯(Multinomial Naïve Bayes),它可以通过以下的方式来调用。

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
categories = ["alt.atheism", "soc.religion.christian","comp.graphics", "sci.med"]
twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",categories=categories,load_content = True,encoding="latin1",decode_error="strict",shuffle=True, random_state=42)
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(twenty_train.data)
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)[/amalthea_pre_exercise_code]
[amalthea_sample_code]
from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB().fit(X_train_tfidf, twenty_train.target)
print("分类器的相关信息:")
print(clf)
复制代码

这样就完成了一个分类器的训练过程。为了使用一个新文档来进行分类器的分类预测工作,我们必须使用同样的数据处理手段处理我们的新文档。如下面的例子所示,我们使用了一组自定义的字符串,用来判断它们的分类情况。字符串组必须经过transform方法的处理才能进行预测。

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
categories = ["alt.atheism", "soc.religion.christian","comp.graphics", "sci.med"]
twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",categories=categories,load_content = True,encoding="latin1",decode_error="strict",shuffle=True, random_state=42)
count_vect = CountVectorizer()
X_train_counts = count_vect.fit_transform(twenty_train.data)
tfidf_transformer = TfidfTransformer()
X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB().fit(X_train_tfidf, twenty_train.target)
# 预测用的新字符串,你可以将其替换为任意英文句子
docs_new = ["Nvidia is awesome!"]
# 字符串处理
X_new_counts = count_vect.transform(docs_new)
X_new_tfidf = tfidf_transformer.transform(X_new_counts)# 进行预测
predicted = clf.predict(X_new_tfidf)# 打印预测结果
for doc, category in zip(docs_new, predicted):print("%r => %s" % (doc, twenty_train.target_names[category]))
复制代码

作为受西方理论指导的一种基础的机器学习算法,朴素贝叶斯虽然很简单,有时候很朴素,但是它的运行速度非常的快,效果也非常的理想,能够跟很多更复杂的算法相提并论。

建立Pipeline

为了简化对于原始数据的清洗、特征提取以及分类过程,Scikit-learn提供了Pipeline类来实现一个整合式的分类器建立过程。分类器可以通过建立一个Pipeline的方式来实现,而各种特征提取、分类方法都可以在建立Pipeline的时候直接指定,从而大大提高编码和调试的效率,如下所示:

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
categories = ["alt.atheism", "soc.religion.christian","comp.graphics", "sci.med"]
twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",categories=categories,load_content = True,encoding="latin1",decode_error="strict",shuffle=True, random_state=42)[/amalthea_pre_exercise_code]
[amalthea_sample_code]
from sklearn.pipeline import Pipeline
# 建立Pipeline
text_clf = Pipeline([("vect", CountVectorizer()),("tfidf", TfidfTransformer()),("clf", MultinomialNB()),
])
# 训练分类器
text_clf = text_clf.fit(twenty_train.data, twenty_train.target)
# 打印分类器信息
print(text_clf)
复制代码

使用测试数据评估分类器性能

我们可以采用上述的方法对测试数据集进行预测,然后使用Numpy所提供的函数得到评测结果:

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
if "text_clf" not in dir() :categories = ["alt.atheism", "soc.religion.christian","comp.graphics", "sci.med"]twenty_train=load_files("/mnt/vol0/sklearn/20news-bydate-train",categories=categories,  load_content = True, encoding="latin1", decode_error="strict",shuffle=True, random_state=42)text_clf = Pipeline([("vect", CountVectorizer()),("tfidf", TfidfTransformer()),("clf", MultinomialNB()),])text_clf = text_clf.fit(twenty_train.data, twenty_train.target)
import numpy as np
# 获取测试数据
twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,load_content = True, encoding='latin1',decode_error='strict',shuffle=True, random_state=42)
docs_test = twenty_test.data
# 使用测试数据进行分类预测
predicted = text_clf.predict(docs_test)
# 计算预测结果的准确率
print("准确率为:")
print(np.mean(predicted == twenty_test.target))
复制代码

如果正常运行上述代码,我们应该可以得到83.4%的准确率。我们有很多办法来改进这个成绩,使用业界公认的最适于文本分类的算法——支持向量机(SVM,Support Vector Machine)就是一个很好的方向(虽然它会比朴素贝叶斯稍微慢一点)。我们可以通过改变Pipeline中分类器所指定的对象轻松地实现这一点:

import numpy as np
from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipelinecategories = ['alt.atheism', 'soc.religion.christian','comp.graphics', 'sci.med']
if 'twenty_train' not in dir() :twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)
if 'twenty_test' not in dir() :twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)docs_test = twenty_test.datafrom sklearn.linear_model import SGDClassifier
text_clf = Pipeline([('vect', CountVectorizer()),('tfidf', TfidfTransformer()),('clf', SGDClassifier(loss='hinge',penalty='l2',alpha=1e-3,n_iter=5,random_state=42)),])
_ = text_clf.fit(twenty_train.data, twenty_train.target)
predicted = text_clf.predict(docs_test)
print("准确率:")
print(np.mean(predicted == twenty_test.target))
复制代码

我们可以看到,相对于朴素贝叶斯,SVM方法得到的准确率有了很大的进步。

Scikit-learn提供了更多的评测工具来更好地帮助我们进行分类器的性能分析,如下所示,我们可以得到预测结果中关于每一种分类的准确率、召回率、F值等等以及它们的混淆矩阵。

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipelinecategories = ['alt.atheism', 'soc.religion.christian','comp.graphics', 'sci.med']
if 'predicted' not in dir() :twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)docs_test = twenty_test.datafrom sklearn.linear_model import SGDClassifiertext_clf = Pipeline([('vect', CountVectorizer()),('tfidf', TfidfTransformer()),('clf', SGDClassifier(loss='hinge', penalty='l2',alpha=1e-3, n_iter=5, random_state=42)),])_ = text_clf.fit(twenty_train.data, twenty_train.target)predicted = text_clf.predict(docs_test)
from sklearn import metrics
print("打印分类性能指标:")
print(metrics.classification_report(twenty_test.target, predicted,target_names=twenty_test.target_names))
print("打印混淆矩阵:")
metrics.confusion_matrix(twenty_test.target, predicted)
复制代码

不出所料,通过混淆矩阵我们可以发现,相对于计算机图形学(comp.graphics),与无神论(alt.atheism)以及基督教(soc.religion.christian)相关的两种分类更难以被区分出来。

使用网格搜索来进行参数优化

我们已经了解了很多机器学习过程中所遇到的参数,比如TfidfTransformer中的use_idf。分类器往往会拥有很多的参数,比如说朴素贝叶斯算法中包含平滑参数alpha,SVM算法会包含惩罚参数alpha以及其他一些可以设置的函数。

为了避免调整这一系列参数而带来的繁杂工作,我们可以使用网格搜索方法来寻找各个参数的最优值。如下面的例子所示,我们可以在采用SVM算法建立分类器时尝试设置如下参数:使用单词或是使用词组、使用IDF或是不使用IDF、惩罚参数为0.01或是0.001。

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipelinecategories = ['alt.atheism', 'soc.religion.christian','comp.graphics', 'sci.med']
if 'text_clf' not in dir() :twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)docs_test = twenty_test.datafrom sklearn.linear_model import SGDClassifiertext_clf = Pipeline([('vect', CountVectorizer()),('tfidf', TfidfTransformer()),('clf', SGDClassifier(loss='hinge', penalty='l2',alpha=1e-3, n_iter=5, random_state=42)),])
from sklearn.grid_search import GridSearchCV
# sklearn 0.18.1 版本请使用以下方式导入网格搜索库
# from sklearn.model_selection import GridSearchCV# 设置参与搜索的参数
parameters = {'vect__ngram_range': [(1, 1), (1, 2)],'tfidf__use_idf': (True, False),'clf__alpha': (1e-2, 1e-3),
}# 构建分类器
gs_clf = GridSearchCV(text_clf, parameters, n_jobs=-1)
print(gs_clf)
复制代码

很明显,逐个进行这样一个搜索过程会消耗较大的计算资源。如果我们拥有一个多核CPU平台,我们就可以并行计算这8个任务(每个参数有两种取值,三个参数共有个参数组合),这需要我们修改n_jobs这个参数。如果我们设置这个参数的值为-1,网格搜索过程将会自动检测计算环境所存在的CPU核心数量,并使用全部核心进行并行工作。

一个具体的网格搜索模型与普通的分类器模型一致,我们可以使用一个较小的子数据块来加快模型的训练过程。对GridSearchCV对象调用fit方法之后将得到一个与之前案例类似的分类器,我们可以使用这个分类器来进行预测。

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.grid_search import GridSearchCVcategories = ['alt.atheism', 'soc.religion.christian','comp.graphics', 'sci.med']
if 'gs_clf' not in dir() :twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)docs_test = twenty_test.datafrom sklearn.linear_model import SGDClassifiertext_clf = Pipeline([('vect', CountVectorizer()),('tfidf', TfidfTransformer()),('clf', SGDClassifier(loss='hinge', penalty='l2',alpha=1e-3, n_iter=5, random_state=42)),])parameters = {'vect__ngram_range': [(1, 1), (1, 2)],'tfidf__use_idf': (True, False),'clf__alpha': (1e-2, 1e-3),}gs_clf = GridSearchCV(text_clf, parameters, n_jobs=-1)
# 使用部分训练数据训练分类器
gs_clf = gs_clf.fit(twenty_train.data[:400], twenty_train.target[:400])
# 查看分类器对于新文本的预测结果,你可以自行改变下方的字符串来观察分类效果
twenty_train.target_names[gs_clf.predict(['An apple a day keeps doctor away'])[0]]
复制代码

分类器同时包含best_score_best_params_两个属性,这两个属性包含了最佳预测结果以及取得最佳预测结果时的参数配置。当然,我们也可以浏览gs_clf.cv_results_来获取更详细的搜索结果(这是sklearn 0.18.1版本新加入的特性),这个参数可以很容易地导入到pandas中进行更为深入的研究。

from sklearn.datasets import load_files
from sklearn.feature_extraction.text import CountVectorizer,TfidfTransformer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
from sklearn.grid_search import GridSearchCVcategories = ['alt.atheism', 'soc.religion.christian','comp.graphics', 'sci.med']
if 'gs_clf' not in dir() :twenty_train=load_files('/mnt/vol0/sklearn/20news-bydate-train',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)twenty_test=load_files('/mnt/vol0/sklearn/20news-bydate-test',categories=categories,  load_content = True, encoding='latin1', decode_error='strict',shuffle=True, random_state=42)docs_test = twenty_test.datafrom sklearn.linear_model import SGDClassifiertext_clf = Pipeline([('vect', CountVectorizer()),('tfidf', TfidfTransformer()),('clf', SGDClassifier(loss='hinge', penalty='l2',alpha=1e-3, n_iter=5, random_state=42)),])parameters = {'vect__ngram_range': [(1, 1), (1, 2)],'tfidf__use_idf': (True, False),'clf__alpha': (1e-2, 1e-3),}gs_clf = GridSearchCV(text_clf, parameters, n_jobs=-1)
gs_clf = gs_clf.fit(twenty_train.data[:400], twenty_train.target[:400])
print("最佳准确率:%r" % (gs_clf.best_score_))for param_name in sorted(parameters.keys()):print("%s: %r" % (param_name, gs_clf.best_params_[param_name]))
复制代码

小结

至此,我们已经完整实践了一个使用机器学习方法进行文本分类工作的全过程,我们了解了从网络获取数据并进行读取、清洗原始数据并提取特征向量、使用不同算法来构建分类器、并使用网格搜索方法来进行参数调优等有监督机器学习中较为常见的各个知识点。关于更为复杂的一些问题,比如中文文本处理、文本聚类分析等等,我们将在之后的文章中进行讨论。


(本篇课程内容来自于Scikit-Learn - Working With Text Data,转载请注明来源。)

推荐阅读

用PaddlePaddle调戏邮件诈骗犯(完结篇)

这评论有毒!——文本分类的一般套路

我做了一个叫“瑟曦”的机器人,可是她动不动就想让格雷果爵士弄死我。

[Scikit-learn教程] 03.02 文本处理:分类与优化相关推荐

  1. python 高维数据_用Sci-kit learn和XGBoost进行多类分类:Brainwave数据案例研究

    在机器学习中,高维数据的分类问题非常具有挑战性.有时候,非常简单的问题会因为这个"维度诅咒"问题变得非常复杂.在本文中,我们将了解不同分类器的准确性和性能是如何变化的. 理解数据 ...

  2. tensorflow笔记-文本情感分类

    本文是在学习tensorflow2.0官方教程时的一个笔记,原始教程请见文本情感分类 准备工作 1. 安装tensorflow并导入相关库 如果已经安装了可以略去此步 !pip install ten ...

  3. scikit - learn 做文本分类

    文章来源: https://my.oschina.net/u/175377/blog/84420 Scikit Learn: 在python中机器学习 Warning 警告:有些没能理解的句子,我以自 ...

  4. BERT实战(1):使用DistilBERT作为词嵌入进行文本情感分类,与其它词向量(FastText,Word2vec,Glove)进行对比

    这次根据一篇教程Jay Alammar: A Visual Guide to Using BERT for the First Time学习下如何在Pytorch框架下使用BERT. 主要参考了中文翻 ...

  5. 如何用Python和BERT做中文文本二元分类?| 程序员硬核评测

    点击上方↑↑↑蓝字关注我们~ 「2019 Python开发者日」全日程揭晓,请扫码咨询 ↑↑↑ 作者 | 王树义 来源 | 王树芝兰(ID:nkwangshuyi) 兴奋 去年, Google 的 B ...

  6. python scikit_Python SciKit学习教程

    python scikit Scikit学习 (Scikit Learn) Scikit-learn is a machine learning library for Python. It feat ...

  7. python笔迹识别_python_基于Scikit learn库中KNN,SVM算法的笔迹识别

    之前我们用自己写KNN算法[网址]识别了MNIST手写识别数据 [数据下载地址] 这里介绍,如何运用Scikit learn库中的KNN,SVM算法进行笔迹识别. 数据说明: 数据共有785列,第一列 ...

  8. 【scikit-learn】如何用Python和SciKit Learn 0.18实现神经网络

    本教程的代码和数据来自于 Springboard 的博客教程.本文的作者为 Jose Portilla,他是网络教育平台 Udemy 一门数据科学类课程的讲师. GitHub 链接:https://g ...

  9. Scikit Learn: 在python中机器学习

    Warning 警告:有些没能理解的句子,我以自己的理解意译. 翻译自:Scikit Learn:Machine Learning in Python 作者: Fabian Pedregosa, Ga ...

  10. python 多分类情感_文本情感分类(一):传统模型

    前言:四五月份的时候,我参加了两个数据挖掘相关的竞赛,分别是物电学院举办的"亮剑杯",以及第三届 "泰迪杯"全国大学生数据挖掘竞赛.很碰巧的是,两个比赛中,都有 ...

最新文章

  1. poj(2325)线段树
  2. 日本3D打印最贵牛肉!人工组装肌肉脂肪和血管,两天即完成,网友:赛博朋克的仿制肉...
  3. 两个大文件找出相同的一条记录
  4. 【Spark Summit EU 2016】摆脱传统ETL,让我们走向Spark吧!
  5. 怎么使用socket在云服务上通信步骤(可支持TCP或UDP)
  6. 【渝粤教育】电大中专微生物与寄生虫基础作业 题库
  7. (转)C++ main函数中参数argc和argv含义及用法
  8. asp.net 下载文件
  9. SSM-水果商城-pom.xml-学习-3
  10. employees mysql_「employees」mysql示例employees数据库 - seo实验室
  11. ActiveMQ下载和安装
  12. 力士乐电源模块故障代码_REXROTH DRIVE博士力士乐伺服驱动器故障代码大全
  13. Android系统最高的电视盒子,2019年电视盒子排行榜:市面上性能最强的电视盒子大盘点...
  14. 三菱PLC型号通讯接口汇总表 细分FX Q系列等 PLC数据采集实用知识点
  15. Vaa3d_DIADEM metric基本介绍_SWC拓扑结构量纲
  16. kafka-eagle 使用配置及远程jmx端口设置遇到的问题
  17. mysql设置不用科学记数法,关闭科学记数法MySQL
  18. 无法启动此程序,因为计算机中丢失MSVCRTD.dll(MFC42D.dll, MFCO42D.dll)
  19. NLP_learning 中文基本任务与处理(分词、停用词、词性标注、语句依存分析、关键词抽取、命名实体识别)介绍、jieba工具库
  20. 舆情监控和应急处理方案,如何做好网络舆情监控?

热门文章

  1. slack 聊天机器人_使用Node.js和Symanto的Text Analytics API在Slack中创建情感机器人
  2. java excel 操作方式_java excel兩種操作方式
  3. android期末课设选题_Android课程设计报告书.doc
  4. Matlab信号提取、频谱分析、滤波、阈值设定、寻找极值点
  5. android 导出数据库文件
  6. 经典原型链、继承解析
  7. 翻转一个数的二进制后的值
  8. 形象描述oracle是如何工作的--有点意思
  9. java中如何获得屏幕的宽度和高度,android-如何获取屏幕的宽度和高度
  10. android 弹幕礼物,Android的简易弹幕