机器学习——SVM之交叉验证对参数(C,gamma)进行优化以及选择

目录

一、(C,gamma)简介

二、交叉验证

1、什么是交叉验证?

2、参数优化方法

3、python实现交叉验证cross_val_score(网格搜索算法GridSearchCV)

1)关键代码

2)sklearn中的cross_val_score()函数参数

3)AX3D三维绘图

4)ravel函数

5)完整代码


 

 

前面写了一篇关于参数(C,gamma)的文章,但是只是从感性上去说明了一下参数对模型和结果的影响,但没有说明如何对参数(C,gamma)进行选择。因此写下这篇。

一、(C,gamma)简介

对于SVM模型,最主要的参数就是C和gamma,C被称为惩罚因子,越大说明对错误的容忍度越小,可能发生过拟合(overfitting),C太小可能会导致容错率过高,这样的模型就没有意义了。

对于C和gamma参数的确定,一般是通过交叉验证的方法来进行确定的,大概思路就是将C和gamma参数在一定地取值范围内按照一定的步长(默认为1)进行取值组合,在不同(C,gamma)的组合下,将训练集样本均分成k组,一组作为验证的数据样本,其余k-1组则用来作为训练的数据,每一组数据都轮流着作为验证数据样本,这样在一组(C,gamma)组合下,就需要进行K次计算,把这K次计算的模型测试准确率score的均值作为这组(C,gamma)下模型的得分。这样的话就能够得到不同(C,gamma)组合下模型的得分,取得分最高的那组(C,gamma)即可,如果碰到有相同分的,一般考虑参数C,取C小的,因为在保证模型的准确率的情况下,C越小模型容错率大,可以避免过拟合,若C也相同,则取先出现的那一组gamma

 

二、交叉验证

1、什么是交叉验证?

主要使用k-fold Cross Validation(记为k-CV)

就是将训练样本集进行均分,比如将训练样本集均分为k组,称为k折,每次k-1折进行训练,另一折用于验证,每一组数据轮换作为验证数据。这里验证的是模型的识别率(accuracy)。在每一组(C,gamma)下对每一折数据进行轮换验证,这就是交叉验证,一般折数越多,越精确,但是计算的时间就会增加,需要在效率和精度之间进行权衡。

将C和gamma参数在一定地取值范围内按照一定的步长(默认为1)进行取值组合,在不同(C,gamma)的组合下,将训练集样本均分成k组,一组作为验证的数据样本,其余k-1组则用来作为训练的数据,每一组数据都轮流着作为验证数据样本,这样在一组(C,gamma)组合下,就需要进行K次计算,把这K次计算的模型测试准确率score的均值作为这组(C,gamma)下模型的得分。这样的话就能够得到不同(C,gamma)组合下模型的得分,取得分最高的那组(C,gamma)即可,如果碰到有相同分的,一般考虑参数C,取C小的,因为在保证模型的准确率的情况下,C越小模型容错率大,可以避免过拟合,若C也相同,则取先出现的那一组gamma

2、参数优化方法

可能很多人会有点懵,难道交叉验证不是一个方法吗?其实交叉验证只是一种方案,而要去完成这个方案还需要方法,完成一个方案的方法有很多,不同的方法完成的效果也不一样。同样的道理参数的优化来说,优化算法有很多,如网格搜索算法、遗传算法、粒子群算法、蚁群算法等,

对于交叉验证来说,我们采取的是网格搜索算法,即在参数的一定的范围内,按照指定的步长对不同的参数进行排列组合,将每一组参数组合进行测试,取性能指标最优的那一组参数作为最终参数的值。如本例中(C,gamma)组成了一个二维网格,再与性能指标识别率组成三维模型,这样一来就可以实现参数的最优选择啦!!!

《几种常用交叉验证(cross validation)方式的比较》

 

3、python实现交叉验证cross_val_score(网格搜索算法GridSearchCV)

本例是一个两特征三分类的问题,这里只涉及交叉验证,没有使用到网络搜索算法,有兴趣可以上网搜一下GridSearchCV

1)关键代码

for C in range(1,10,1):
    for gamma in range(1,11,1):
        #获得不同组合下的识别率,作为模型优劣评价的性能指标,这里需要注意的是,性能指标roc_auc,在本例中行不通,因为是多类问题,需要另外设置
        #获得的识别率是交叉验证后的平均值
        accuracy = cross_val_score(SVC(C=C/10,kernel='rbf',gamma=gamma/10),x,y.ravel(),cv=5,scoring='accuracy').mean()
        X.append(C/10)
        Y.append(gamma/10)
        Z.append(accuracy)
        M.append((C/10, gamma/10, accuracy))

2)sklearn中的cross_val_score()函数参数

参考:《【Python】sklearn中的cross_val_score()函数参数》

sklearn 中的cross_val_score函数可以用来进行交叉验证,因此十分常用,这里介绍这个函数的参数含义

sklearn.cross_validation.cross_val_score(estimator, X, y=None, scoring=None,
cv=None, n_jobs=1, verbose=0, fit_params=None, pre_dispatch=‘2*n_jobs’)

 

estimator:估计方法对象(分类器)
X:数据特征(Features)
y:数据标签(Labels)
soring:调用方法(包括accuracy、roc_auc、mean_squared_error等等)
cv:几折交叉验证
n_jobs:同时工作的cpu个数(-1代表全部)

3)AX3D三维绘图

参考:《plot_surface(Axes3D)方法:绘制3D图形》

