目录
核函数(Kernel Function)主要用于将数据从原来的低维空间映射到一个更高维度的空间中,从而使得在高维空间中可以更容易地找到线性分割的决策边界。
核函数接受两个输入(通常是向量形式),并输出它们在某个高维特征空间中的内积。可以看作是在这个高维空间中,两个点之间的“相似性”或“关系”。这让复杂的数据变得可以被简单的方法(比如直线或平面)来分类。
核函数(Kernel Functions)是支持向量机(SVM)、高斯过程(Gaussian Processes)等机器学习算法中的核心概念之一。它们使得算法能够在高维甚至无限维的特征空间中进行操作,而不需要显式地计算特征映射。这种技术被称为“核技巧”(Kernel Trick)。
1、定义
核函数 是一个定义在输入空间的两个样本 和 之间的函数,其定义为:
其中, 是将输入样本 从原始空间映射到一个高维(甚至无限维)特征空间的映射函数,而 表示特征空间中的内积。
在机器学习问题中,计算映射到高维特征空间后的内积可能非常昂贵或不可行。然而,通过核技巧,我们可以直接在原始空间计算内积,而无需显式地计算映射。也就是说,核函数能够直接给出在高维特征空间中的内积值,而不需要实际计算 。也就是本来是先映射再求内积,现在直接使用核函数。
常见的核函数
线性核 | 无映射 | |
多项式核 | c和d是超参数 | |
高斯径向基核(RBF) | 是超参数 | |
拉普拉斯核 | 是超参数 |
2、支持向量机(SVM)中的核函数使用
支持向量机的目标是找到一个决策边界,使得边界到两类样本的最近点的距离最大化。在线性SVM中,这相当于找到最优的超平面:
在非线性SVM中,我们使用核函数来处理非线性分类问题:
(1)数据映射:使用映射函数 将输入数据 映射到高维特征空间。
(2)构建拉格朗日函数:构造基于映射数据的拉格朗日函数。
(3)计算内积:在优化过程中,内积被核函数替代。
(4)求解优化问题:求解相应的对偶问题,最终得到支持向量和决策函数。
优化问题的最终形式为:
其中, 是拉格朗日乘子, 是样本的标签。最终的决策函数为:
(1)原始优化问题
在原始问题中,我们的目标是最小化目标函数:
subject to:
(2)拉格朗日对偶问题
为了简化计算和解决问题,我们使用拉格朗日乘子法,将约束条件引入目标函数,形成拉格朗日函数
(3)对偶问题
通过对拉格朗日函数进行优化,我们可以得到对偶问题,其目标是最大化对偶拉格朗日函数
(4)得到的决策变量
通过求解对偶问题,我们得到的决策变量是拉格朗日乘子.这个决策边界(超平面)就是用于分类的分界线,能够将数据分为两类。
核函数的选取与调优:
在实际应用中,核函数的选择对模型性能有很大影响。常见的流程为:选择核函数类型→超参数调优→模型训练与评估
3、SVC、SVM、SVR
SVC、SVM 和 SVR 都是与支持向量机(Support Vector Machine, SVM)相关的算法和模型,但它们适用于不同的任务。
SVM(Support Vector Machine) | SVM 是支持向量机的通用术语,它是一种用于分类、回归和其他任务的强大算法。具体的实现和应用会根据任务的不同而变化。分类任务 使用 SVC 或 LinearSVC。回归任务 使用 SVR 或 LinearSVR。 |
SVC(Support Vector Classification) | SVC 是用于分类任务的支持向量机实现。它可以处理二分类和多分类问题,并且支持各种核函数(如线性核、RBF 核、多项式核等) |
SVR(Support Vector Regression) | SVR 是用于回归任务的支持向量机实现。它与 SVC 类似,但用于预测连续值。 |
SVC
from sklearn.svm import SVC
# 初始化SVC模型
model = SVC(kernel='rbf', C=1.0, gamma='scale')
# 训练模型
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
kernel:核函数类型,常用的有 'linear'(线性核)、'rbf'(RBF 核)、'poly'(多项式核)。
C:正则化参数,用于控制模型的复杂度。C
是一种惩罚参数,控制着模型对误分类的容忍程度与决策边界的宽度之间的平衡。
-
如果
C
值较大,模型会更加严苛地惩罚误分类,倾向于让模型更准确地分类训练数据,但可能导致决策边界更复杂,从而过拟合训练数据。 -
较小的
C
值会导致更宽松的决策边界,允许更多的误分类样本,模型会更简单,可能更好地泛化到未见过的数据,但可能会欠拟合训练数据。
gamma:核系数,主要用于 RBF 核和多项式核。这里的,所以上文中的核函数在这里写成。gamma='scale'
是 scikit-learn
提供的一种自动计算 gamma
值的方法。
其中:
- n_features 是特征的数量,即输入数据的维度。
- Var(X)是数据集中每个特征的方差的平均值。
优点:
-
适应性强:
gamma='scale'
可以适应不同数据集的特征维度和特征分布,因为它基于数据的方差来计算。对于特征方差较大的数据,gamma
会变小,决策边界会更平滑;对于特征方差较小的数据,gamma
会变大,决策边界会更细致。 -
避免极端值:直接设定一个固定的
gamma
值(如0.1
或1
)可能在某些情况下不适用,尤其是在特征规模差异较大的数据集中。scale
方法根据数据自动调整,避免了手动调参的繁琐和不确定性。
SVR
from sklearn.svm import SVR
# 初始化SVR模型
model = SVR(kernel='rbf', C=1.0, gamma='scale')
# 训练模型
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
参数 kernel、C 和 gamma 的作用与 SVC 相同,但应用于回归任务。
LinearSVC 和 LinearSVR
如果只想使用线性核函数,可以直接使用 LinearSVC 或 LinearSVR。它们与 SVC 和 SVR 的区别在于,它们使用线性核函数,计算效率更高。
from sklearn.svm import LinearSVC
model = LinearSVC(C=1.0)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
from sklearn.svm import LinearSVR
model = LinearSVR(C=1.0)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
4、代码实践
(1)8x8像素的手写数字图像分类
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import datasets
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import classification_report, confusion_matrix, accuracy_score
# 加载数据集
digits = datasets.load_digits() # 手写数字(0-9)的 8x8 像素图像及其对应的标签。
# 特征和目标
X = digits.data
y = digits.target
# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.3,
random_state=42, stratify=y)
# 初始化SVM模型
svc = SVC(kernel='rbf', random_state=42)
# 网格搜索进行超参数优化
param_grid = {
'C': [0.1, 1, 10, 100],
'gamma': [1, 0.1, 0.01, 0.001]
}
grid_search = GridSearchCV(svc, param_grid, refit=True, verbose=3, cv=5, n_jobs=-1)
grid_search.fit(X_train, y_train)
# 打印最佳参数
print(f"最佳参数: {grid_search.best_params_}")
# 预测
y_pred = grid_search.predict(X_test)
# 打印分类报告
print('classification_report',classification_report(y_test, y_pred))
# 混淆矩阵
conf_matrix = confusion_matrix(y_test, y_pred)
# 可视化混淆矩阵
plt.figure(figsize=(10, 7))
sns.heatmap(conf_matrix, annot=True, cmap="Blues", fmt="d")
plt.title("Confusion Matrix")
plt.xlabel("Predicted")
plt.ylabel("True")
plt.show()
# 可视化不同 C 和 gamma 参数下的准确率
results = pd.DataFrame(grid_search.cv_results_)
scores_matrix = results.pivot("param_C", "param_gamma", "mean_test_score")
plt.figure(figsize=(8, 6))
sns.heatmap(scores_matrix, annot=True, cmap="YlGnBu")
plt.title("Grid Search Accuracy - C vs Gamma")
plt.xlabel("Gamma")
plt.ylabel("C")
plt.show()
使用最佳参数分类的混淆矩阵:
可视化不同参数和对精确度的影响:
总结
核函数主要适用于以下类型的问题:
-
非线性分类问题:当数据在原始空间中不可线性分割时,核函数通过将数据映射到高维空间,使得数据在新的空间中变得线性可分。
-
非线性回归问题:核函数同样可以应用于回归问题中,通过非线性映射,捕捉数据之间的复杂关系。
-
降维与数据映射:核函数可以用于降维技术(如核主成分分析),帮助在高维数据集中找到低维表示,同时保留数据中的重要结构。
-
聚类与密度估计:在无监督学习中,核函数可用于核密度估计和核聚类算法,如Spectral Clustering。
核函数的优缺点
优点:(1)处理非线性问题:核函数能够通过核技巧将原本线性不可分的问题转化为线性可分问题,从而处理复杂的非线性关系。(2)灵活性高:不同类型的核函数可以适应不同的应用场景,根据数据的特点选择合适的核函数能够提高模型性能。(3)无需显式映射:核函数通过计算内积直接在原始空间操作,而不需要显式地映射到高维空间,节省了计算资源。(4)广泛应用:核函数在多种算法中均有应用,如支持向量机、核岭回归、核主成分分析等。
缺点:(1)计算复杂度高:对于大规模数据集,核函数的计算复杂度较高,尤其是涉及到核矩阵的计算和存储时,可能会成为瓶颈。(2)选择和调优难度大:选择合适的核函数和超参数需要经验和大量实验,不同的核函数在不同的场景下效果差异较大。(3)易过拟合:如果选择的核函数和超参数不当,容易导致模型在训练数据上表现良好,但在测试数据上出现过拟合。
运用核函数的前提条件
-
数据集的规模:核函数在处理大规模数据集时会遇到计算瓶颈,因此在应用核函数前,需要考虑数据集的规模是否适合使用核函数。
-
数据的非线性特点:核函数适用于数据呈现出明显的非线性关系的情况,如果数据本身是线性可分的,则使用简单的线性模型可能更为有效。
-
算法的计算资源:由于核函数涉及到核矩阵的计算和存储,因此需要考虑算法是否有足够的计算资源和时间来完成这些操作。
-
合适的核函数选择:不同的核函数适用于不同的数据分布和问题类型,应用前需要对数据的特征和分布有一定的了解,以选择适当的核函数。
参考