系列目录
《Web安全之机器学习入门》笔记:第九章 9.2 支持向量机SVM hello world
《Web安全之机器学习入门》笔记:第九章 9.3 支持向量机算法SVM 检测XSS攻击
《Web安全之机器学习入门》笔记:第九章 9.4 支持向量机算法SVM 检测DGA域名
目录
本系列是《Web安全之机器学习入门》的笔记集合,包含书中第五章-第十七章的内容。本文这一小节主要内容是讲解第8章使用SVM算法的基本用法,本小节是通过随机创建40个点,构造超平面,使用svm处理并分类。
一、SVM算法
支持向量机(SVM)是一种基于统计学习理论的监督学习算法,其核心思想是通过寻找最优超平面(在特征空间中表现为最大间隔分离边界)来实现分类或回归任务。对于线性可分数据,SVM通过最大化决策边界与最近样本点(支持向量)之间的几何间隔来构建分离超平面;对于非线性问题,则借助核技巧(如高斯核、多项式核等)将原始特征映射到高维空间使其线性可分。SVM原理图如下所示。
SVM算法具有严格的数学推导基础,其优化目标转化为凸二次规划问题,可通过拉格朗日乘子法高效求解。SVM特别适合小样本、高维数据场景,具有较强的泛化能力,但计算复杂度随数据量增长而显著增加。
项目 | 详情 |
---|---|
全称 | 支持向量机(Support Vector Machine) |
算法类型 | 有监督学习算法,可用于分类(二分类、多分类)和回归任务 |
原理 | 在特征空间中寻找一个最优超平面,使得不同类别的样本间隔最大。对于线性不可分的数据,通过核函数将数据映射到高维空间使其线性可分 |
核函数 | 常见的有线性核(用于线性可分数据)、多项式核、高斯核(RBF 核)、Sigmoid 核等 |
目标函数 | 最大化分类间隔,通常通过求解二次规划问题来确定最优超平面的参数 |
优点 | 在小样本、高维数据上表现良好;泛化能力强,不易过拟合;可以通过选择不同的核函数处理各种类型的数据 |
缺点 | 对大规模数据集训练时间长;核函数的选择和参数调整较为困难;解释性相对较差 |
应用场景 | 手写字符识别、图像分类、文本分类、生物信息学中的蛋白质分类等 |
二、SVM分类实战
1、数据集处理
本小节的数据通过随机创40个点,前20个标记为10,后20个标记为1。
X = np.r_[np.random.randn(20, 2) - [2, 2], np.random.randn(20, 2) + [2, 2]]
Y = [0] * 20 + [1] * 20
接下来我们打印数据集X与Y,具体如下所示。
[[-0.23594765 -1.59984279]
[-1.02126202 0.2408932 ]
[-0.13244201 -2.97727788]
[-1.04991158 -2.15135721]
[-2.10321885 -1.5894015 ]
[-1.85595643 -0.54572649]
[-1.23896227 -1.87832498]
[-1.55613677 -1.66632567]
[-0.50592093 -2.20515826]
[-1.6869323 -2.85409574]
[-4.55298982 -1.3463814 ]
[-1.1355638 -2.74216502]
[ 0.26975462 -3.45436567]
[-1.95424148 -2.18718385]
[-0.46722079 -0.53064123]
[-1.84505257 -1.62183748]
[-2.88778575 -3.98079647]
[-2.34791215 -1.84365103]
[-0.76970932 -0.79762015]
[-2.38732682 -2.30230275]
[ 0.95144703 0.57998206]
[ 0.29372981 3.9507754 ]
[ 1.49034782 1.5619257 ]
[ 0.74720464 2.77749036]
[ 0.38610215 1.78725972]
[ 1.10453344 2.3869025 ]
[ 1.48919486 0.81936782]
[ 1.97181777 2.42833187]
[ 2.06651722 2.3024719 ]
[ 1.36567791 1.63725883]
[ 1.32753955 1.64044684]
[ 1.18685372 0.2737174 ]
[ 2.17742614 1.59821906]
[ 0.36980165 2.46278226]
[ 1.09270164 2.0519454 ]
[ 2.72909056 2.12898291]
[ 3.13940068 0.76517418]
[ 2.40234164 1.31518991]
[ 1.12920285 1.42115034]
[ 1.68844747 2.05616534]]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
2、训练数据集
本文通过训练线性核支持向量机(SVM)计算分类超平面及相关直线。先初始化 SVM 模型并用数据(X,Y)拟合;从模型中提取超平面系数 w 和截距,计算超平面方程(yy = a*xx - 截距 /w [1]);再基于支持向量计算超平面的两条平行直线(yy_down 和 yy_up),分别通过第一个和最后一个支持向量,为后续可视化分类边界及支持向量位置做准备。具体代码如下所示。
- 模型训练:初始化线性核 SVM,用数据拟合模型
- 超平面系数:提取分类超平面的法向量 w 和截距
- 斜率计算:根据 w 计算超平面斜率 a(-w [0]/w [1])
- 横轴范围:生成从 - 5 到 5 的线性空间 xx 作为横轴数据
- 超平面方程:计算分离超平面的纵轴值 yy
- 下边界线:计算过第一个支持向量的平行直线 yy_down
- 上边界线:计算过最后一个支持向量的平行直线 yy_up
# fit the model
clf = svm.SVC(kernel='linear')
clf.fit(X, Y)
# get the separating hyperplane
w = clf.coef_[0]
a = -w[0] / w[1]
xx = np.linspace(-5, 5)
yy = a * xx - (clf.intercept_[0]) / w[1]
# plot the parallels to the separating hyperplane that pass through the
# support vectors
b = clf.support_vectors_[0]
yy_down = a * xx + (b[1] - a * b[0])
b = clf.support_vectors_[-1]
yy_up = a * xx + (b[1] - a * b[0])
3、完整代码
接下来将源码进行详细注释,代码实现了线性核 SVM 的训练与超平面可视化准备。
- 模型训练:用线性核 SVM 拟合数据集,生成分类超平面
- 参数提取:从训练好的模型中获取法向量和截距
- 方程推导:计算超平面的斜率和截距,构建直线方程
- 边界计算:基于支持向量生成上下边界的平行直线
# 打印模块文档字符串(通常显示示例说明)
print(__doc__)
# 导入必要的库
import numpy as np # 数值计算
import matplotlib.pyplot as plt # 数据可视化
from sklearn import svm # 支持向量机算法
# 创建40个线性可分的数据点(20个负类+20个正类)
np.random.seed(0) # 固定随机种子保证可重复性
# 生成数据:前20个点围绕[-2,-2]的正态分布,后20个点围绕[2,2]的正态分布
X = np.r_[np.random.randn(20, 2) - [2, 2], np.random.randn(20, 2) + [2, 2]]
Y = [0] * 20 + [1] * 20 # 前20个点标签为0,后20个为1
# 创建线性SVM分类器并训练
clf = svm.SVC(kernel='linear') # 使用线性核函数
clf.fit(X, Y) # 训练模型(寻找最优分离超平面)
# 计算分离超平面方程 w·x + b = 0
w = clf.coef_[0] # 获取权重向量(二维)
a = -w[0] / w[1] # 斜率
xx = np.linspace(-5, 5) # 生成x轴坐标范围
# 计算超平面直线方程:y = a*x - b/w[1]
yy = a * xx - (clf.intercept_[0]) / w[1]
# 计算支持向量边界线(与超平面平行且经过支持向量)
# 第一个支持向量的边界线
b = clf.support_vectors_[0]
yy_down = a * xx + (b[1] - a * b[0]) # y = a*x + (y0 - a*x0)
# 最后一个支持向量的边界线
b = clf.support_vectors_[-1]
yy_up = a * xx + (b[1] - a * b[0])
# 绘制可视化图形
plt.plot(xx, yy, 'k-') # 黑色实线:分离超平面
plt.plot(xx, yy_down, 'k--') # 黑色虚线:下边界
plt.plot(xx, yy_up, 'k--') # 黑色虚线:上边界
# 绘制支持向量(空心圆圈突出显示)
plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1],
s=80, # 点大小
facecolors='none') # 空心点
# 绘制所有数据点(按类别着色)
plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Paired)
plt.axis('tight') # 紧凑坐标轴
plt.show() # 显示图形