scikit-learning教程(三)使用文本数据
使用文本数据
本指南的目标是探讨scikit-learn
一个实际任务中的一些主要工具:分析二十个不同主题的文本文档(新闻组帖子)集合。
在本节中,我们将看到如何:
- 加载文件内容和类别
- 提取适用于机器学习的特征向量
- 训练线性模型进行分类
- 使用网格搜索策略来查找特征提取组件和分类器的良好配置
教程设置
要开始使用本教程,您首先必须安装 scikit-learn及其所有必需的依赖项。
有关详细信息和每个系统的说明,请参阅安装说明页面。
本教程的源码可以在您的scikit-learn文件夹中找到:
scikit - learn / doc / tutorial / text_analytics /
该教程文件夹应包含以下文件夹:
*.rst files
- 使用sphinx编写的教程文档的源代码data
- 用于放置教程中使用的数据集的文件夹skeletons
- 练习的示例不完整脚本solutions
- 练习的解决方案
您可以将骨架复制到您的硬盘驱动器上的某个位置的新文件夹中sklearn_tut_workspace
,您将在其中编辑自己的文件以进行练习,同时保持原始的骨架不变:
% cp - r skeletonons work_directory / sklearn_tut_workspace
机器学习算法需要数据。转到每个$TUTORIAL_HOME/data
子文件夹并fetch_data.py
从那里运行脚本(首先阅读它们之后)。
例如:
%cd $ TUTORIAL_HOME / data / languages
%fetch_data.py
%python fetch_data.py
加载20个新闻组数据集
数据集称为“二十新闻组”。这是官方的说明,从网站引用:
20个新闻组数据集是大约20,000个新闻组文档的集合,在20个不同的新闻组中平均分配(几乎)。据我们所知,它最初是由肯朗收集的,可能是他的论文“Newsweeder:学习过滤网络新闻”,虽然他没有明确提及这个集合。20个新闻组集合已成为机器学习技术的文本应用中的实验的流行数据集,如文本分类和文本聚类。
在下面我们将使用内置的数据集加载器来从scikit学习的20个新闻组。或者,可以从网站手动下载数据集,并通过将该sklearn.datasets.load_files
功能指向20news-bydate-train
未压缩归档文件夹的子文件夹来使用该功能。
为了在第一个例子中获得更快的执行时间,我们将在数据集中的20个可用数据集中仅处理4个类别的部分数据集:
>>> categories = ['alt.atheism', 'soc.religion.christian',
... 'comp.graphics', 'sci.med']
我们现在可以加载与这些类别匹配的文件列表,如下所示:
>>> from sklearn.datasets import fetch_20newsgroups
>>> twenty_train = fetch_20newsgroups(subset='train',
... categories=categories, shuffle=True, random_state=42)
返回的数据集是一个scikit-learn
“束”:一个简单的持有者对象,其字段可以作为python dict
键或object
属性被方便地访问,例如 target_names
保存所请求的类别名称的列表:
>>> twenty_train.target_names
['alt.atheism', 'comp.graphics', 'sci.med', 'soc.religion.christian']
文件本身被加载到data
属性的内存中。作为参考,文件名也可用:
>>> len(twenty_train.data)
2257
>>> len(twenty_train.filenames)
2257
我们先打印第一个加载文件的第一行:
>>> print("\n".join(twenty_train.data[0].split("\n")[:3]))
From: sd345@city.ac.uk (Michael Collier)
Subject: Converting images to HP LaserJet III?
Nntp-Posting-Host: hampton >>> print(twenty_train.target_names[twenty_train.target[0]])
comp.graphics
受监督的学习算法将需要训练集中的每个文档的类别标签。在这种情况下,类别是新闻组的名称,它也恰好是保存单个文档的文件夹的名称。
为了速度和空间效率的原因,scikit-learn
将目标属性加载为与target_names
列表中类别名称的索引对应的整数数组。每个样本的类别整数id存储在target
属性中:
>>> twenty_train.target[:10]
array([1, 1, 3, 3, 3, 3, 3, 2, 2, 2])
可以如下回到类别名称:
>>> for t in twenty_train.target[:10]:
... print(twenty_train.target_names[t])
...
comp.graphics
comp.graphics
soc.religion.christian
soc.religion.christian
soc.religion.christian
soc.religion.christian
soc.religion.christian
sci.med
sci.med
sci.med
您可以注意到样品已经随机洗牌(使用固定的RNG种子):如果您仅选择第一个样品来快速培养模型并在完成数据集之前重新训练之前获得结果的第一个想法,这很有用。
从文本文件中提取特征
为了对文本文档执行机器学习,我们首先需要将文本内容转换为数字特征向量。
袋子
最直观的方式是这样做:
- 为训练集的任何文档中发生的每个单词分配一个固定的整数id(例如通过从单词到整数索引建立词典)。
- 对于每个文档
#i
,对每个单词的出现次数进行计数w
,并将其存储为特征值, 其中是词典中的单词索引X[i, j]
#j
j
w
词汇表示意味着n_features
语料库中不同单词的数量:这个数字通常大于100,000。
如果存储为float32类型的numpy数组将需要10000 x 100000 x 4字节= 4GB的RAM,这在今天的计算机上几乎不可管理。n_samples == 10000
X
幸运的是,X中的大多数值将为零,因为对于给定的文档,将少于几千个不同的单词将被使用。因此,我们说袋子里的单词通常是 高维稀疏数据集。通过将特征向量的非零部分存储在存储器中,可以节省大量的存储空间。
scipy.sparse
矩阵是完全这样做的数据结构,并且scikit-learn
内置了对这些结构的支持。
用表征文本scikit-learn
文本预处理,令牌化和过滤的无效词包含在高级组件中,能够构建特征字典并将文档转换为特征向量:
>>> from sklearn.feature_extraction.text import CountVectorizer
>>> count_vect = CountVectorizer()
>>> X_train_counts = count_vect.fit_transform(twenty_train.data)
>>> X_train_counts.shape
(2257, 35788)
CountVectorizer
支持N克单词或连续字符的计数。一旦装配,矢量化器已经建立了一个特征索引字典:
>>> count_vect.vocabulary_.get(u'algorithm')
4690
词汇中单词的索引值与其在整个训练语料库中的频率相关。
从出现到频率
发生次数是一个好的开始,但有一个问题:更长的文档将具有比较短的文档更高的平均值,即使他们可能会讨论相同的主题。
为了避免这些潜在的差异,将文档中每个单词的出现次数除以文档中的单词总数就足够了:这些新功能被称为tf
“术语频率”。
在tf之上的另一个改进是对在语料库中的许多文档中出现的单词进行缩减权重,因此比仅在较小部分语料库中发生的单词更少的信息量。
这个缩减被称为tf-idf,用于“Term Frequency times Inverse Document Frequency”。
两个TF和TF-IDF可以计算如下:
>>> from sklearn.feature_extraction.text import TfidfTransformer
>>> tf_transformer = TfidfTransformer(use_idf=False).fit(X_train_counts)
>>> X_train_tf = tf_transformer.transform(X_train_counts)
>>> X_train_tf.shape
(2257, 35788)
在上面的示例代码中,我们首先使用该fit(..)
方法将我们的估计器与数据进行匹配,其次是transform(..)
将我们的计数矩阵转换为tf-idf表示法的方法。通过跳过冗余处理,可以组合这两个步骤,以更快地实现相同的最终结果。这是通过使用fit_transform(..)
如下所示的方法完成的 ,如上一节中的注释所述:
>>> tfidf_transformer = TfidfTransformer()
>>> X_train_tfidf = tfidf_transformer.fit_transform(X_train_counts)
>>> X_train_tfidf.shape
(2257, 35788)
训练分类器
现在我们有了我们的功能,我们可以训练一个分类器来尝试预测一个职位的类别。让我们从一个朴素的贝叶斯 分类器开始,为这个任务提供了一个很好的基准。scikit-learn
包括该分类器的几个变体; 最适合单词计数的是多项式:
>>> from sklearn.naive_bayes import MultinomialNB
>>> clf = MultinomialNB().fit(X_train_tfidf, twenty_train.target)
为了尝试预测新文档的结果,我们需要使用与以前几乎相同的特征提取链来提取特征。不同的是,我们所说transform
的,而不是fit_transform
对变压器,因为它们已经适应训练集:
>>> docs_new = ['God is love', 'OpenGL on the GPU is fast']
>>> 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]))
...
'God is love' => soc.religion.christian
'OpenGL on the GPU is fast' => comp.graphics
建立管道
为了使vectorizer => transformer =>分类器更容易使用,scikit-learn
提供了一个Pipeline
类似复合分类器的类:
>>> from sklearn.pipeline import Pipeline
>>> text_clf = Pipeline([('vect', CountVectorizer()),
... ('tfidf', TfidfTransformer()),
... ('clf', MultinomialNB()),
... ])
名称vect
,tfidf
和clf
(分类)是任意的。我们将在下面的网格搜索部分看到他们的使用。我们现在可以用一个命令来训练模型:
>>> text_clf = text_clf.fit(twenty_train.data, twenty_train.target)
测试集上的性能评估
评估模型的预测准确性同样容易:
>>> import numpy as np
>>> twenty_test = fetch_20newsgroups(subset='test',
... categories=categories, shuffle=True, random_state=42)
>>> docs_test = twenty_test.data
>>> predicted = text_clf.predict(docs_test)
>>> np.mean(predicted == twenty_test.target)
0.834...
即,我们达到83.4%的准确度。让我们看看我们是否可以用线性支持向量机(SVM)来做得更好,这是广泛认为是最好的文本分类算法之一(尽管它也比初学贝叶斯慢一点)。我们可以通过将不同的分类对象插入到我们的管道中来改变学习者:
>>> from 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)
>>> np.mean(predicted == twenty_test.target)
0.912...
scikit-learn
进一步提供实用程序以更详细地对结果进行性能分析:
>>> from sklearn import metrics
>>> print(metrics.classification_report(twenty_test.target, predicted,
... target_names=twenty_test.target_names))
...
precision recall f1-score support alt.atheism 0.95 0.81 0.87 319
comp.graphics 0.88 0.97 0.92 389
sci.med 0.94 0.90 0.92 396
soc.religion.christian 0.90 0.95 0.93 398 avg / total 0.92 0.91 0.91 1502 >>> metrics.confusion_matrix(twenty_test.target, predicted)
array([[258, 11, 15, 35],
[ 4, 379, 3, 3],
[ 5, 33, 355, 3],
[ 5, 10, 4, 379]])
如预期的那样,混乱矩阵表明,无神论和基督教的新闻组的帖子比计算机图形更容易彼此混淆。
参数整定使用格搜索
我们已经遇到了一些参数,如use_idf
在 TfidfTransformer
。分类器也有许多参数; 例如,MultinomialNB
包括一个平滑参数alpha
, 并且在目标函数中SGDClassifier
具有惩罚参数alpha
和可配置的损失和惩罚项(参见模块文档,或使用Python help
函数来获取这些描述)。
而不是调整链的各种组件的参数,可以对可能值的网格上的最佳参数进行详尽的搜索。我们尝试使用或不使用idf的单词或双字母分隔符,对于线性SVM,可以使用0.01或0.001的惩罚参数:
>>> 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),
... }
显然,这种详尽的搜索可能是昂贵的。如果我们拥有多个CPU内核,我们可以告诉电网搜索者与参数并行地尝试这八个参数组合n_jobs
。如果我们给这个参数一个值-1
,网格搜索将会检测到安装了多少个内核并使用它们:
>>> gs_clf = GridSearchCV(text_clf, parameters, n_jobs=-1)
网格搜索实例的行为与普通scikit-learn
模型类似。让我们在较小的训练数据子集上进行搜索,以加速计算:
>>> gs_clf = gs_clf.fit(twenty_train.data[:400], twenty_train.target[:400])
调用的结果fit
一上GridSearchCV
对象的分类,我们可以用它来predict
:
>>> twenty_train.target_names[gs_clf.predict(['God is love'])[0]]
'soc.religion.christian'
对象best_score_
和best_params_
属性存储与该分数相对应的最佳平均分数和参数设置:
>>> gs_clf.best_score_
0.900...
>>> for param_name in sorted(parameters.keys()):
... print("%s: %r" % (param_name, gs_clf.best_params_[param_name]))
...
clf__alpha: 0.001
tfidf__use_idf: True
vect__ngram_range: (1, 1)
更详细的搜索摘要可在gs_clf.cv_results_
。
该cv_results_
参数可以很容易地导入熊猫作为 DataFrame
进一步检查。
练习
要做练习,将“skeleton”文件夹的内容复制为名为“workspace”的新文件夹:
% cp -r skeletons workspace
然后,您可以编辑工作区的内容,而不用担心丢失原始的运动说明。
然后启动一个ipython shell并运行正在进行的工作脚本:
[1] %run workspace/exercise_XX_script.py arg1 arg2 arg3
如果触发了异常,则可以使用%debug
来启动post mortem ipdb会话。
优化实施并重复运算直到练习解决。
对于每个练习,骨架文件提供了所有必需的导入语句,样板代码来加载数据和样本代码,以评估模型的预测准确性。
练习1:语言识别
- 使用自定义预处理器编写文本分类管道,并
CharNGramAnalyzer
使用维基百科文章中的数据作为培训集。 - 评估某些测试套件的性能。
ipython命令行:
%run workspace/exercise_01_language_train_model.py data/languages/paragraphs/
练习2:电影评论的情绪分析
- 写一个文本分类管道将电影评论分为正面或负面。
- 使用网格搜索找到一组好的参数。
- 评估一个持有的测试集的性能。
ipython命令行:
%run workspace/exercise_02_sentiment.py data/movie_reviews/txt_sentoken/
练习3:CLI文本分类实用程序
使用以前练习的结果和cPickle
标准库的模块,编写一个命令行实用程序,用于检测提供的一些文本的语言,stdin
并且如果文本用英语写成,则可以估计极性(正或负)。
奖金点,如果公用事业能够给出其预测的置信水平。
从这里到
以下是一些建议,以帮助您在完成本教程后进一步提高您的scikit学习直觉:
- 尝试玩弄
analyzer
和在下token normalisation
CountVectorizer
- 如果您没有标签,请尝试 在您的问题上使用 Clustering。
- 如果每个文档有多个标签,例如类别,请查看多类和多标签部分
- 尝试使用截断的SVD进行 潜在语义分析。
- 看看使用 核心外分类来学习不适合计算机主内存的数据。
- 看看哈希向量化器 作为一种高效的记忆效能
CountVectorizer
。
使用文本数据
本指南的目标是探讨scikit-learn
一个实际任务中的一些主要工具:分析二十个不同主题的文本文档(新闻组帖子)集合。
在本节中,我们将看到如何:
- 加载文件内容和类别
- 提取适用于机器学习的特征向量
- 训练线性模型进行分类
- 使用网格搜索策略来查找特征提取组件和分类器的良好配置
教程设置
要开始使用本教程,您首先必须安装 scikit-learn及其所有必需的依赖项。
有关详细信息和每个系统的说明,请参阅安装说明页面。
本教程的源码可以在您的scikit-learn文件夹中找到:
scikit - learn / doc / tutorial / text_analytics /
该教程文件夹应包含以下文件夹:
*.rst files
- 使用sphinx编写的教程文档的源代码data
- 用于放置教程中使用的数据集的文件夹skeletons
- 练习的示例不完整脚本solutions
- 练习的解决方案
您可以将骨架复制到您的硬盘驱动器上的某个位置的新文件夹中sklearn_tut_workspace
,您将在其中编辑自己的文件以进行练习,同时保持原始的骨架不变:
% cp - r skeletonons work_directory / sklearn_tut_workspace
机器学习算法需要数据。转到每个$TUTORIAL_HOME/data
子文件夹并fetch_data.py
从那里运行脚本(首先阅读它们之后)。
例如:
%cd $ TUTORIAL_HOME / data / languages
%fetch_data.py
%python fetch_data.py
加载20个新闻组数据集
数据集称为“二十新闻组”。这是官方的说明,从网站引用:
20个新闻组数据集是大约20,000个新闻组文档的集合,在20个不同的新闻组中平均分配(几乎)。据我们所知,它最初是由肯朗收集的,可能是他的论文“Newsweeder:学习过滤网络新闻”,虽然他没有明确提及这个集合。20个新闻组集合已成为机器学习技术的文本应用中的实验的流行数据集,如文本分类和文本聚类。
在下面我们将使用内置的数据集加载器来从scikit学习的20个新闻组。或者,可以从网站手动下载数据集,并通过将该sklearn.datasets.load_files
功能指向20news-bydate-train
未压缩归档文件夹的子文件夹来使用该功能。
为了在第一个例子中获得更快的执行时间,我们将在数据集中的20个可用数据集中仅处理4个类别的部分数据集:
>>> 类别 = [ 'alt.atheism' , 'soc.religion.christian' ,
... 'comp.graphics' , ' sci.med ' ]
我们现在可以加载与这些类别匹配的文件列表,如下所示:
>>> from sklearn.datasets import fetch_20newsgroups
>>> twenty_train = fetch_20newsgroups (subset = 'train' ,
... categories = categories , shuffle = True , random_state = 42 )
返回的数据集是一个scikit-learn
“束”:一个简单的持有者对象,其字段可以作为python dict
键或object
属性被方便地访问,例如 target_names
保存所请求的类别名称的列表:
>>> twenty_train 。target_names
['alt.atheism','comp.graphics','sci.med','soc.religion.christian']
文件本身被加载到data
属性的内存中。作为参考,文件名也可用:
>>> LEN (twenty_train 。数据)
2257
>>> LEN (twenty_train 。文件名)
2257
我们先打印第一个加载文件的第一行:
>>> 打印(“ \ n ” 。加入(twenty_train 。数据[ 0 ] 。分裂(“ \ n ” )[:3 ]))
来自:sd345@city.ac.uk(迈克尔科利尔)
主题:将图像转换为HP LaserJet III?
Nntp-Posting-Host:汉普顿 >>> 打印(twenty_train 。target_names [ twenty_train 。靶向[ 0 ]])
comp.graphics
受监督的学习算法将需要训练集中的每个文档的类别标签。在这种情况下,类别是新闻组的名称,它也恰好是保存单个文档的文件夹的名称。
为了速度和空间效率的原因,scikit-learn
将目标属性加载为与target_names
列表中类别名称的索引对应的整数数组。每个样本的类别整数id存储在target
属性中:
>>> twenty_train 。目标[:10 ]
阵列([1,1,3,3,3,3,3,2,2,2])
可以如下回到类别名称:
>>> 用于 吨 在 twenty_train 。目标[:10 ]:
... 打印(twenty_train 。target_names [ 吨])
...
comp.graphics
comp.graphics
soc.religion.christian
soc.religion.christian
soc.religion.christian
soc.religion.christian
soc.religion .christian
sci.med
sci.med
sci.med
您可以注意到样品已经随机洗牌(使用固定的RNG种子):如果您仅选择第一个样品来快速培养模型并在完成数据集之前重新训练之前获得结果的第一个想法,这很有用。
从文本文件中提取特征
为了对文本文档执行机器学习,我们首先需要将文本内容转换为数字特征向量。
袋子
最直观的方式是这样做:
- 为训练集的任何文档中发生的每个单词分配一个固定的整数id(例如通过从单词到整数索引建立词典)。
- 对于每个文档
#i
,对每个单词的出现次数进行计数w
,并将其存储为特征值, 其中是词典中的单词索引X[i, j]
#j
j
w
词汇表示意味着n_features
语料库中不同单词的数量:这个数字通常大于100,000。
如果存储为float32类型的numpy数组将需要10000 x 100000 x 4字节= 4GB的RAM,这在今天的计算机上几乎不可管理。n_samples == 10000
X
幸运的是,X中的大多数值将为零,因为对于给定的文档,将少于几千个不同的单词将被使用。因此,我们说袋子里的单词通常是 高维稀疏数据集。通过将特征向量的非零部分存储在存储器中,可以节省大量的存储空间。
scipy.sparse
矩阵是完全这样做的数据结构,并且scikit-learn
内置了对这些结构的支持。
用表征文本scikit-learn
文本预处理,令牌化和过滤的无效词包含在高级组件中,能够构建特征字典并将文档转换为特征向量:
>>> from sklearn.feature_extraction.text import CountVectorizer
>>> count_vect = CountVectorizer ()
>>> X_train_counts = count_vect 。fit_transform (twenty_train 。数据)
>>> X_train_counts 。形状
(2257,35788)
CountVectorizer
支持N克单词或连续字符的计数。一旦装配,矢量化器已经建立了一个特征索引字典:
>>> count_vect 。vocabulary_ 。得到(ü “算法” )
4690
词汇中单词的索引值与其在整个训练语料库中的频率相关。
从出现到频率
发生次数是一个好的开始,但有一个问题:更长的文档将具有比较短的文档更高的平均值,即使他们可能会讨论相同的主题。
为了避免这些潜在的差异,将文档中每个单词的出现次数除以文档中的单词总数就足够了:这些新功能被称为tf
“术语频率”。
在tf之上的另一个改进是对在语料库中的许多文档中出现的单词进行缩减权重,因此比仅在较小部分语料库中发生的单词更少的信息量。
这个缩减被称为tf-idf,用于“Term Frequency times Inverse Document Frequency”。
两个TF和TF-IDF可以计算如下:
>>> from sklearn.feature_extraction.text import TfidfTransformer
>>> tf_transformer = TfidfTransformer (use_idf = False )。fit (X_train_counts )
>>> X_train_tf = tf_transformer 。transform (X_train_counts )
>>> X_train_tf 。形状
(2257,35788)
在上面的示例代码中,我们首先使用该fit(..)
方法将我们的估计器与数据进行匹配,其次是transform(..)
将我们的计数矩阵转换为tf-idf表示法的方法。通过跳过冗余处理,可以组合这两个步骤,以更快地实现相同的最终结果。这是通过使用fit_transform(..)
如下所示的方法完成的 ,如上一节中的注释所述:
>>> tfidf_transformer = TfidfTransformer ()
>>> X_train_tfidf = tfidf_transformer 。fit_transform (X_train_counts )
>>> X_train_tfidf 。形状
(2257,35788)
训练分类器
现在我们有了我们的功能,我们可以训练一个分类器来尝试预测一个职位的类别。让我们从一个朴素的贝叶斯 分类器开始,为这个任务提供了一个很好的基准。scikit-learn
包括该分类器的几个变体; 最适合单词计数的是多项式:
>>> 从 sklearn.naive_bayes 导入 MultinomialNB
>>> CLF = MultinomialNB () 。适合(X_train_tfidf , twenty_train 。目标)
为了尝试预测新文档的结果,我们需要使用与以前几乎相同的特征提取链来提取特征。不同的是,我们所说transform
的,而不是fit_transform
对变压器,因为它们已经适应训练集:
>>> docs_new = [ 'God is love' , 'OpenGL on the GPU is fast' ]
>>> X_new_counts = count_vect 。transform (docs_new )
>>> X_new_tfidf = tfidf_transformer 。变换(X_new_counts ) >>> 预测 = CLF 。预测(X_new_tfidf ) >>> 为 DOC , 类别 在 拉链(docs_new , 预测):
... 打印(' %R => %S ' % (DOC , twenty_train 。target_names [ 类别]))
...
'神是爱'=> soc.religion.christian'GPU上
的OpenGL很快'=> comp.graphics
建立管道
为了使vectorizer => transformer =>分类器更容易使用,scikit-learn
提供了一个Pipeline
类似复合分类器的类:
>>> 从 sklearn.pipeline 进口 管道
>>> text_clf = 管道([('VECT' , CountVectorizer ()),
... ('TFIDF' , TfidfTransformer ()),
... ('CLF' , MultinomialNB ( )),
... ])
名称vect
,tfidf
和clf
(分类)是任意的。我们将在下面的网格搜索部分看到他们的使用。我们现在可以用一个命令来训练模型:
>>> text_clf = text_clf 。配合(twenty_train 。数据, twenty_train 。目标)
测试集上的性能评估
评估模型的预测准确性同样容易:
>>> import numpy as np
>>> twenty_test = fetch_20newsgroups (subset = 'test' ,
... categories = categories , shuffle = True , random_state = 42 )
>>> docs_test = twenty_test 。数据
>>> 预测 = text_clf 。预测(docs_test )
>>> np 。
即,我们达到83.4%的准确度。让我们看看我们是否可以用线性支持向量机(SVM)来做得更好,这是广泛认为是最好的文本分类算法之一(尽管它也比初学贝叶斯慢一点)。我们可以通过将不同的分类对象插入到我们的管道中来改变学习者:
])>>> _ = text_clf 。配合(twenty_train 。数据,twenty_train 。目标)>>> 预测= text_clf 。预测(docs_test )>>> np 。意思是(预测== twenty_test 。目标)0.912 ... 目标)>>> 预测= text_clf 。预测(docs_test )>>> np 。意思是(预测== twenty_test 。目标)0.912 ... 目标)>>> 预测= text_clf 。预测(docs_test )>>> np 。意思是(预测== twenty_test 。目标)0.912 ...
scikit-learn
进一步提供实用程序以更详细地对结果进行性能分析:
>>> 从 sklearn 进口 度量
>>> 打印(度量。classification_report (twenty_test 。目标, 预测,
... target_names = twenty_test 。target_names ))
...
精度召回F1-得分支持 替代性主义0.95 0.81 0.87 319
comp.graphics 0.88 0.97 0.92 389
sci.med 0.94 0.90 0.92 396
soc.religion.christian 0.90 0.95 0.93 398 平均/总0.92 0.91 0.91 1502 >>> 指标。confusion_matrix (twenty_test 。目标, 预测)
阵列([[258,11,15,35],
[4,379,3,3],
[5,33,355,3],
[5,10,4,379] ])
如预期的那样,混乱矩阵表明,无神论和基督教的新闻组的帖子比计算机图形更容易彼此混淆。
参数整定使用格搜索
我们已经遇到了一些参数,如use_idf
在 TfidfTransformer
。分类器也有许多参数; 例如,MultinomialNB
包括一个平滑参数alpha
, 并且在目标函数中SGDClassifier
具有惩罚参数alpha
和可配置的损失和惩罚项(参见模块文档,或使用Python help
函数来获取这些描述)。
而不是调整链的各种组件的参数,可以对可能值的网格上的最佳参数进行详尽的搜索。我们尝试使用或不使用idf的单词或双字母分隔符,对于线性SVM,可以使用0.01或0.001的惩罚参数:
>>> 从 sklearn.model_selection 进口 GridSearchCV
>>> 参数 = { 'vect__ngram_range' : [(1 , 1 ), (1 , 2 )],
... 'tfidf__use_idf' :( 真,假),... ' clf__alpha” :(1E-2 ,1E-3 ),... }
显然,这种详尽的搜索可能是昂贵的。如果我们拥有多个CPU内核,我们可以告诉电网搜索者与参数并行地尝试这八个参数组合n_jobs
。如果我们给这个参数一个值-1
,网格搜索将会检测到安装了多少个内核并使用它们:
>>> gs_clf = GridSearchCV (text_clf , parameters , n_jobs = - 1 )
网格搜索实例的行为与普通scikit-learn
模型类似。让我们在较小的训练数据子集上进行搜索,以加速计算:
>>> gs_clf = gs_clf 。适合(twenty_train 。数据[:400 ], twenty_train 。目标[:400 ])
调用的结果fit
一上GridSearchCV
对象的分类,我们可以用它来predict
:
>>> twenty_train 。target_names [ gs_clf 。预测([ '上帝是爱' ])[ 0 ]]
'soc.religion.christian'
对象best_score_
和best_params_
属性存储与该分数相对应的最佳平均分数和参数设置:
>>> gs_clf 。best_score_
0.900 ...
>>> 为 PARAM_NAME 在 排序(参数。键()):
... 打印(“ %S :%R ” % (PARAM_NAME , gs_clf 。best_params_ [ PARAM_NAME ]))
...
clf__alpha:0.001
tfidf__use_idf:True
vect__ngram_range:(1,1)
更详细的搜索摘要可在gs_clf.cv_results_
。
该cv_results_
参数可以很容易地导入熊猫作为 DataFrame
进一步检查。
练习
要做练习,将“skeleton”文件夹的内容复制为名为“workspace”的新文件夹:
% cp - r 骨架 工作区
然后,您可以编辑工作区的内容,而不用担心丢失原始的运动说明。
然后启动一个ipython shell并运行正在进行的工作脚本:
[ 1 ] %run workspace / exercise_XX_script 。py arg1 arg2 arg3
如果触发了异常,则可以使用%debug
来启动post mortem ipdb会话。
优化实施并重复运算直到练习解决。
对于每个练习,骨架文件提供了所有必需的导入语句,样板代码来加载数据和样本代码,以评估模型的预测准确性。
练习1:语言识别
- 使用自定义预处理器编写文本分类管道,并
CharNGramAnalyzer
使用维基百科文章中的数据作为培训集。 - 评估某些测试套件的性能。
ipython命令行:
%run workspace / exercise_01_language_train_model 。py 数据/ 语言/ 段落/
练习2:电影评论的情绪分析
- 写一个文本分类管道将电影评论分为正面或负面。
- 使用网格搜索找到一组好的参数。
- 评估一个持有的测试集的性能。
ipython命令行:
%run workspace / exercise_02_sentiment 。py data / movie_reviews / txt_sentoken /
练习3:CLI文本分类实用程序
使用以前练习的结果和cPickle
标准库的模块,编写一个命令行实用程序,用于检测提供的一些文本的语言,stdin
并且如果文本用英语写成,则可以估计极性(正或负)。
奖金点,如果公用事业能够给出其预测的置信水平。
从这里到
以下是一些建议,以帮助您在完成本教程后进一步提高您的scikit学习直觉:
- 尝试玩弄
analyzer
和在下token normalisation
CountVectorizer
- 如果您没有标签,请尝试 在您的问题上使用 Clustering。
- 如果每个文档有多个标签,例如类别,请查看多类和多标签部分
- 尝试使用截断的SVD进行 潜在语义分析。
- 看看使用 核心外分类来学习不适合计算机主内存的数据。
- 看看哈希向量化器 作为一种高效的记忆效能
CountVectorizer
。
scikit-learning教程(三)使用文本数据的更多相关文章
- CRL快速开发框架系列教程三(更新数据)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
- 基础学习总结(三)--文本、SD卡数据读写
简单的文本数据写入文件不需要权限,读写SD卡在4.0版本前需要写权限.在4.0后需要读写权限 布局: <LinearLayout xmlns:android="http://schem ...
- Deep learning:三十八(Stacked CNN简单介绍)
http://www.cnblogs.com/tornadomeet/archive/2013/05/05/3061457.html 前言: 本节主要是来简单介绍下stacked CNN(深度卷积网络 ...
- 如何使用 scikit-learn 为机器学习准备文本数据
欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 文本数据需要特殊处理,然后才能开始将其用于预测建模. 我们需要解析文本,以删除被称为标记化的单词.然后,这些词还需要被编码为整型或浮点型,以用作 ...
- NLP相关问题中文本数据特征表达初探
1. NLP问题简介 0x1:NLP问题都包括哪些内涵 人们对真实世界的感知被成为感知世界,而人们用语言表达出自己的感知视为文本数据.那么反过来,NLP,或者更精确地表达为文本挖掘,则是从文本数据出发 ...
- Deep Learning 教程翻译
Deep Learning 教程翻译 非常激动地宣告,Stanford 教授 Andrew Ng 的 Deep Learning 教程,于今日,2013年4月8日,全部翻译成中文.这是中国屌丝军团,从 ...
- Hand on Machine Learning第三章课后作业(1):垃圾邮件分类
import os import email import email.policy 1. 读取邮件数据 SPAM_PATH = os.path.join( "E:\\3.Study\\机器 ...
- Elasticsearch入门教程(三):Elasticsearch索引&映射
原文:Elasticsearch入门教程(三):Elasticsearch索引&映射 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文 ...
- CRL快速开发框架系列教程九(导入/导出数据)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
随机推荐
- 格式转换至yuv422转 yuv420
//pYUV为422,yuv为420 /*ok! * brief:pyuv is yuv422sp srcIn, and yuv is yuv420p desOut */ int YUV422To4 ...
- 在HDInsight中的Hadoop介绍
在HDInsight中的Hadoop介绍 概览 Azure的HDInsight是,部署和规定的Apache™Hadoop®集群在云中,提供用于管理,分析和大数据报告软件框架中的服务. 大数据 数据被描 ...
- poj 1015 Jury Compromise(背包+方案输出)
\(Jury Compromise\) \(solution:\) 这道题很有意思,它的状态设得很...奇怪.但是它的数据范围实在是太暴露了.虽然当时还是想了好久好久,出题人设了几个限制(首先要两个的 ...
- js对table操作(添加删除交换上下TR)
<table width="100%" border="0" cellpadding="2" cellspacing="1& ...
- 安卓AndroidManifest.xml介绍
先说一下,我的开发环境为Eclipse 3.7.1 + Android SDK + Android 1.5(API level3) Android最大的一个特点,就是用xml文件来配置,这个演习了Ja ...
- Linux内核中工作队列的使用work_struct,delayed_work【转】
本文转载自:http://blog.csdn.net/zahuopuboss/article/details/43268983 初始化工作队列 调度工作队列 取消工作队列 #include <l ...
- POJ2516 Minimum Cost —— 最小费用最大流
题目链接:https://vjudge.net/problem/POJ-2516 Minimum Cost Time Limit: 4000MS Memory Limit: 65536K Tota ...
- 项目中Redis分库
Redis中有16个库 默认第0个库 配置库的设置: 不同的库 key可以重复哈 公司的多个不同分布式项目,但是只有一个redis时候,以项目方式区分不同的库 每个项目连接相同 但是库不同
- 织梦CMS首页、列表页文章如何调出该文章TAG标签?
1.如果是dedecms v5.7版本直接使用标签 [field:id function=GetTags(@me)/] 就可以调用出来了.只不过不带连接的. 2.如果需要连接请注释掉include/h ...
- COGS-2049 疯狂动物城
Description 你意外来到了一个未知的星球, 这里是一个动物乌托邦, 生活着一群拥有非凡智力的动物. 你遇到了一个叫做尼克的狐狸, 他准备给他的 GF 过生日 . 他将制作一个巨大的多层蛋糕, ...