机器学习模型使用技巧、特征提升、模型正则化 、模型校验、超参数搜索

3.1 模型使用技巧

通常情况下,并不能保证:
1.所有用于训练的数据特征都是最好的
2.学习得到的参数一定是最优的
3.默认配置下的模型总是最佳的
所以提升模型的性能很关键,这其中通常包括预处理数据、控制参数训练以及优化模型的配置等方法。

3.1.1 特征提升

我们通常希望对数据特征的抽取或者筛选出来达到提升模型性能的目的。所谓的特征抽取,就是逐条将原始数据转换为特征向量的形式,这个过程同时设计对数据特征的量化表示;而特征筛选则更进一步,在高纬度、以量化的特征向量中选择对指定任务更有效的特征组合,进一步提升模型性能。

3.1.1.1 特征抽取

原始数据的种类有很多种,除了数字化的信息数据,还有大量的符号化的文本,然而我们无法直接将符号化的文本本身用于计算任务,而是需要通过某些处理手段,预先将文本量化为特征向量。

有些用符号表示的数据特征已经相对的机构化了,并用字典这种数据结构进行存储,这时,我们可以使用DictVectorizer对特征进行抽取和向量化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# DictVectorizer对使用字典存储的数据进行特征抽取与向量化
# 定义一组字典列表,用来表示多个数据样本(每个字典代表一个数据样本)。
measurements = [{'city': 'Dubai', 'temperature': 33.}, {'city': 'London', 'temperature': 12.}, {'city': 'San Fransisco', 'temperature': 18.}]
# 从sklearn.feature_extraction 导入 DictVectorizer
from sklearn.feature_extraction import DictVectorizer
# 初始化DictVectorizer特征抽取器
vec = DictVectorizer()
# 输出转化之后的特征矩阵。
print vec.fit_transform(measurements).toarray()
# 输出各个维度的特征含义。
print vec.get_feature_names()
[[ 1. 0. 0. 33.]
[ 0. 1. 0. 12.]
[ 0. 0. 1. 18.]]
['city=Dubai', 'city=London', 'city=San Fransisco', 'temperature']

由上述代码可知,DictVectorizer对于类别型与数值型特征的处理方式由很大的差异。由于类别性特征无法直接数字化显示,因此需要借助原特征的名称,组合产生新的特征并采用0/1的二值方式进行量化,而数值型的特征转换则相对方便,一般情况下只需要维持原始特征值即可。

如果是村文本形式的存储,都是一系列的字符串,处理这些数据的时候常用的文本特征表示方法为词袋法,不考虑词语的出现顺序,只是将训练文本中的每个出现过的词汇单独的视作一列特征,我们称这些不重复的词汇集合为词表。于是每条训练文本都可以在高纬度的词表上映射出一个特征向量。而特征数值的常见计算方式为2种,分别是: CountVectorizer和TfidiVectorizer,对于每一条训练文本,CountVectorizer只考虑每种词汇在该条训练文本中出现的频率,而TfidiVectorizer除了考量某一词汇在当前文本中出现的频率之外,同时关注包含这个词汇的文本数条数的倒数(Inverse Document Frequency)。相比之下训练文本的条数越多,TfidiVectorizer这种特征量化方式就更有优势。因为我们的目的就是找出所在的文本含义更有贡献的重要词汇。如果一个词几乎在每个文本中都要出现,说明这是一个常用的词汇,反而不会帮助模型对文本的分类,在训练文本量较多的时候,利用TfidiVectorizer压制这些常用词汇对分类决策的干扰,往往可以起到提高模型性能的作用。

