支持向量机
(四)支持向量机
支持向量机(Support Vector Machine, SVM)是一种用于分类、回归分析以及异常检测的监督学习模型。SVM特别擅长处理高维空间的数据,并在文本和图像分类、生物信息学等领域有着广泛的应用。
核心概念:
最大间隔超平面
- 超平面:在二维空间中,超平面是一条直线;在三维空间中,是一个平面;更高维度则是超平面;
- 最大间隔:SVM的目标是找到一个能够将不同类别的样本分开,并且使得两类之间的间隔最大化。这个间隔是由距离超平面最近的数据点(即支持向量)来定义的。
支持向量
- 支持向量:位于分类边界(决策边界或超平面)最近的数据点称为支持向量。这些点对于定义最优超平面至关重要。即使去掉其他非支持向量的数据点,也不会影响超平面的位置。
核技巧(Kernel Trick)
- 当数据不是线性可分时,可以通过使用核函数将原始特征空间映射到一个更高维度的空间,在那里数据可能变得线性可分。常用的核函数包括:
- 线性核:适用于线性可分的数据;
- 多项式核:可以捕捉输入变量间的非线性关系;
- RBF(径向基函数)核:非常流行,尤其适合于复杂的非线性问题;
- Sigmoid核:类似于神经网络中的激活函数。
- 当数据不是线性可分时,可以通过使用核函数将原始特征空间映射到一个更高维度的空间,在那里数据可能变得线性可分。常用的核函数包括:
软间隔与硬间隔
- 硬间隔:假设数据完全线性可分,寻找一个能够完美分离所有训练样本的超平面。
- 软间隔:允许某些样本跨越边际甚至落在错误的一侧,通过引入松弛变量和惩罚参数C来实现。这有助于提高模型对噪声的鲁棒性和泛化能力。
1.算法步骤
数据准备
- 目标:收集与业务问题相关的结构化数据;
- 关键操作:
- 定义特征(如客户收入、信用历史、消费行为)和标签(如“违约/非违约”)。
- 划分数据集为训练集(70% ~ 80%)和测试集(20% ~ 30%)。
数据预处理
- 标准化:对特征进行 Z-score 标准化,消除量纲影响: x s c a l e d = x − μ σ x_{scaled}=\frac{x−μ}{σ} xscaled=σx−μ
- 处理缺失值:删除或填充缺失数据(如用均值/中位数);
- 类别平衡:若标签分布不均,使用过采样(SMOTE)或欠采样。
选择核函数
- 常用核函数:
- 线性核(
linear
),适用于线性可分问题,复杂度低: K ( x i , x j ) = x i T x j K(x_i,x_j)=x_i^Tx_j K(xi,xj)=xiTxj - 高斯核(
RBF
),适用于非线性问题,需调节参数 γ γ γ : K ( x i , x j ) = e x p ( − γ ∥ x i − x j ∥ 2 ) K(x_i,x_j)=exp(−γ \lVert xi−xj \rVert ^2) K(xi,xj)=exp(−γ∥xi−xj∥2) - 多项式核(
polynomial
),适用于高阶特征交互: K ( x i , x j ) = ( x i T x j + c ) d K(x_i,x_j)=(x_i^Tx_j+c)^d K(xi,xj)=(xiTxj+c)d
- 线性核(
- 常用核函数:
求解优化问题
- 目标函数:最大化间隔,转化为凸二次规划问题: min w , b 1 2 ∥ w ∥ 2 + C ∑ i = 1 n ξ i \min_{w,b} \frac{1}{2} \|w\|^2 + C \sum_{i=1}^{n} \xi_i w,bmin21∥w∥2+Ci=1∑nξi s.t. y i ( w T x i + b ) ≥ 1 − ξ i , ξ i ≥ 0 \text{s.t. } y_i(w^T x_i + b) \geq 1 - \xi_i, \quad \xi_i \geq 0 s.t. yi(wTxi+b)≥1−ξi,ξi≥0
- 参数:
- C C C :正则化参数,控制分类错误的惩罚力度;
- γ γ γ(高斯核):控制决策边界的复杂度。
- 参数:
- 目标函数:最大化间隔,转化为凸二次规划问题: min w , b 1 2 ∥ w ∥ 2 + C ∑ i = 1 n ξ i \min_{w,b} \frac{1}{2} \|w\|^2 + C \sum_{i=1}^{n} \xi_i w,bmin21∥w∥2+Ci=1∑nξi s.t. y i ( w T x i + b ) ≥ 1 − ξ i , ξ i ≥ 0 \text{s.t. } y_i(w^T x_i + b) \geq 1 - \xi_i, \quad \xi_i \geq 0 s.t. yi(wTxi+b)≥1−ξi,ξi≥0
构建决策边界
- 支持向量:距离决策边界最近的样本点。
- 分类规则: f ( x ) = s i g n ( ∑ i = 1 n α i y i K ( x i , x ) + b ) f(x) = \mathrm{sign} \left( \sum_{i=1}^{n} \alpha_i y_i K(x_i, x) + b \right) f(x)=sign(i=1∑nαiyiK(xi,x)+b)
模型评估
- 分类指标:
- 准确率(Accuracy):模型预测正确的样本数占总样本数的比例, A c c u r a c y = T P + T N T P + F P + F N + T N Accuracy=\frac{TP+TN}{TP+FP+FN+TN} Accuracy=TP+FP+FN+TNTP+TN;
- 精确率(Precision):正确预测为正类的样本数占所有预测为正类的样本数的比例,公式: A c c u r a c y = T P / ( T P + F P ) Accuracy=TP / (TP + FP) Accuracy=TP/(TP+FP)。
- 召回率(Recall):正确预测为正类的样本数占所有实际正类样本数的比例。公式: R e c a l l = T P / ( T P + F N ) Recall=TP / (TP + FN) Recall=TP/(TP+FN)。
- F1分数(F1 Score):精确率和召回率的调和平均数,用于综合评估两者的表现,公式: F 1 S c o r e = 2 ∗ ( P r e c i s i o n ∗ R e c a l l ) / ( P r e c i s i o n + R e c a l l ) F1\ Score=2 * (Precision * Recall) / (Precision + Recall) F1 Score=2∗(Precision∗Recall)/(Precision+Recall)。
- ROC 曲线与 AUC 值(适用于二分类):
- ROC 曲线是一种展示分类模型在不同阈值下的性能的图形化方法,它通过绘制真阳性率(TPR,True Positive Rate)对假阳性率(FPR,False Positive Rate)来实现;
- 真阳性率( T P R ) = T P T P + F N 真阳性率(TPR)= \frac{TP}{TP+FN} 真阳性率(TPR)=TP+FNTP(也称为召回率Recall);
- 假阳性率( F P R ) = F P F P + T N 假阳性率(FPR) = \frac{FP}{FP+TN} 假阳性率(FPR)=FP+TNFP。
- ROC 曲线展示了模型区分正负类别的能力。理想情况下,希望 TPR 尽可能高,同时保持FPR尽可能低。曲线越靠近左上角(即 TPR接近 1 而 FPR 接近 0 ) ,表示模型的性能越好。
- AUC 指的是ROC曲线下方的面积大小,它是衡量模型区分能力的一个单一数值指标,AUC的取值范围从0到1,其中:
- AUC = 1 表示完美的分类器;
- AUC = 0.5 表示模型的表现与随机猜测相同;
- AUC < 0.5 则表示模型比随机猜测还要差(这种情况通常可以通过反转预测标签来改善)。
- AUC值越高,说明模型的平均性能越好,对于不平衡数据集来说,AUC是一个非常有用的评估标准,因为它不直接依赖于类别分布的比例。
- ROC 曲线是一种展示分类模型在不同阈值下的性能的图形化方法,它通过绘制真阳性率(TPR,True Positive Rate)对假阳性率(FPR,False Positive Rate)来实现;
- 回归指标(SVR):
- 均方误差(MSE):预测值与实际值之间差异的平方的平均值;
- R 2 R² R2 值(决定系数):表示模型解释变量变异的比例。
- 分类指标:
2. MATLAB 实现
银行需根据客户信息预测其贷款违约风险,特征包括:
年龄
、月收入
、信用评分
、负债比(负债/收入)
、历史违约次数
;- 标签:0(正常客户),1(高风险客户)。
%% 支持向量机(SVM)根据客户信息预测其贷款违约风险
clc; clear; close all;
%% 生成模拟数据(1000个样本)
rng(25); % 固定随机种子
num_samples = 1000;
% 特征生成
age = randi([22, 65], num_samples, 1); % 年龄:22-65岁
income = rand(num_samples, 1)*15000 + 3000; % 月收入:3000-18000
credit_score = randn(num_samples, 1)*50 + 650; % 信用评分:均值650,标准差50
debt_ratio = rand(num_samples, 1)*0.7 + 0.1; % 负债比:0.1-0.8
past_default = randi([0, 3], num_samples, 1); % 历史违约次数:0-3次
% 标签生成(违约概率与负债比、历史违约次数正相关)
default_prob = 1 ./ (1 + exp(-(0.5*debt_ratio + 0.8*past_default - 0.1*(credit_score-600)/50)));
labels = double(default_prob > 0.6); % 阈值0.6
% 合并特征矩阵
X = [age, income, credit_score, debt_ratio, past_default];
y = labels;
%% 数据标准化(Z-score)
X_scaled = zscore(X);
% 按7:3划分训练集和测试集
cv = cvpartition(y, 'HoldOut', 0.3);
X_train = X_scaled(cv.training, :);
y_train = y(cv.training, :);
X_test = X_scaled(cv.test, :);
y_test = y(cv.test, :);
%% 使用高斯核SVM,设置参数
svm_model = fitcsvm(X_train, y_train, ...
'KernelFunction', 'RBF', ... % 高斯核
'BoxConstraint', 1, ... % 正则化参数C,控制过拟合
'KernelScale', 'auto', ... % 自动计算核参数γ
'Standardize', false); % 已手动标准化数据
%% 预测测试集
[y_pred, scores] = predict(svm_model, X_test);
%% =====================================================================
%% 模型评估指标计算
% 1. 准确率 (Accuracy)
accuracy = sum(y_pred == y_test) / numel(y_test);
% 2. 混淆矩阵
conf_mat = confusionmat(y_test, y_pred);
TP = conf_mat(2,2); % 真正例 (True Positive)
FP = conf_mat(1,2); % 假正例 (False Positive)
FN = conf_mat(2,1); % 假负例 (False Negative)
% 3. 精确率 (Precision)
precision = TP / (TP + FP);
% 4. 召回率 (Recall)
recall = TP / (TP + FN);
% 5. F1-Score
f1_score = 2 * (precision * recall) / (precision + recall);
% 6. 均方误差 (MSE) —— 基于预测概率(需转换为0-1概率)
% 注意:SVM默认输出决策值,需转换为概率(MATLAB需训练后验概率模型)
svm_model = fitPosterior(svm_model); % 训练概率输出模型
[~, prob_estimates] = predict(svm_model, X_test);
mse = mean((prob_estimates(:,2) - y_test).^2); % 使用正类概率计算MSE
% 7. R²值 (基于预测概率)
ss_total = sum((y_test - mean(y_test)).^2);
ss_residual = sum((y_test - prob_estimates(:,2)).^2);
r_squared = 1 - (ss_residual / ss_total);
%% 输出结果
fprintf('=== 模型评估指标 ===\n');
fprintf('准确率: %.2f%%\n', accuracy*100);
fprintf('精确率: %.2f%%\n', precision*100);
fprintf('召回率: %.2f%%\n', recall*100);
fprintf('F1-Score: %.2f\n', f1_score);
fprintf('均方误差 (MSE): %.4f\n', mse);
fprintf('R²值: %.4f\n\n', r_squared);
disp('混淆矩阵:');
disp(conf_mat);
%% 绘制ROC曲线
figure;
[X_roc, Y_roc, ~, AUC] = perfcurve(y_test, scores(:,2), 1);
plot(X_roc, Y_roc, 'LineWidth', 2);
xlabel('假正率 (FPR)');
ylabel('真正率 (TPR)');
title(sprintf('ROC曲线 (AUC = %.2f)', AUC));
grid on;