在支持向量机(SVM)中,径向基函数(RBF)核是一种常用的核函数,它通过调整两个关键参数——gamma和C——来影响模型的性能。Gamma参数定义了单个训练样本的影响范围,其值越低,影响范围越广;值越高,影响范围越小。这可以看作是模型选择的支持向量的影响半径的倒数。而C参数则在训练样本的正确分类与决策函数边界最大化之间进行权衡。C值较大时,模型更倾向于接受较小的边界,以确保所有训练点都能被正确分类;C值较小,则倾向于获得较大的边界,从而得到一个更简单的决策函数,但这可能会牺牲训练精度。换句话说,C参数在SVM中充当了正则化参数的角色。
首先,通过一个简化的分类问题来可视化决策函数,该问题仅涉及2个输入特征和2个可能的目标类别(二元分类)。需要注意的是,对于具有更多特征或目标类别的问题,这种类型的可视化是不可能实现的。然后,通过热图展示了分类器的交叉验证准确率,这是作为C和gamma参数的函数。在这个例子中,探索了一个相对较大的网格,以便于说明。在实际应用中,通常使用从10^-3到10^3的对数网格就足够了。如果最佳参数位于网格的边界上,可以在后续搜索中向该方向扩展网格。
热图的色条有一个特殊的中点值,接近最佳性能模型的分数值,这样可以很容易地一眼区分出最佳模型。模型的行为对gamma参数非常敏感。如果gamma过大,支持向量的影响区域只包括支持向量本身,即使使用C进行正则化也无法防止过拟合。当gamma非常小时,模型过于受限,无法捕捉数据的复杂性或“形状”。任何选定的支持向量的影响区域将包括整个训练集。结果模型的行为类似于具有一组超平面的线性模型,这些超平面分离了任意两个类别的高密度中心。
对于中间值,可以看到在第二幅图的C和gamma的对角线上可以找到好的模型。平滑模型(较低的gamma值)可以通过增加分类每个点的重要性(较大的C值)来变得更复杂,因此对角线上的模型表现良好。最后,还可以观察到,对于一些中间的gamma值,当C变得非常大时,可以得到表现相同的模型。这表明支持向量集不再改变。RBF核本身作为一个良好的结构正则化器。进一步增加C没有帮助,可能是因为没有更多的训练点违反规定(在边界内或错误分类),或者至少找不到更好的解决方案。分数相等时,使用较小的C值可能更有意义,因为非常高的C值通常会增加拟合时间。
另一方面,较低的C值通常会导致更多的支持向量,这可能会增加预测时间。因此,降低C值涉及到拟合时间和预测时间之间的权衡。还应该注意到,分数的小差异来自于交叉验证过程的随机分割。这些虚假的变化可以通过增加CV迭代次数n_splits来平滑,以牺牲计算时间为代价。增加C_range和gamma_range步骤的数量将增加超参数热图的分辨率。
以下是一个Python代码示例,展示了如何使用scikit-learn库中的GridSearchCV来寻找SVM模型的最优参数。
import numpy as np
from matplotlib.colors import Normalize
class MidpointNormalize(Normalize):
def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
self.midpoint = midpoint
Normalize.__init__(self, vmin, vmax, clip)
def __call__(self, value, clip=None):
x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
return np.ma.masked_array(np.interp(value, x, y))
# 加载并准备数据集
from sklearn.datasets import load_iris
iris = load_iris()
X = iris.data
y = iris.target
# 数据集用于决策函数可视化:只保留X中的前两个特征,并下采样数据集,只保留2个类别,使其成为二元分类问题。
X_2d = X[:, :2]
X_2d = X_2d[y > 0]
y_2d = y[y > 0]
y_2d -= 1
# 通常对SVM训练进行数据缩放是一个好主意。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X = scaler.fit_transform(X)
X_2d = scaler.fit_transform(X_2d)
# 训练分类器
from sklearn.model_selection import GridSearchCV, StratifiedShuffleSplit
from sklearn.svm import SVC
C_range = np.logspace(-2, 10, 13)
gamma_range = np.logspace(-9, 3, 13)
param_grid = dict(gamma=gamma_range, C=C_range)
cv = StratifiedShuffleSplit(n_splits=5, test_size=0.2, random_state=42)
grid = GridSearchCV(SVC(), param_grid=param_grid, cv=cv)
grid.fit(X, y)
print("The best parameters are %s with a score of %0.2f" % (grid.best_params_, grid.best_score_))
以上代码首先定义了一个MidpointNormalize类,用于调整色条的中点值。然后加载了iris数据集,并对其进行了预处理,包括特征选择和数据缩放。接下来,使用GridSearchCV进行了参数搜索,找到了最优的C和gamma值。
可以通过绘制参数效果的可视化图来进一步理解这些参数如何影响模型的性能。以下是一个Python代码示例,展示了如何绘制决策函数的可视化图和交叉验证准确率的热图。
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 6))
xx, yy = np.meshgrid(np.linspace(-3, 3, 200), np.linspace(-3, 3, 200))
for k, (C, gamma, clf) in enumerate(classifiers):
# 在网格中评估决策函数
Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
# 为这些参数可视化决策函数
plt.subplot(len(C_2d_range), len(gamma_2d_range), k + 1)
plt.title("gamma=10^%d, C=10^%d" % (np.log10(gamma), np.log10(C)), size="medium")
# 可视化参数对决策函数的影响
plt.pcolormesh(xx, yy, -Z, cmap=plt.cm.RdBu)
plt.scatter(X_2d[:, 0], X_2d[:, 1], c=y_2d, cmap=plt.cm.RdBu_r, edgecolors="k")
plt.xticks(())
plt.yticks(())
plt.axis("tight")
scores = grid.cv_results_["mean_test_score"].reshape(len(C_range), len(gamma_range))
Draw heatmap of the validation accuracy as a function of gamma and C
The score are encoded as colors with the hot colormap which varies from dark red to bright yellow. As the most interesting scores are all located in the 0.92 to 0.97 range we use a custom normalizer to set the mid-point to 0.92 so as to make it easier to visualize the small variations of score values in the interesting range while not brutally collapsing all the low score values to the same color.
plt.figure(figsize=(8, 6))
plt.subplots_adjust(left=0.2, right=0.95, bottom=0.15, top=0.95)
plt.imshow(scores, interpolation="nearest", cmap=plt.cm.hot, norm=MidpointNormalize(vmin=0.2, midpoint=0.92),)
plt.xlabel("gamma")
plt.ylabel("C")
plt.colorbar()
plt.xticks(np.arange(len(gamma_range)), gamma_range, rotation=45)
plt.yticks(np.arange(len(C_range)), C_range)
plt.title("Validation accuracy")
plt.show()
以上代码首先绘制了决策函数的可视化图,展示了不同C和gamma值对决策边界的影响。然后,绘制了一个热图,展示了交叉验证准确率作为gamma和C的函数。热图使用了自定义的归一化器MidpointNormalize,以便更容易地可视化分数值在感兴趣范围内的小变化。