一、支持向量机介绍
支持向量机(support vector machines, SVM)是一种二分类模型,它的基本模型是定义在特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;SVM还包括核技巧,这使它成为实质上的非线性分类器。SVM的的学习策略就是间隔最大化,可形式化为一个求解凸二次规划的问题,也等价于正则化的合页损失函数的最小化问题。SVM的的学习算法就是求解凸二次规划的最优化算法。
1.svm算法原理
SVM学习的基本想法是求解能够正确划分训练数据集并且几何间隔最大的分离超平面。如上图所示, 即为分离超平面,对于线性可分的数据集来说,这样的超平面有无穷多个(即感知机),但是几何间隔最大的分离超平面却是唯一的。
问题 :将训练样本分开的超平面可能有很多, 哪一个好呢?答案: 应选择”正中间” , 容忍性好, 鲁棒性高, 泛化能力最强
支持向量:距超平面(c)距离最近的点。
支持向量平面:恰好过这些点的平面(a、b)。
超平面:超平面是n维欧氏空间中余维度等于一的线性子空间,也就是必须是(n-1)维度。 如果空间是3维的,那么它的超平面是二维平面,而如果空间是二维的,则其超平面是一维线。
2.支持向量机分类
二、最大间隔与分类
1.超平面方程
2.最大间隔
SVM中,分隔超平面是一个能够将正负样本恰好隔开的超平面,并且使得正样本在分隔超平面“上方”,负样本在分隔超平面”下方“。这就意味着,分隔超平面中的需要满足以下条件:
间隔:
解释一下这个间隔的由来:上图中的x1点代入得到式1:,x2代入得到式2:,将式1-式2得到:,根据向量相乘的性质
,由上图可以看出,即,
所以
最大化间隔:寻找参数w和b , 使得下述公式最大
求的最大值,就是求其倒数的最小值
三、对偶问题
1.等式约束
2.不等式约束的KKT条件
四、SVM实现鸢尾花分类
1.数据集介绍
鸢尾花数据集是一个经典数据集,在统计学习和机器学习领域都经常被用作例子。数据集内包含 3 类共 150 个样本,每类各 50 个样本,每条样本都有 4 个特征:花萼长度、花萼宽度、花瓣长度、花瓣宽度,可以通过这 4 个特征预测鸢尾花属于(iris-setosa, iris-versicolour, iris-virginica)中的哪个品种。
花萼长度 | 花萼宽度 | 花瓣长度 | 花瓣宽度 |
5.1 | 3.3 | 1.7 | 0.5 |
5.0 | 2.3 | 3.3 | 1.0 |
6.4 | 2.8 | 5.6 | 2.2 |
品种(标签) |
0(山鸢尾) |
1(变色鸢尾) |
2(维吉尼亚鸢尾) |
2.代码实现
# 导入所需的库
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
class SVM:
def __init__(self, learning_rate=0.001, lambda_param=0.01, n_iters=1000):
self.lr = learning_rate
self.lambda_param = lambda_param
self.n_iters = n_iters
self.w = None
self.b = None
def fit(self, X, y):
n_samples, n_features = X.shape
y_ = np.where(y <= 0, -1, 1)
self.w = np.zeros(n_features)
self.b = 0
for _ in range(self.n_iters):
for idx, x_i in enumerate(X):
condition = y_[idx] * (np.dot(x_i, self.w) - self.b) >= 1
if condition:
self.w -= self.lr * (2 * self.lambda_param * self.w)
else:
self.w -= self.lr * (2 * self.lambda_param * self.w - np.dot(x_i, y_[idx]))
self.b -= self.lr * y_[idx]
def predict(self, X):
linear_output = np.dot(X, self.w) - self.b
return np.sign(linear_output)
# 加载鸢尾花数据集
iris = datasets.load_iris()
X = iris.data[:, :2] # 只取前两个特征以便于可视化
y = iris.target
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建并训练SVM模型
model = SVM()
model.fit(X_train, y_train)
# 预测训练集和测试集
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
# 计算训练集和测试集的准确率
train_accuracy = np.sum(y_train_pred == y_train) / len(y_train)
test_accuracy = np.sum(y_test_pred == y_test) / len(y_test)
print(f'Train Accuracy: {train_accuracy*100:.2f}%')
print(f'Test Accuracy: {test_accuracy*100:.2f}%')
# 可视化
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=plt.cm.coolwarm)
ax = plt.gca()
xlim = ax.get_xlim()
ylim = ax.get_ylim()
xx = np.linspace(xlim[0], xlim[1], 30)
yy = np.linspace(ylim[0], ylim[1], 30)
YY, XX = np.meshgrid(yy, xx)
xy = np.vstack([XX.ravel(), YY.ravel()]).T
Z = model.predict(xy).reshape(XX.shape)
ax.contour(XX, YY, Z, colors='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--'])
plt.show()