我们通常称这些在每条文本中都出现的常用词汇为停用词(Stop Words),如英文中的the、a等。这些停用词在文本特征抽取中经常以黑名单的方式过滤掉,并且提高模型的性能表现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 使用CountVectorizer并且不去掉停用词的条件下,对文本特征进行量化的朴素贝叶斯分类性能测试
## sklearn.datasets里导入20类新闻文本数据抓取器。
from sklearn.datasets import fetch_20newsgroups
# 从互联网上即时下载新闻样本,subset='all'参数代表下载全部近2万条文本存储在变量news中。
news = fetch_20newsgroups(subset='all')
# 从sklearn.cross_validation导入train_test_split模块用于分割数据集。
from sklearn.cross_validation import train_test_split
# 对news中的数据data进行分割,25%的文本用作测试集;75%作为训练集。
X_train, X_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25, random_state=33)
# 从sklearn.feature_extraction.text里导入CountVectorizer
from sklearn.feature_extraction.text import CountVectorizer
# 采用默认的配置对CountVectorizer进行初始化(默认配置不去除英文停用词),并且赋值给变量count_vec。
count_vec = CountVectorizer()
# 只使用词频统计的方式将原始训练和测试文本转化为特征向量。
X_count_train = count_vec.fit_transform(X_train)
X_count_test = count_vec.transform(X_test)
# 从sklearn.naive_bayes里导入朴素贝叶斯分类器。
from sklearn.naive_bayes import MultinomialNB
# 使用默认的配置对分类器进行初始化。
mnb_count = MultinomialNB()
# 使用朴素贝叶斯分类器,对CountVectorizer(不去除停用词)后的训练样本进行参数学习。
mnb_count.fit(X_count_train, y_train)
# 输出模型准确性结果。
print 'The accuracy of classifying 20newsgroups using Naive Bayes (CountVectorizer without filtering stopwords):', mnb_count.score(X_count_test, y_test)
# 将分类预测的结果存储在变量y_count_predict中。
y_count_predict = mnb_count.predict(X_count_test)
# 从sklearn.metrics 导入 classification_report。
from sklearn.metrics import classification_report
# 输出更加详细的其他评价分类性能的指标。
print classification_report(y_test, y_count_predict, target_names = news.target_names)
The accuracy of classifying 20newsgroups using Naive Bayes (CountVectorizer without filtering stopwords): 0.839770797963
precision recall f1-score support
alt.atheism 0.86 0.86 0.86 201
comp.graphics 0.59 0.86 0.70 250
comp.os.ms-windows.misc 0.89 0.10 0.17 248
comp.sys.ibm.pc.hardware 0.60 0.88 0.72 240
comp.sys.mac.hardware 0.93 0.78 0.85 242
comp.windows.x 0.82 0.84 0.83 263
misc.forsale 0.91 0.70 0.79 257
rec.autos 0.89 0.89 0.89 238
rec.motorcycles 0.98 0.92 0.95 276
rec.sport.baseball 0.98 0.91 0.95 251
rec.sport.hockey 0.93 0.99 0.96 233
sci.crypt 0.86 0.98 0.91 238
sci.electronics 0.85 0.88 0.86 249
sci.med 0.92 0.94 0.93 245
sci.space 0.89 0.96 0.92 221
soc.religion.christian 0.78 0.96 0.86 232
talk.politics.guns 0.88 0.96 0.92 251
talk.politics.mideast 0.90 0.98 0.94 231
talk.politics.misc 0.79 0.89 0.84 188
talk.religion.misc 0.93 0.44 0.60 158
avg / total 0.86 0.84 0.82 4712

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# 使用TfidiVectorizer并且不去掉停用词的条件下,对文本特征进行量化的朴素贝叶斯分类性能测试
# 从sklearn.feature_extraction.text里分别导入TfidfVectorizer。
from sklearn.feature_extraction.text import TfidfVectorizer
# 采用默认的配置对TfidfVectorizer进行初始化(默认配置不去除英文停用词),并且赋值给变量tfidf_vec。
tfidf_vec = TfidfVectorizer()
# 使用tfidf的方式,将原始训练和测试文本转化为特征向量。
X_tfidf_train = tfidf_vec.fit_transform(X_train)
X_tfidf_test = tfidf_vec.transform(X_test)
# 依然使用默认配置的朴素贝叶斯分类器,在相同的训练和测试数据上,对新的特征量化方式进行性能评估。
mnb_tfidf = MultinomialNB()
mnb_tfidf.fit(X_tfidf_train, y_train)
print 'The accuracy of classifying 20newsgroups with Naive Bayes (TfidfVectorizer without filtering stopwords):', mnb_tfidf.score(X_tfidf_test, y_test)
y_tfidf_predict = mnb_tfidf.predict(X_tfidf_test)
print classification_report(y_test, y_tfidf_predict, target_names = news.target_names)
The accuracy of classifying 20newsgroups with Naive Bayes (TfidfVectorizer without filtering stopwords): 0.846349745331
precision recall f1-score support
alt.atheism 0.84 0.67 0.75 201
comp.graphics 0.85 0.74 0.79 250
comp.os.ms-windows.misc 0.82 0.85 0.83 248
comp.sys.ibm.pc.hardware 0.76 0.88 0.82 240
comp.sys.mac.hardware 0.94 0.84 0.89 242
comp.windows.x 0.96 0.84 0.89 263
misc.forsale 0.93 0.69 0.79 257
rec.autos 0.84 0.92 0.88 238
rec.motorcycles 0.98 0.92 0.95 276
rec.sport.baseball 0.96 0.91 0.94 251
rec.sport.hockey 0.88 0.99 0.93 233
sci.crypt 0.73 0.98 0.83 238
sci.electronics 0.91 0.83 0.87 249
sci.med 0.97 0.92 0.95 245
sci.space 0.89 0.96 0.93 221
soc.religion.christian 0.51 0.97 0.67 232
talk.politics.guns 0.83 0.96 0.89 251
talk.politics.mideast 0.92 0.97 0.95 231
talk.politics.misc 0.98 0.62 0.76 188
talk.religion.misc 0.93 0.16 0.28 158
avg / total 0.87 0.85 0.84 4712
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# 使用CountVectorizer和TfidiVectorizer并且去掉停用词的条件下,对文本特征进行量化的朴素贝叶斯分类性能测试
# 继续沿用代码56与代码57中导入的工具包(在同一份源代码中,或者不关闭解释器环境),分别使用停用词过滤配置初始化CountVectorizer与TfidfVectorizer。
count_filter_vec, tfidf_filter_vec = CountVectorizer(analyzer='word', stop_words='english'), TfidfVectorizer(analyzer='word', stop_words='english')
# 使用带有停用词过滤的CountVectorizer对训练和测试文本分别进行量化处理。
X_count_filter_train = count_filter_vec.fit_transform(X_train)
X_count_filter_test = count_filter_vec.transform(X_test)
# 使用带有停用词过滤的TfidfVectorizer对训练和测试文本分别进行量化处理。
X_tfidf_filter_train = tfidf_filter_vec.fit_transform(X_train)
X_tfidf_filter_test = tfidf_filter_vec.transform(X_test)
# 初始化默认配置的朴素贝叶斯分类器,并对CountVectorizer后的数据进行预测与准确性评估。
mnb_count_filter = MultinomialNB()
mnb_count_filter.fit(X_count_filter_train, y_train)
print 'The accuracy of classifying 20newsgroups using Naive Bayes (CountVectorizer by filtering stopwords):', mnb_count_filter.score(X_count_filter_test, y_test)
y_count_filter_predict = mnb_count_filter.predict(X_count_filter_test)
# 初始化另一个默认配置的朴素贝叶斯分类器,并对TfidfVectorizer后的数据进行预测与准确性评估。
mnb_tfidf_filter = MultinomialNB()
mnb_tfidf_filter.fit(X_tfidf_filter_train, y_train)
print 'The accuracy of classifying 20newsgroups with Naive Bayes (TfidfVectorizer by filtering stopwords):', mnb_tfidf_filter.score(X_tfidf_filter_test, y_test)
y_tfidf_filter_predict = mnb_tfidf_filter.predict(X_tfidf_filter_test)
# 对上述两个模型进行更加详细的性能评估。
from sklearn.metrics import classification_report
print classification_report(y_test, y_count_filter_predict, target_names = news.target_names)
print classification_report(y_test, y_tfidf_filter_predict, target_names = news.target_names)
The accuracy of classifying 20newsgroups using Naive Bayes (CountVectorizer by filtering stopwords): 0.863752122241
The accuracy of classifying 20newsgroups with Naive Bayes (TfidfVectorizer by filtering stopwords): 0.882640067912
precision recall f1-score support
alt.atheism 0.85 0.89 0.87 201
comp.graphics 0.62 0.88 0.73 250
comp.os.ms-windows.misc 0.93 0.22 0.36 248
comp.sys.ibm.pc.hardware 0.62 0.88 0.73 240
comp.sys.mac.hardware 0.93 0.85 0.89 242
comp.windows.x 0.82 0.85 0.84 263
misc.forsale 0.90 0.79 0.84 257
rec.autos 0.91 0.91 0.91 238
rec.motorcycles 0.98 0.94 0.96 276
rec.sport.baseball 0.98 0.92 0.95 251
rec.sport.hockey 0.92 0.99 0.95 233
sci.crypt 0.91 0.97 0.93 238
sci.electronics 0.87 0.89 0.88 249
sci.med 0.94 0.95 0.95 245
sci.space 0.91 0.96 0.93 221
soc.religion.christian 0.87 0.94 0.90 232
talk.politics.guns 0.89 0.96 0.93 251
talk.politics.mideast 0.95 0.98 0.97 231
talk.politics.misc 0.84 0.90 0.87 188
talk.religion.misc 0.91 0.53 0.67 158
avg / total 0.88 0.86 0.85 4712
precision recall f1-score support
alt.atheism 0.86 0.81 0.83 201
comp.graphics 0.85 0.81 0.83 250
comp.os.ms-windows.misc 0.84 0.87 0.86 248
comp.sys.ibm.pc.hardware 0.78 0.88 0.83 240
comp.sys.mac.hardware 0.92 0.90 0.91 242
comp.windows.x 0.95 0.88 0.91 263
misc.forsale 0.90 0.80 0.85 257
rec.autos 0.89 0.92 0.90 238
rec.motorcycles 0.98 0.94 0.96 276
rec.sport.baseball 0.97 0.93 0.95 251
rec.sport.hockey 0.88 0.99 0.93 233
sci.crypt 0.85 0.98 0.91 238
sci.electronics 0.93 0.86 0.89 249
sci.med 0.96 0.93 0.95 245
sci.space 0.90 0.97 0.93 221
soc.religion.christian 0.70 0.96 0.81 232
talk.politics.guns 0.84 0.98 0.90 251
talk.politics.mideast 0.92 0.99 0.95 231
talk.politics.misc 0.97 0.74 0.84 188
talk.religion.misc 0.96 0.29 0.45 158
avg / total 0.89 0.88 0.88 4712

