在机器学习中,支持向量机(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 算法,进行各类数据的二元分类。