手动实现SVM三种核函数需注意:线性核为点积;多项式核默认coef0=1;RBF核应直接算差的平方和而非先开方再平方;预计算核矩阵训练时为n×n方阵,预测时为m×n非方阵;gamma需标准化数据后在0.001~10间对数搜索。

怎么手动实现 SVM 的三种核函数(线性/多项式/RBF)
直接写 sklearn.svm.SVC 是最省事的,但如果你要调试核函数行为、画决策边界、理解支持向量怎么被映射,就得自己手写核计算逻辑。关键不是“能不能写”,而是“写完能不能和 sklearn 对齐”——很多人的自定义核跑出来结果离谱,问题常出在参数默认值或广播维度上。
三个核的核心区别在于输入向量对 x_i 和 x_j 的相似度计算方式:
- 线性核:
np.dot(x_i, x_j),就是原始空间的内积 - 多项式核:
(gamma * np.dot(x_i, x_j) + coef0) ** degree,注意coef0默认是 1,不是 0 - RBF 核:
np.exp(-gamma * np.linalg.norm(x_i - x_j) ** 2),等价于np.exp(-gamma * pairwise_distances_sq(x_i, x_j)),别手算欧氏距离再开方再平方——直接用差的平方和更稳
为什么自定义核传给 SVC(kernel='precomputed') 总报错 shape 不匹配
预计算核矩阵必须是方阵,且第 i 行第 j 列对应训练样本 X[i] 和 X[j] 的核值。最容易漏的是:测试时你也得算「测试点 vs 全部训练点」的核值,不是「测试点之间」的。
常见错误现象:ValueError: X.shape[1] != n_features_in_ 或训练能过、预测崩。根本原因是没按 SVC 的预期构造 gram_matrix:
- 训练阶段:传入
n_samples × n_samples的对称矩阵,行/列索引都对应X_train的样本序号 - 预测阶段:传入
n_test × n_train的非方阵,每行是某测试样本对全部训练样本的核值 - 别用
scipy.spatial.distance.pdist,它只输出上三角;要用sklearn.metrics.pairwise.pairwise_kernels(X, metric='rbf', gamma=...)或手动双循环(小数据够用)
RBF 核的 gamma 值怎么调才不爆炸也不失效
gamma 不是越大越好。太小(如 1e-5)会让所有样本核值趋近 1,决策边界变直线;太大(如 100)会让核矩阵接近单位阵,每个样本只“认识自己”,严重过拟合。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
实际中 gamma 的合理范围高度依赖数据尺度。如果没做标准化,X 各维度量纲差异大,gamma 会非常敏感:
- 先做
StandardScaler().fit_transform(X),再试gamma在0.001 ~ 10之间 - 用
sklearn.model_selection.GridSearchCV时,别只扫固定步长,用np.logspace(-3, 2, 10)更靠谱 - 注意:sklearn 默认
gamma='scale',即1 / (n_features * X.var()),不是'auto'(旧版),这个默认值本身已隐含了缩放假设
画决策边界时,RBF 核的等高线为啥总歪成一坨
不是核函数写错了,大概率是网格点分辨率不够或坐标范围太窄。RBF 的响应是非线性的、局部敏感的,边界可能藏在两个样本点之间的缝隙里。
实操建议:
- 网格步长别用
0.1这种整数,改用np.linspace(X.min(), X.max(), 200),保证覆盖全范围 - 预测前务必用和训练时**同一套 scaler** 变换网格点坐标,否则核值计算基准错乱
- 别直接画
svc.predict()的离散结果,先用svc.decision_function()得到连续分值,再用plt.contour画等高线(levels=[0]就是决策边界) - 如果边界看起来“抖动”,检查是否用了
probability=True并调了decision_function_shape='ovr'——这会影响分值标度
真正麻烦的是:核函数本身不显式给出映射 φ(x),你看到的边界是高维空间里超平面的原像。所以哪怕公式写对了,图像也可能反直觉——这不是 bug,是 RBF 本色。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