从上面可以知道使用TdifiCectorizer比CountVectorizer在不去掉停用词的时候,对训练和测试文本就行特征量化,并利用默认配置的朴素贝叶斯分类器,在测试文本上可以得到TdifiVectorizer可以得到更高的准确率。而且平均精度、召回率和F1指标也都有提升。去掉停用词的时候效果更加好。
TdifiVectorizer的特征抽取和量化方法更加具备优势,使用停用词比不用停用词的模型综合性能要高.

3.1.1.2 特征筛选

良好的数据特征组合不需要太多,就可以是的模型的性能表现突出。冗余的特征虽然不会影响到模型的性能,不过却是的CPU的计算做了无用功,二不良的特征还会降低模型的精度,所以特征的筛选很重要。

特征筛选与PCA这类通过选择主成分特征进行重建的方法略有区别:对于PCA而言,我们经常无法解释重建之后的特征,但是特征筛选不存在对特征值的修改,更加侧重于寻找那些对模型的性能提升较大的少量特征。

3.1.2 模型正则化

通常我们需要重视模型的繁华里,也就是对未知的数据能有更好的适应能力表现能力,防止过拟合或者欠拟合。而通过正则化的方式可以加强模型的泛化力,避免模型过拟合。

3.1.2.1 欠拟合与过拟合

