在机器学习中,支持向量机(Support Vector Machine, SVM) 是一种用于二元分类的常用算法。SVM 的核心思想是通过找到一个最优的分隔超平面,将样本分为两个不同的类别。与逻辑回归不同,SVM 强调的是“最大化两个类别之间的边界”,这使得它在高维空间中的表现尤其优异。
本篇文章将带你了解 SVM 的基本原理,并通过 C# 实现一个简化的二元分类模型。
什么是支持向量机(SVM)?
SVM 是一种基于几何边界的分类算法。给定一个带有标签的数据集,SVM 会尝试找到一个超平面(线性分类边界)来将数据分隔为不同的类别。为了保证分类效果,SVM 最大化了数据点到分类边界的距离,从而获得分类性能良好的模型。
核心思想
支持向量机的目标是找到一个最优超平面,它不仅能将不同类别的样本分开,还能最大化分类边界的宽度。这种宽度是通过支持向量
,即离超平面最近的数据点来确定的。
SVM 的数学公式
对于线性可分数据,SVM 试图找到一个超平面,使得所有样本点满足:
其中:
-
( y_i ) 为样本 ( x_i ) 的标签(-1 或 +1)。
-
( \mathbf{w} ) 是超平面的法向量。
-
( b ) 是偏置。
SVM 的目标就是找到参数 ( \mathbf{w} ) 和 ( b ),使得数据点到超平面的最小距离最大化。
C#实现支持向量机(SVM)
在 C# 中,我们可以通过实现一个简单的线性 SVM 分类器,利用 梯度下降 来优化参数。以下是基于梯度下降的 SVM 实现代码。
C#代码实现
using System;
class SVM
{
private double[] weights;
private double bias;
private double learningRate;
private int iterations;
private double lambda; // 正则化参数
// 构造函数
public SVM(double learningRate, int iterations, double lambda)
{
this.learningRate = learningRate;
this.iterations = iterations;
this.lambda = lambda;
}
// 训练 SVM 模型
public void Train(double[,] X, double[] y)
{
int m = X.GetLength(0); // 样本数量
int n = X.GetLength(1); // 特征数量
// 初始化权重和偏置
weights = new double[n];
bias = 0;
// 梯度下降迭代
for (int iter = 0; iter < iterations; iter++)
{
for (int i = 0; i < m; i++)
{
double decision = DotProduct(X, weights, i) + bias;
// 判断是否满足约束条件
if (y[i] * decision >= 1)
{
// 样本正确分类,更新权重
for (int j = 0; j < n; j++)
{
weights[j] -= learningRate * (2 * lambda * weights[j]);
}
}
else
{
// 样本未正确分类,更新权重和偏置
for (int j = 0; j < n; j++)
{
weights[j] -= learningRate * (2 * lambda * weights[j] - y[i] * X[i, j]);
}
bias += learningRate * y[i];
}
}
}
}
// 预测函数
public double Predict(double[] X)
{
double decision = DotProduct(X, weights) + bias;
return decision >= 0 ? 1 : -1;
}
// 计算向量点积
private double DotProduct(double[,] X, double[] weights, int rowIndex)
{
double sum = 0;
int n = X.GetLength(1);
for (int i = 0; i < n; i++)
{
sum += X[rowIndex, i] * weights[i];
}
return sum;
}
// 计算向量点积(简化版)
private double DotProduct(double[] X, double[] weights)
{
double sum = 0;
for (int i = 0; i < X.Length; i++)
{
sum += X[i] * weights[i];
}
return sum;
}
}
class Program
{
static void Main()
{
// 训练数据(2个特征)
double[,] X = {
{ 1.0, 2.0 },
{ 2.0, 3.0 },
{ 3.0, 4.0 },
{ 4.0, 5.0 }
};
// 标签(-1 或 1)
double[] y = { -1, -1, 1, 1 };
// 创建 SVM 实例
SVM model = new SVM(learningRate: 0.001, iterations: 1000, lambda: 0.01);
// 训练模型
model.Train(X, y);
// 预测新样本
double[] newSample = { 2.5, 3.5 };
double prediction = model.Predict(newSample);
Console.WriteLine($"预测结果: {(prediction == 1 ? "类别1" : "类别-1")}");
}
}
代码解析
-
训练数据:
X是一个二维数组,包含样本的特征,每行表示一个样本,每列表示一个特征。y是标签数组,表示每个样本的类别(-1 或 1)。 -
SVM 模型:
-
使用
Train方法训练 SVM 模型,通过梯度下降法更新权重和偏置参数。 -
Predict方法用于预测新样本的类别。
-
-
参数解释:
-
learningRate:学习率,用于控制权重更新的步长。 -
iterations:训练的迭代次数。 -
lambda:正则化参数,用于防止过拟合。
-
-
预测:
Predict方法根据新样本的特征,计算该样本的分类结果。如果计算的决策值decision大于等于 0,则返回类别1,否则返回-1。
运行结果
假设训练数据中的样本分为两类(-1 和 1),在完成训练后,我们对一个新样本 { 2.5, 3.5 } 进行预测。程序将输出:
预测结果: 类别1
总结
通过本文的 C# 实现,我们了解了如何使用支持向量机 (SVM) 进行二元分类。SVM 算法通过最大化边界间隔,提供了一个强大且稳健的分类方式。其应用场景十分广泛,尤其适用于高维数据的分类任务。在实际项目中,我们可以使用 C# 来实现 SVM 算法,进行各类数据的二元分类。