- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
支持向量机(SVM)
支持向量机(Support Vector Machine,简称SVM)是一种常用的监督学习算法,用于分类和回归任务,尤其是在分类问题中表现非常优秀。SVM的核心思想是寻找一个最优的决策边界(也称为超平面),以最大化分类时两类之间的间隔,从而实现更好的分类效果。
1. 基本概念
SVM的目标是找到一个超平面来区分不同类别的数据点。超平面可以理解为一个分隔面,在二维情况下是直线,三维情况下是平面,多维情况下则是超平面。SVM通过最大化超平面到各个类别数据点的最小距离(即间隔)来实现最优分类,这个最大化间隔的过程是SVM最重要的特性。
以上介绍的SVM只能解决线性可分的问题,为了解决更加复杂的问题,支持向量机学习方法有一些由简至繁的模型:
- 线性可分SVM:当训练数据线性可分时,通过硬间隔(hard margin,见下文)最大化可以学习得到一个线性分类器,即硬间隔SVM,如上图的的𝐻3。
- 线性SVM:当训练数据不能线性可分但是可以近似线性可分时,通过软间隔(soft margin)最大化也可以学习到一个线性分类器,即软间隔SVM。
- 非线性SVM:当训练数据线性不可分时,通过使用核技巧(kernel trick)和软间隔最大化,可以学习到一个非线性SVM。
2. 线性可分问题
在理想情况下,数据可以通过一个直线(或高维的超平面)完美分成两类,这称为线性可分。SVM会找到所有能分开这两类数据的超平面中最优的超平面,即能使两类数据之间的间隔最大的超平面。
- 支持向量:在线性可分的情况下,训练数据集的样本点中与分离超平面距离最近的数据点称为支持向量(support vector),支持向量也就是所有在直线𝑋𝑇𝑊+𝑏=1或直线𝑋𝑇𝑊+𝑏=−1上的点。如下图所示:这些点决定了超平面的最终位置,因为超平面是基于这些支持向量的。
3. 线性不可分问题
在现实数据中,大多数情况是线性不可分的,也就是用直线(或超平面)无法完美地将数据分开。此时,SVM采用以下两种方法来处理:
3.1 软间隔(Soft Margin)
在允许一些数据点误分类的情况下,SVM通过引入松弛变量,允许少量的错误分类数据点,进而在大多数情况下找到一个较优的超平面。这个方法叫做软间隔,目的是在误差和间隔之间找到一个平衡。
3.2 核函数(Kernel Trick)
对于线性不可分的问题,SVM还可以将数据映射到更高维的空间,通过在高维空间中找到线性可分的超平面。为了实现这一点,SVM使用核函数,避免了显式地将数据映射到高维空间,极大减少了计算复杂度。
如下图所示,核技巧的基本思路分为两步: ● 使用一个变换将原空间的数据映射到新空间(例如更高维甚至无穷维的空间); ● 然后在新空间里用线性方法从训练数据中学习得到模型。
非线性SVM的核心在于核函数的选择与应用。核函数允许我们在不显式地计算高维空间中的映射的情况下,直接计算在这个高维空间中的内积。这样,我们就可以利用原始特征空间中的数据,在计算上等效于在一个可能更高维度的特征空间中寻找最大边距超平面。常用的核函数有以下几种:
- 线性核函数:适合线性可分问题。
- 多项式核函数:将数据映射到高维多项式空间。
- 高斯径向基核函数(RBF Kernel):常用于复杂的非线性问题,表现非常好。
- Sigmoid核函数:表现类似于神经网络中的激活函数。
4. 公式表达
支持向量机的目标是最大化间隔(Margin)。对于给定的训练集{(𝑥1,𝑦1),(𝑥2,𝑦2),…,(𝑥𝑛,𝑦𝑛)},其中𝑥𝑖∈ℝ𝑛是输入向量,𝑦𝑖∈{−1,1}是类别标签,SVM的优化问题可以表示为:
其中𝐶是一个超参数,控制模型对误分类的容忍度。
5. 超参数
SVM有两个主要的超参数需要调整:
- C参数:控制软间隔的大小,也就是对误分类的容忍度。较大的𝐶值会减少误分类,但也可能导致过拟合;较小的𝐶值会增加间隔,但误分类更多。
- 𝛾参数:在使用核函数时,𝛾决定单个样本的影响范围。较大的𝛾会使模型更加关注近邻的点,可能导致过拟合;较小的𝛾则使模型更加平滑,关注整体趋势。
6. 优缺点
优点
- 高效处理高维数据:SVM在高维空间中表现优越,尤其在特征数量多于样本数量的情况下。
- 避免过拟合:SVM通过最大化间隔来寻找最优分类界限,通常比其他分类器更能避免过拟合。
- 适用非线性问题:通过使用核函数,SVM可以轻松处理线性不可分问题。
缺点
- 计算复杂度高:尤其是在大规模数据集上,SVM的训练时间较长。
- 难以解释:相比于决策树或线性回归,SVM的结果(支持向量、间隔等)不易解释。
- 对超参数敏感:𝐶和𝛾等超参数对模型的效果影响较大,需要仔细调整。
7. 应用场景
SVM在以下领域中有广泛应用:
- 文本分类:SVM广泛用于垃圾邮件检测、情感分析等文本分类任务。
- 图像分类:在图像识别和分类中,SVM常用于识别特定的图像特征。
- 基因数据分析:由于SVM处理高维数据的能力,它也常用于生物信息学领域,比如基因表达数据的分类。
8. 总结
支持向量机通过最大化类间的间隔来进行分类。它通过核函数能很好地处理线性不可分问题,是一种非常强大、灵活的分类算法。尽管SVM计算复杂度较高,但在许多实际应用中,它的表现往往非常出色。
在实际操作中,选择合适的核函数是一个关键步骤,通常需要通过交叉验证等方法来确定最优的核函数类型及相应的参数。一旦选定核函数,非线性SVM的学习算法(如SMO算法)会在这个“kernelized”特征空间中寻找最大边距超平面,从而解决了原始空间中非线性可分的问题。这种方法不仅保持了SVM优雅的理论性质,如最大化间隔,同时也大大增强了模型的表达能力和泛化能力。
实战
1. scikit-learn库实现线性可分的SVM
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
# 加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 数据预处理
sc = StandardScaler()
X = sc.fit_transform(X)
# 训练集和测试集的分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 创建SVM模型
svm = SVC(kernel='linear', C=1.0)
# 训练模型
svm.fit(X_train, y_train)
# 预测
y_pred = svm.predict(X_test)
# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print('Accuracy: %.2f' % (accuracy * 100.0))
2. scikit-learn库实现非线性可分的SVM
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score
# 加载数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 数据预处理
sc = StandardScaler()
X = sc.fit_transform(X)
# 训练集和测试集的分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 创建SVM模型
svm = SVC(kernel='rbf', C=1.0, gamma=0.1)
# 训练模型
svm.fit(X_train, y_train)
# 预测
y_pred = svm.predict(X_test)
# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print('Accuracy: %.2f' % (accuracy * 100.0))
3. sklearn.svm.SVC函数详解
sklearn.svm.SVC 是 Scikit-learn 库中用于实现支持向量机(SVM)分类的一个类。
函数定义:
sklearn.svm.SVC(
C=1.0,
kernel='rbf',
degree=3,
gamma='scale',
coef0=0.0,
shrinking=True,
probability=False,
tol=1e-3,
cache_size=200,
class_weight=None,
verbose=False,
max_iter=-1,
decision_function_shape='ovr',
break_ties=False,
random_state=None
)
常用参数详解:
- C(默认值:1.0)
- 作用:惩罚参数,用于平衡最大化分类间隔和误分类惩罚之间的关系。
- 解释:较大的 C 值意味着对误分类的惩罚更大,模型会倾向于将更多的训练数据点分类正确,但可能会导致间隔变小,可能出现过拟合;较小的 C 值则会更关注于间隔的大小,而允许更多的误分类,从而提高模型的泛化能力。
- 常用范围:通常在 0.001 到 1000 之间进行调节。
- kernel(默认值:'rbf')
- 作用:指定要使用的核函数,支持不同的非线性映射方法。
- 可选值:
- 'linear':线性核函数,即不进行任何非线性映射。
- 'poly':多项式核函数,通常用于多项式可分的情况。
- 'rbf':径向基函数(Radial Basis Function),又称高斯核,是最常用的非线性核函数。
- 'sigmoid':类似于神经网络的激活函数,较少使用。
- 你也可以传递自定义核函数,方法是传递一个函数。
- degree (默认值:3)
- 作用:当 kernel='poly' 时,指定多项式核的多项式次数。
- 解释:如果使用多项式核函数(poly),degree 参数决定多项式的阶数,通常是 2 或 3。
- gamma(默认值:'scale')
- 作用:核函数系数,适用于 'rbf'、'poly' 和 'sigmoid' 核函数。
- 可选值:
- 'scale':使用 1 / (n_features * X.var()) 作为默认值。这个值会根据输入特征的数量和方差自动调整。
- 'auto':使用 1 / n_features 作为值。
- 解释:gamma 值越大,模型越倾向于拟合训练数据,但可能会导致过拟合;gamma 值越小,模型更倾向于平滑。
- coef0(默认值:0.0)
- 作用:核函数中的独立项,仅在 kernel='poly' 或 kernel='sigmoid' 时有意义。
- 解释:用于控制多项式核函数和 sigmoid 核函数中的偏移量。