拟合就是指机器学习模型在训练过程中,通过更新参数,使得模型不断的契合可以观测数据(训练集)的过程。
一次多项式

二次多项式

四次多项式

准确度对比

如出现以上情况,当模型复杂度很低的时候Degree=1时,模型不仅没有对训练集上的数据有良好的拟合状态,而且在测试数据集上也表现平平,这种状态叫欠拟合(Underfitting),但是如果一味追求很高的模型复杂度如Degree=4的时候,尽管模型几乎完全的拟合了所有的训练数据,但是模型也会变得非常波动,几乎丧失了对未知数据的预测能力,这种情况叫做过拟合(Overfitting),这两种情况都是缺乏模型泛化力的表现。

为了能够在增加模型复杂度提高在训练集数据上表现性能的同时,又能够兼顾模型的泛化力,防止发生过拟合,平衡这个两难问题,采用模型正则化的方法,

3.1.2.2 L 1 范数正则化


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#Lasso。
lasso_poly4 = Lasso()
# 从使用Lasso对4次多项式特征进行拟合。
lasso_poly4.fit(X_train_poly4, y_train)
# 对Lasso模型在测试样本上的回归性能进行评估。
print lasso_poly4.score(X_test_poly4, y_test)
# 从sklearn.linear_model中导入Lasso。
from sklearn.linear_model import Lasso
# 从使用默认配置初始化Lasso。
lasso_poly4 = Lasso()
# 从使用Lasso对4次多项式特征进行拟合。
lasso_poly4.fit(X_train_poly4, y_train)
# 对Lasso模型在测试样本上的回归性能进行评估。
print lasso_poly4.score(X_test_poly4, y_test)
0.83889268736
# 输出Lasso模型的参数列表。
print lasso_poly4.coef_
[ 0.00000000e+00 0.00000000e+00 1.17900534e-01 5.42646770e-05
-2.23027128e-04]
# 回顾普通4次多项式回归模型过拟合之后的性能。
print regressor_poly4.score(X_test_poly4, y_test)
0.809588079578
# 回顾普通4次多项式回归模型的参数列表。
print regressor_poly4.coef_
[[ 0.00000000e+00 -2.51739583e+01 3.68906250e+00 -2.12760417e-01
4.29687500e-03]]
# 输出普通4次多项式回归模型的参数列表。
print regressor_poly4.coef_
[[ 0.00000000e+00 -2.51739583e+01 3.68906250e+00 -2.12760417e-01
4.29687500e-03]]
# 输出上述这些参数的平方和,验证参数之间的巨大差异。
print np.sum(regressor_poly4.coef_ ** 2)
647.382645692