3D 图形需要的数据与等高线图基本相同:X、Y 数据决定坐标点,Z 轴数据决定 X、Y 坐标点对应的高度。与等高线图使用等高线来代表高度不同,3D 图形将会以更直观的形式来表示高度。

为了绘制 3D 图形,需要调用 Axes3D 对象的 plot_surface() 方法来完成。

下面程序将使用与前面等高线图相同的数据来绘制 3D 图形,此时将看到程序会以更直观的形式来显示高度。

..................
fig = plt.figure()
ax = Axes3D(fig)
..................
# 绘制3D图形
ax.plot_surface(X, Y, Z,
    rstride=1,  # rstride(row)指定行的跨度
    cstride=1,  # cstride(column)指定列的跨度
    cmap=plt.get_cmap('rainbow'))  # 设置颜色映射
# 设置Z轴范围
ax.set_zlim(-2, 2)
# 设置标题
plt.title("3D图")
plt.show()#一定不要忘记这行
....................
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(12, 8))
ax = Axes3D(fig)
delta = 0.125
# 生成代表X轴数据的列表
x = np.arange(-3.0, 3.0, delta)
# 生成代表Y轴数据的列表
y = np.arange(-2.0, 2.0, delta)
# 对x、y数据执行网格化
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-X**2 - Y**2)
Z2 = np.exp(-(X - 1)**2 - (Y - 1)**2)
# 计算Z轴数据(高度数据)
Z = (Z1 - Z2) * 2
# 绘制3D图形
ax.plot_surface(X, Y, Z,
    rstride=1,  # rstride(row)指定行的跨度
    cstride=1,  # cstride(column)指定列的跨度
    cmap=plt.get_cmap('rainbow'))  # 设置颜色映射
# 设置Z轴范围
ax.set_zlim(-2, 2)
# 设置标题
plt.title("3D图")
plt.show()

 机器学习——SVM之交叉验证对参数(C,gamma)进行优化以及选择_第1张图片

4)ravel函数

将多维数组转换成一维数组

可参考:《numpy——ravel()和flatten()》

column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
  return f(**kwargs)
import numpy as np
arr = np.array([[1, 2],[3, 4]])
arr.ravel()    #降维默认行序优先,传入参数‘F’表示列序优先
arr.ravel('F')

##arr.ravel()=%s [1 2 3 4]
##arr.ravel('F')=%s [1 3 2 4]

 

5)完整代码

from sklearn.svm import SVC
import numpy as np
import sklearn
import matplotlib.pyplot as plt
from sklearn import preprocessing
from sklearn.model_selection import  cross_val_score
from mpl_toolkits.mplot3d import Axes3D
from sklearn.model_selection import GridSearchCV


#define converts(字典)
def Iris_label(s):
    it={b'Iris-setosa':0, b'Iris-versicolor':1, b'Iris-virginica':2 }
    return it[s]

#1.读取数据集
path='E:\PYTHON\machine_learning/Iris.data'
data=np.loadtxt(path, dtype=float, delimiter=',', converters={4:Iris_label} )
#converters={4:Iris_label}中“4”指的是第5列:将第5列的str转化为label(number)

#2.划分数据与标签
x,y=np.split(data,indices_or_sections=(4,),axis=1) #x为数据,y为标签,axis是分割的方向,1表示横向,0表示纵向,默认为0
x=x[:,0:2] #为便于后边画图显示,只选取前两维度。若不用画图,可选取前四列x[:,0:4]

# x = preprocessing.scale(x)#预处理数据样本



X = []
Y = []
Z = []
M = []#定义列表,分别用于接受不同组合的C,gamma以及性能指标值
for C in range(1,10,1):
    for gamma in range(1,11,1):
        #获得不同组合下的识别率,作为模型优劣评价的性能指标,这里需要注意的是,性能指标roc_auc,在本例中行不通,因为是多类问题,需要另外设置
        #获得的识别率是交叉验证后的平均值
        accuracy = cross_val_score(SVC(C=C/10,kernel='rbf',gamma=gamma/10),x,y.ravel(),cv=5,scoring='accuracy').mean()
        X.append(C/10)
        Y.append(gamma/10)
        Z.append(accuracy)
        M.append((C/10, gamma/10, accuracy))
print(M)

#5、以C,gamma,auc作为三个坐标变量绘图

#将列表转换成数组
X = np.array(X).reshape(9,10)
Y = np.array(Y).reshape(9,10)
Z = np.array(Z).reshape(9,10)

#绘制三维图形
fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X,Y,Z,rstride=1,cstride=1,cmap=plt.get_cmap('rainbow'))
# ax.scatter(Y,X,Z,c='r')
plt.xlabel('Gamma')
plt.ylabel('C')
plt.title('gamma_C_auc')
plt.show()

绘制图像如下,图中红色部分则为识别率最高的地方,取该处的(C,gamma)作为参数进行模型训练。

至于具体怎么去得到最优的参数,我们可以在内层循环中再嵌入一个判断语句,大概思路为:先假设k = 0,m=0,n=0,将每次循环得到的accuracy与k做比较,若accuracy大于k,则将accuracy的值赋给k,同时将C赋值给m,将gamma赋值给n,最后就能够得到最大的accuracy时的参数,当然也有可能出现accuracy相同时的情况,这时候就判断C的大小,取C小的那组,同理gamma也是如此!!!这样我们就找到了最优参数C,gamma啦

机器学习——SVM之交叉验证对参数(C,gamma)进行优化以及选择_第2张图片


 

你可能感兴趣的:(机器学习,机器学习,python)