本文将通过具体代码示例,带你掌握如何使用 SVM 解决实际问题,包括数据预处理、模型训练、参数调优和结果评估的完整流程。
一、准备工作:环境与库
我们将使用 Python 的 scikit-learn 库,它提供了高效的 SVM 实现。首先确保环境就绪:
安装必要的库
pip install numpy pandas scikit-learn matplotlib seaborn
核心库介绍:
sklearn.svm.SVC
:用于分类任务的 SVM 实现
sklearn.svm.SVR
:用于回归任务的 SVM 实现
sklearn.model_selection
:提供数据分割和交叉验证功能
sklearn.preprocessing
:数据预处理工具
二、基础实战:SVM 分类鸢尾花数据集
我们从经典的鸢尾花数据集入手,这是一个多分类问题,非常适合入门练习。
代码实现:
python
import pandas as pd
import numpy as np
from sklearn.svm import SVC
import matplotlib.pyplot as plt
data = pd.read_csv('iris.csv',header=None)
data1 = data.iloc[:50,:]
data2 = data.iloc[50:,:]
plt.scatter(data1[1], data1[3], marker='+')
plt.scatter(data2[1], data2[3], marker='o')
X = data.iloc[:,[1,3]]
y = data.iloc[:,-1]
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=42)
svm = SVC(kernel='linear',C=float('inf'),random_state=0)
svm.fit(X_train,y_train)
y_pred = svm.predict(X_test)
print(y_pred)
w = svm.coef_[0]
b = svm.intercept_[0]
x1 = np.linspace(0,7,300)
x2 = (-w[0]*x1 - b) / w[1] # 超平面方程
x3 = (-w[0]*x1 - b + 1) / w[1] # 上边界线
x4 = (-w[0]*x1 - b - 1) / w[1] # 下边界线
print(f"\n超平面方程: {w[0]:.4f}*x1 + {w[1]:.4f}*x2 + {b:.4f} = 0")
print(f"上边界线方程: {w[0]:.4f}*x1 + {w[1]:.4f}*x2 + {b:.4f} = 1")
print(f"下边界线方程: {w[0]:.4f}*x1 + {w[1]:.4f}*x2 + {b:.4f} = -1")
plt.plot(x1,x2,linewidth=2,color='r')
plt.plot(x1,x3,linewidth=1,color='r',linestyle='--')
plt.plot(x1,x4,linewidth=1,color='r',linestyle='--')
plt.xlim(4,7)
plt.ylim(0,5)
vets = svm.support_vectors_
plt.scatter(vets[:,0],vets[:,1],c='g',marker='x')
plt.show()
代码解析:
- 数据预处理:SVM 对特征尺度非常敏感,因此必须进行标准化(StandardScaler)
- 核函数选择:这里使用了 线性回归核函数,它是处理非线性数据的通用选择
- 模型评估:通过准确率、混淆矩阵和分类报告全面评估模型性能
- 可视化:为了直观展示 SVM 的决策边界,我们使用了前两个特征进行训练和绘图
运行这段代码,你会发现 SVM 在鸢尾花数据集上可以达到很高的准确率,决策边界图也能清晰展示不同类别鸢尾花的分隔情况。
三、进阶技巧:SVM 参数调优
SVM 的性能很大程度上取决于参数选择,我们可以使用网格搜索(GridSearchCV)来找到最优参数组合。
python
# 基于上面的鸢尾花数据集继续
# 定义参数网格
param_grid = {
'C': [0.1, 1, 10, 100], # 惩罚系数,控制正则化强度
'gamma': ['scale', 'auto', 0.1, 1, 10], # RBF核的带宽参数
'kernel': ['rbf', 'linear', 'poly', 'sigmoid'] # 核函数类型
}
# 网格搜索 + 交叉验证
grid_search = GridSearchCV(
estimator=SVC(random_state=42),
param_grid=param_grid,
cv=5, # 5折交叉验证
n_jobs=-1, # 使用所有可用CPU
verbose=1 # 显示搜索过程
)
# 执行搜索
grid_search.fit(X_train, y_train)
# 输出最佳参数和最佳得分
print("最佳参数组合:", grid_search.best_params_)
print("交叉验证最佳得分:", grid_search.best_score_)
# 使用最佳模型进行预测
best_model = grid_search.best_estimator_
y_pred_best = best_model.predict(X_test)
print("最佳模型在测试集上的准确率:", accuracy_score(y_test, y_pred_best))
关键参数解释:
C:惩罚系数,控制对误分类样本的惩罚力度。C 越大,模型越倾向于正确分类所有训练样本,但可能过拟合;C 越小,允许更多误分类,模型更简单,可能欠拟合。
gamma:仅用于 RBF、poly 和 sigmoid 核。控制单个样本的影响范围,gamma 值越小,影响范围越大;gamma 值越大,模型越容易过拟合。
kernel:核函数类型,常用的有:
linear:线性核,适用于线性可分数据
rbf:径向基函数核,适用于非线性数据
poly:多项式核,适用于具有多项式关系的数据
四、SVM 实战注意事项
- 特征预处理:SVM 对特征尺度敏感,必须进行标准化或归一化
- 样本量考量 :SVM 在中小规模数据集上表现优秀,大规模数据可考虑
SGDClassifier
的 hinge 损失函数替代 - 核函数选择 :
- 优先尝试线性核(速度快,尤其适合高维数据)
- 非线性数据尝试 RBF 核
- 特定领域知识指导下选择多项式核
- 参数调优:C 和 gamma 是关键参数,务必通过交叉验证优化
- 类别不平衡 :可使用
class_weight
参数处理不平衡数
五、总结
通过本文的代码示例,你可以清晰看到 SVM 在分类和回归任务中的基本应用方法。SVM 作为一种经典的机器学习算法,在特征维度高、样本量适中的场景中依然具有很强的竞争力。理解 SVM 的适用场景和参数特性,就可以在实际问题中灵活运用,发挥其最大威力。