Lass使得4次3次多项式的特征参数都为0,使得特征更为稀疏,并且调高了模型的性能。

3.1.2.3 L 2 范数正则化

L2也是增加惩罚项也叫ridge

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 从sklearn.linear_model导入Ridge。
from sklearn.linear_model import Ridge
# 使用默认配置初始化Riedge。
ridge_poly4 = Ridge()
# 从sklearn.linear_model导入Ridge。
from sklearn.linear_model import Ridge
# 使用默认配置初始化Riedge。
ridge_poly4 = Ridge()
# 使用Ridge模型对4次多项式特征进行拟合。
ridge_poly4.fit(X_train_poly4, y_train)
# 输出Ridge模型在测试样本上的回归性能。
print ridge_poly4.score(X_test_poly4, y_test)
0.837420175937
# 输出Ridge模型的参数列表,观察参数差异。
print ridge_poly4.coef_
[[ 0. -0.00492536 0.12439632 -0.00046471 -0.00021205]]
# 计算Ridge模型拟合后参数的平方和。
print np.sum(ridge_poly4.coef_ ** 2)
0.0154989652036

ridge模型你和后参数之间的差异非常的小,不论是Lasso还是ridge的惩罚项中都会有一个因子兰布达进行调节,尽管其不属于拟合的参数,但是却有着非常重要的作用。

3.1.3 模型检验

3.1.3.1 留一验证

就是从任务提供的数据中,随机采样一定比例作为训练集,剩下的留作验证。一般取得比例为7:3,或者4:1,即70%作为训练集,30%作为测试集进行模型验证。这一验证方法不是很稳定,原因在于对验证集合随机采样的不确定性。

3.1.3.2 交叉验证

交叉验证可以理解为多次留意验证的集合的过程,只是每次检验所使用的验证集之间是互斥的,并且要保证每一条可用数据都被模型验证过。例如5折验证就是全部可用数据被随机的分割为平均数量的5组,每次迭代都选取其中的1组数据作为验证集, 其它4组作为训练集。交叉验证的好处在于可用保证所有的数据都有被训练和验证的机会,也尽最大可能让优化的模型性能保险的更加可信。

3.1.4 超参数搜索

模型中的一些重要参数,我们常常称为模型的超参数,如K邻近算法中的K值,支持向量机中的不同核函数等。

3.1.4.1 网格搜索

