简介
支持向量机(Support Vector Machine,简称 SVM)是一种非常强大且灵活的监督学习算法,用于分类和回归任务。其基本思想是在特征空间中找到一个最优的超平面,将不同类别的样本分开,并且使得超平面与最近的样本点的距离(也称为间隔)最大化。
以下是支持向量机的一些关键概念:
-
超平面(Hyperplane):在一个n维空间中,超平面是一个n-1维的平面,它将空间划分为两个部分。在二维空间中,超平面是一条直线,而在三维空间中,超平面是一个平面。
-
间隔(Margin):超平面与离它最近的样本点之间的距离称为间隔。SVM 的目标是最大化间隔,以提高分类的鲁棒性。
-
支持向量(Support Vectors):支持向量是离超平面最近的那些点。这些点决定了超平面的位置,并且在计算间隔和决定分类边界时起到重要作用。
-
核技巧(Kernel Trick):在低维特征空间中可能无法线性分割样本,这时可以使用核技巧将样本映射到高维特征空间中,从而实现在高维空间中线性分割样本的目的。常用的核函数包括线性核、多项式核、高斯核等。
-
正则化参数(Regularization Parameter):用于控制模型的复杂度,避免过拟合。正则化参数越大,模型的复杂度越低,反之亦然。
SVM 在解决线性和非线性分类问题上表现出色,并且对于高维数据集的处理效果也很好。其应用领域涵盖图像分类、文本分类、生物信息学、金融数据分析等多个领域。
原理
SVM的基本原理是找到一个最优的超平面,将不同类别的样本点分开,并使超平面与最近的样本点的距离最大化。
通过最大化间隔,提高分类的鲁棒性。
代码实现
- 生成数据集
def generate_data(samples):
# 生成随机特征
X = np.random.rand(samples, 2) * 10
# 根据新规则生成标签,x1 + x2 > 5 为类别1
y = np.zeros(samples)
for i in range(samples):
if X[i, 0] + X[i, 1] > 10:
y[i] = 1
return X, y
- 划分数据集
def split_data(X, y, rate):
#调整标签数组的形状
y.resize((y.size, 1))
#合并特征和标签
data = np.concatenate((X, y), axis=1)
#打乱数据
np.random.shuffle(data)
test_len = y.size - int(rate * y.size)
return data[:test_len, :2], data[test_len:, :2], data[:test_len, 2], data[test_len:, 2]
- 向量机训练模型
class SupportVectorMachine:
def __init__(self, learning_rate=0.01, num_iterations=1000, C=1.0):
self.learning_rate = learning_rate
self.num_iterations = num_iterations
self.C = C
self.weights = None
self.bias = None
def fit(self, X, y):
num_samples, num_features = X.shape
# 初始化参数
self.weights = np.zeros(num_features)
self.bias = 0
# 梯度下降优化
for _ in range(self.num_iterations):
for i, x_i in enumerate(X):
condition = y[i] * (np.dot(x_i, self.weights) - self.bias) >= 1
if condition:
self.weights -= self.learning_rate * (2 * self.C * self.weights)
else:
self.weights -= self.learning_rate * (2 * self.C * self.weights - np.dot(x_i, y[i]))
self.bias -= self.learning_rate * y[i]
def predict(self, X):
linear_output = np.dot(X, self.weights) - self.bias
return np.sign(linear_output)
- 决策边界
def plot_decision_boundary(model, X, y):
# 创建网格来绘制决策边界
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, 0.02),
np.arange(x2_min, x2_max, 0.02))
# 将网格点数据放入模型中进行预测
Z = model.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
Z = Z.reshape(xx1.shape)
# 绘制等高线
plt.contourf(xx1, xx2, Z, alpha=0.3)
# 绘制样本点
plt.scatter(X[:, 0], X[:, 1], c=y, marker='o', edgecolors='k', label='Data Points')
# 绘制支持向量
plt.scatter(X[model.support_vectors_idx, 0], X[model.support_vectors_idx, 1], c='red', marker='x', label='Support Vectors')
# 设置图标题和坐标轴标题
plt.title('Decision Boundary')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend()
plt.show()
最终完善代码
import numpy as np
import matplotlib.pyplot as plt
# 设置字体为宋体
plt.rcParams['font.family'] = ['serif'] # 设置字体为有衬线字体(宋体是有衬线字体之一)
plt.rcParams['font.serif'] = ['SimSun'] # 设置有衬线字体为宋体
# 生成数据集
def generate_data(samples):
from sklearn.datasets import make_blobs
X, y = make_blobs(n_samples=samples, centers=2, random_state=42)
y = np.where(y == 0, -1, 1)
return X, y
class SupportVectorMachine:
def __init__(self, learning_rate=0.01, num_iterations=1000, C=1.0):
self.learning_rate = learning_rate
self.num_iterations = num_iterations
self.C = C
self.weights = None
self.bias = None
self.support_vectors_idx = None
def fit(self, X, y):
num_samples, num_features = X.shape
# 初始化参数
self.weights = np.zeros(num_features)
self.bias = 0
# 梯度下降优化
for _ in range(self.num_iterations):
for i, x_i in enumerate(X):
condition = y[i] * (np.dot(x_i, self.weights) - self.bias) >= 1
if condition:
self.weights -= self.learning_rate * (2 * self.C * self.weights)
else:
self.weights -= self.learning_rate * (2 * self.C * self.weights - np.dot(x_i, y[i]))
self.bias -= self.learning_rate * y[i]
# 记录支持向量的索引
self.support_vectors_idx = np.where((y * (np.dot(X, self.weights) - self.bias)) < 1)[0]
def predict(self, X):
linear_output = np.dot(X, self.weights) - self.bias
return np.sign(linear_output)
def plot_decision_boundary(model, X, y):
# 创建网格来绘制决策边界
x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, 0.02),
np.arange(x2_min, x2_max, 0.02))
# 将网格点数据放入模型中进行预测
Z = model.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
Z = Z.reshape(xx1.shape)
# 绘制等高线
plt.contourf(xx1, xx2, Z, alpha=0.3)
# 绘制样本点
plt.scatter(X[:, 0], X[:, 1], c=y, marker='o', edgecolors='k', label='Data Points')
# 绘制支持向量
plt.scatter(X[model.support_vectors_idx, 0], X[model.support_vectors_idx, 1], c='red', marker='x', label='Support Vectors')
# 设置图标题和坐标轴标题
plt.title('Decision Boundary')
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.legend()
plt.show()
# 样本和数据集划分
samples = 50
# 构造数据集
X, y = generate_data(samples)
# 训练SVM模型
svm_model = SupportVectorMachine()
svm_model.fit(X, y)
# 绘制决策边界和支持向量
plot_decision_boundary(svm_model, X, y)
总结
支持向量机(Support Vector Machine,SVM)是一种强大的机器学习算法,适用于分类和回归任务。以下是关于支持向量机的主要要点总结:
-
优点:
- 在高维空间中表现良好,适用于复杂的数据集。
- 对于小样本数据集具有较好的泛化能力。
- 可以使用不同的核函数来处理线性和非线性问题。
-
缺点:
- 对于大规模数据集训练时间较长。
- 对于高维稀疏数据集的效果可能不如其他算法。
-
应用:
- 图像分类
- 文本分类
- 生物信息学
- 金融数据分析等多个领域。
综上所述,支持向量机是一种功能强大的算法,广泛应用于各种机器学习任务中,尤其适用于处理高维数据和复杂分类问题。