写点什么

支持向量机 - 选取与核函数相关的参数:degree & gamma & coef0

  • 2022-11-26
    山东
  • 本文字数:2708 字

    阅读完需:约 9 分钟

之前的表格



对于线性核函数,"kernel"是唯一能够影响它的参数,但是对于其他三种非线性核函数,他们还受到参数 gamma,degree 以及 coef0 的影响。参数 gamma 就是表达式中的,degree 就是多项式核函数的次数,参数 coef0 就是常数项。其中,高斯径向量核函数受到 gamma 的影响,而多项式核函数受到三个参数的影响



但从核函数的公式来看,我们其实很难去界定具体每个参数如何影响了 SVM 的表现。当 gamma 的符号变化,或者 degree 的大小变化时,核函数本身甚至都不是永远单调的。所以如果我们想要彻底地理解这三个参数,我们要先推导出它们如何影响核函数地变化,再找出核函数的变化如何影响了我们的预测函数(可能改变我们的核变化所在的维度),再判断出决策边界随着预测函数的改变发生了怎样的变化。无论是从数学的角度来说还是从实践的角度来说,这个过程太复杂也太低效。所以,我们往往避免去真正探究这些参数如何影响了我们的核函数,而直接使用学习曲线或者网格搜索来帮助我们查找最佳的参数组合。对于高斯径向基核函数,调整 gamma 的方式其实比较容易,那就是画学习曲线。我们来试试看高斯径向基核函数 rbf 的参数 gamma 在乳腺癌数据集上的表现:


score = []gamma_range = np.logspace(-10,1,50)for i in gamma_range:    clf = SVC(kernel="rbf",gamma=i,cache_size=5000).fit(Xtrain,Ytrain)    score.append(clf.score(Xtest,Ytest))print(max(score),gamma_range[score.index(max(score))])---0.9766081871345029 0.012067926406393264
plt.plot(gamma_range,score)plt.show()
复制代码



np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
# 生成对数等比数列
# 大概步骤,先将[start,stop]等分num份,得到每个值i,然后计算10^i的值
# 注意是分割[start,stop]的时候等差,因为需要计算10^i,输出等比

np.logspace(-10,1,50)
---
array([1.00000000e-10, 1.67683294e-10, 2.81176870e-10, 4.71486636e-10,……, 1.00000000e+01])

(10**1,1.00000000e+01),(10**-10,1.00000000e-10)
# 1e+01可以理解为1*10^+1,负数同理
---
((10, 10.0), (1e-10, 1e-10))


通过学习曲线,很容就找出了 rbf 的最佳 gamma 值。但我们观察到,这其实与线性核函数的准确率一模一样之前的准确率。我们可以多次调整 gamma_range 来观察结果,可以发现 97.6608 应该是 rbf 核函数的极限了。但对于多项式核函数来说,因为三个参数共同作用在一个数学公式上影响它的效果,因此我们往往使用网格搜索来共同调整三个对多项式核函数有影响的参数。依然使用乳腺癌数据集。


from sklearn.model_selection import StratifiedShuffleSplitfrom sklearn.model_selection import GridSearchCV
time0 = time()
gamma_range = np.logspace(-10,1,20)coef0_range = np.linspace(0,5,10) # coef不接收负数# 因为我们已经知道多项式核函数的degree为1,因此不需要进行网格搜索param_grid = dict(gamma = gamma_range ,coef0 = coef0_range)cv = StratifiedShuffleSplit(n_splits=5,test_size=0.3,random_state=420)# n_splits:将数据集分5次# test_size:测试集大小grid = GridSearchCV(SVC(kernel="poly",degree=1,cache_size=5000) ,param_grid=param_grid ,cv=cv )grid.fit(X,y)print("The best parameters are %s with a score of %0.5f" % (grid.best_params_,grid.best_score_))print(datetime.datetime.fromtimestamp(time() - time0).strftime("%M:%S:%f"))---The best parameters are {'coef0': 0.0, 'gamma': 0.18329807108324375} with a score of 0.9695900:07:456977
复制代码


可以发现,网格搜索为我们返回的整体分数是 0.96959,虽然比调参前略有提高,但依然没有超过线性核函数核和 rbf 的结果。可见,如果最初选择核函数的时候,你就发现多项式的结果不如 rbf 和线性核函数,那就不要挣扎了,试试看调整 rbf 或者直接使用线性。


关于几种交叉验证

KFold K 折交叉验证:进行多次 train_test_split 划分。每次划分时,在不同的数据集上进行训练、测试评估,从而得出一个评价结果;如果是 5 折交叉验证,意思就是在原始数据集上,进行 5 次划分,每次划分进行一次训练、评估,最后得到 5 次划分后的评估结果,一般在这几次评估结果上取平均得到最后的评分。这也是 cross_val_score 默认的方法

StratifiedKFold 分层交叉验证:StratifiedKFold 是为分类问题设计的 KFold 版本。在分类问题中,即使将数据拆分为多个集合,也必须保留目标分布。 简单的说就是分类目标的比例在进行分折后应该与原始数据相同,例如原始数据种 A 类占比 30%,B 类占比 35%,C 类占比 35%,在我们分折以后,这个比例是不应该变化的。而使用 StratifiedKFold 就可以保证样本集与测试集不同类别的数据成比例

观察上面两个方法,明显可以发现,交叉验证中所有的测试集加和应该正好是一个全集,那么如果我们交叉验证测试足够大,测试集就可能过小而产生干扰,因此就有

ShuffleSplit 随机打乱交叉验证先根据随机数进行指定次的 train_test_split,然后不同次的训练集测试集分别进行验证得到 score,并进行平均。优点是可以完全控制每个折中训练集和测试集的大小。 集合的大小不必与拆分的数量成反比。但是与其他拆分器相反,不能保证在每次随机拆分中样本不同。

StratifiedShuffleSplit 随机打乱分层交叉验证:也就是 ShuffleSplit 用于分类的版本

在方法的参数中也有体现

KFold(n_splits='warn', shuffle=False, random_state=None)
# n_splits:交叉验证的次数
# 其实这里也有shuffle,但这里的shuffle与StratifiedShuffleSplit里的意义不同。例如如果设置shuffle=Falsh也就是默认值,进行3次K折验证,测试集第一次取前1/3,第二次取中间1/3,最后一次取剩余1/3;如果设置为True,每次取出的测试集总和仍然是全集的1/3,只是位置发生变化而已

StratifiedKFold(n_splits='warn', shuffle=False, random_state=None)
# 参数同KFold

ShuffleSplit(
 ['n_splits=10', "test_size='default'", 'train_size=None', 'random_state=None'],
)
# 对比前两个方法,这里多了个test_size和train_size,也就是说我们可以指定测试集和训练集的大小,就类似于我们使用train_test_splite方法
StratifiedShuffleSplit(
 ['n_splits=10', "test_size='default'", 'train_size=None', 'random_state=None'],
)
# 参数同ShuffleSplit

部分来源作者:deephub链接:5个常见的交叉验证技术介绍和可视化_deephub的博客-CSDN博客_五重交叉验证


视频作者:菜菜TsaiTsai链接:【技术干货】菜菜的机器学习sklearn【全85集】Python进阶_哔哩哔哩_bilibili


发布于: 刚刚阅读数: 6
用户头像

跃入人海 2022-09-14 加入

还未添加个人简介

评论

发布
暂无评论
支持向量机-选取与核函数相关的参数:degree & gamma & coef0_Python_烧灯续昼2002_InfoQ写作社区