SVM系列目录:
支持向量机SVM③——通过4种核函数进行波斯顿房价回归预测
支持向量机SVM②——文本分类实战(SVM&KNN&贝叶斯&决策树)
本来想先写一篇支持向量机的原理篇,结果在白天钻研,晚上做梦都在思考的2周后,还是没有搞太明白,实在是见识到了人类智慧的博大精深和自我的渺小。因此我还是先从应用下手,先用到慢慢体会好了。本篇主要介绍sklearn库的svm的分类和回归参数,其中重点介绍四大核函数的参数。
之前在未调参的情况下将svm和决策树、贝叶斯进行了分类对比,发现训练器分数巨低,且训练过程时间是真的长,长到怀疑人生。所以想要SVM用得好,会调参真的是很重要,很重要,很重要!!!(
文末有大礼赠送
)
一、分类
二、回归
SVM回归算法库的重要参数大部分和分类算法库类似,因此这里重点讲述和分类算法库不同的部分
三、参数注意事项
①对训练数据和测试数据最好都做归一化
②如果特征非常多,或者样本数远少于特征数时,数据更偏向线性可分,用线性核函数效果就会很好
③优先选择线性核函数,如果拟合不好同,再推荐默认的高斯(rbf),因为高斯需要通过交叉验证选择适合的惩罚系数C和gamma
④理论上高斯不会比线性核差,但是高斯需要花非常多的时间在调参上,实际业务中能用线性就用线性
四、GridSearchCV调参实例
① 用sklearn数据生成器生成特征数为2的圆环型数据
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm,datasets
from sklearn.svm import SVC
from sklearn.datasets import make_moons,make_circles,make_classification
X, y = make_circles(noise=0.2, factor=0.5, random_state=1) # make_circles是环形,noise是加一点噪音,factor是两个圆形的距离
from sklearn.preprocessing import StandardScaler
X = StandardScaler().fit_transform(X) # StandardScaler 可以通过对训练集生成一个转换器,然后可以同时转化训练集和测试集,测试集直接用transform就好了
②使用线性核函数,默认参数
# 先使用线性核函数
clf = LinearSVC()
clf.fit(X,y)
print('线性核函数模型评分:',clf.score(X,y))
在未调参情况下,评分非常低,只有0.48,调参如下:
from sklearn.model_selection import GridSearchCV
grid = GridSearchCV(LinearSVC(), param_grid={'C':np.linspace(0.1,10,50)}, cv=4) # SVC默认是高斯核,高斯核函数有2个参数c和gamma,CV 是将训练集分成多少从来进行交叉验证
grid.fit(X,y)
print('grid_best_params:', grid.best_params_)
print('grid.best_score_:', grid.best_score_)
调参后最佳C值为0.1,但是分数只提升了0.1,说明数据是线性不可分的,需要尝试其它非线性核函数,先分别对高斯,多项式和sigmoid核函数进行调参,结果如下:
param_grid=[{"kernel":["rbf"],"C":[0.1, 1, 10], "gamma": [1, 0.1, 0.01]},
{"kernel":["poly"],"C": [0.1, 1, 10], "gamma": [1, 0.1, 0.01],"degree":[3,5,10],"coef0":[0,0.1,1]},
{"kernel":["sigmoid"], "C": [0.1, 1, 10], "gamma": [1, 0.1, 0.01],"coef0":[0,0.1,1]}]
grid = GridSearchCV(SVC(), param_grid=param_grid, cv=4)
grid.fit(X,y)
print('grid_best_params:', grid.best_params_)
print('grid.best_score_:', grid.best_score_)
最佳的核函数是高斯(rbf),且分数达到了0.91,相对线性核函数翻了一倍
为了更清楚地看到调参过程对分类的影响,对调参的分类结果进行可视化,先看下原始数据:
ax = plt.subplot()
ax.set_title('data')
ax.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.summer)
ax.set_xticks(())
ax.set_yticks(())
plt.tight_layout() #自动调节子图参数,使之填充整个区域
plt.show()
for i, kernel in enumerate(('rbf','poly','sigmoid')):
for j ,C in enumerate((0.1, 1)): # 对于一个序列或者列表,既要遍历索引又要遍历元素时,将下标和列表中的内容组成一个tutle().还可以enumerate(序列,1),这样下标会从1开始
for k, gamma in enumerate((1, 0.1)):
plt.subplot()
clf = SVC(kernel=kernel, C=C, gamma=gamma)
clf.fit(X, y)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) # x.shape(3),y.shape(2),xx,yy.shape(2,3),np.c_,shape(6),xx = [[1,2,3],[3,5,7]],yy=[[2,3,4],[5,3,2]],xx.ravel()=[1,2,3,3,5,7],yy.ravel=[2,3,4,5,3,2],np.c_=[[1,2],[2,],[]]
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8)
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.coolwarm)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.xlabel('kernel='+str(kernel)+' gamma=' + str(gamma) + ' C=' + str(C))
plt.show()
由于原始数据是环形,在增加了噪音后基本偏向于圆形分布,因此高斯是更适合的。从图像上也能看出,高斯分类效果高于任一一张多项式分布的,这里加上一张sigmoid的,也是要比高斯差一些
本人互联网数据分析师,目前已出Excel,SQL,Pandas,Matplotlib,Seaborn,机器学习,统计学,个性推荐,关联算法,工作总结系列。
微信搜索 "
数据小斑马
" 公众号,回复“
数据分析
"就可以
免费领取
数据分析升级打怪
15本必备教材
喔