由于超参数的空间是无尽的,因此超参数的组合配置只能是更优解,没有最优解。通常情况下,我们依靠网格搜索对多种超参数组合的空间进行暴力搜索,每一条超参数组合被代入到学习函数中作为新的模型,并且为了比较新模型之间的性能,每个模型都会采用交叉验证的方法在多组相同的训练和开发数据集下进行评估。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 从sklearn.datasets中导入20类新闻文本抓取器。
from sklearn.datasets import fetch_20newsgroups
# 导入numpy,并且重命名为np。
import numpy as np
# 使用新闻抓取器从互联网上下载所有数据,并且存储在变量news中。
news = fetch_20newsgroups(subset='all')
# 从sklearn.cross_validation导入train_test_split用来分割数据。
from sklearn.cross_validation import train_test_split
# 对前3000条新闻文本进行数据分割,25%文本用于未来测试。
X_train, X_test, y_train, y_test = train_test_split(news.data[:3000], news.target[:3000], test_size=0.25, random_state=33)
# 导入支持向量机(分类)模型。
from sklearn.svm import SVC
# 导入TfidfVectorizer文本抽取器。
from sklearn.feature_extraction.text import TfidfVectorizer
# 导入Pipeline。
from sklearn.pipeline import Pipeline
#使用Pipeline 简化系统搭建流程,将文本抽取与分类器模型串联起来。
clf = Pipeline([('vect', TfidfVectorizer(stop_words='english', analyzer='word')), ('svc', SVC())])
# 这里需要试验的2个超参数的的个数分别是4、3, svc__gamma的参数共有10^-2, 10^-1... 。这样我们一共有12种的超参数组合,12个不同参数下的模型。
parameters = {'svc__gamma': np.logspace(-2, 1, 4), 'svc__C': np.logspace(-1, 1, 3)}
# 从sklearn.grid_search中导入网格搜索模块GridSearchCV。
from sklearn.grid_search import GridSearchCV
# 将12组参数组合以及初始化的Pipline包括3折交叉验证的要求全部告知GridSearchCV。请大家务必注意refit=True这样一个设定 。
gs = GridSearchCV(clf, parameters, verbose=2, refit=True, cv=3)
# 执行单线程网格搜索。
%time _= gs.fit(X_train, y_train)
gs.best_params_, gs.best_score_
# 输出最佳模型在测试集上的准确性。
print gs.score(X_test, y_test)


共3x4=12组超参数,再乘以3折交叉验证共36项独立运行的计算任务。

3.1.4.2 并行搜索

网格搜索结合交叉验证来寻找超参数组合比较耗时,然而一旦获得了比较好的参数组合,都可以保持一段时间的使用,因此是非常值得推荐的提升方法,而且各个新模型在执行交叉验证的过程中间都是相互独立的,所以我们可以充分利用多核处理器,甚至是分布式的计算资源来从事并行搜索,这样就可以节省时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#使用多个线程对文本分类的朴素贝叶斯模型的超参数组合执行并行化的网格搜索
# 从sklearn.datasets中导入20类新闻文本抓取器。
from sklearn.datasets import fetch_20newsgroups
# 导入numpy,并且重命名为np。
import numpy as np
# 使用新闻抓取器从互联网上下载所有数据,并且存储在变量news中。
news = fetch_20newsgroups(subset='all')
# 从sklearn.cross_validation导入train_test_split用来分割数据。
from sklearn.cross_validation import train_test_split
# 对前3000条新闻文本进行数据分割,25%文本用于未来测试。
X_train, X_test, y_train, y_test = train_test_split(news.data[:3000], news.target[:3000], test_size=0.25, random_state=33)
# 导入支持向量机(分类)模型。
from sklearn.svm import SVC
# 导入TfidfVectorizer文本抽取器。
from sklearn.feature_extraction.text import TfidfVectorizer
# 导入Pipeline。
from sklearn.pipeline import Pipeline
#使用Pipeline 简化系统搭建流程,将文本抽取与分类器模型串联起来。
clf = Pipeline([('vect', TfidfVectorizer(stop_words='english', analyzer='word')), ('svc', SVC())])
# 这里需要试验的2个超参数的的个数分别是4、3, svc__gamma的参数共有10^-2, 10^-1... 。这样我们一共有12种的超参数组合,12个不同参数下的模型。
parameters = {'svc__gamma': np.logspace(-2, 1, 4), 'svc__C': np.logspace(-1, 1, 3)}
# 从sklearn.grid_search中导入网格搜索模块GridSearchCV。
from sklearn.grid_search import GridSearchCV
# 初始化配置并行网格搜索,n_jobs=-1代表使用该计算机全部的CPU。
gs = GridSearchCV(clf, parameters, verbose=2, refit=True, cv=3, n_jobs=-1)
# 执行多线程并行网格搜索。
%time _= gs.fit(X_train, y_train)
gs.best_params_, gs.best_score_
# 输出最佳模型在测试集上的准确性。
print gs.score(X_test, y_test)

坚持原创技术分享,您的支持将鼓励我继续创作!