复现SMO算法:从理论到实践的Python实现【四、实战编程】

python复现SMO算法

任务要求重述

  1. 复现带有高斯核的SMO算法

  2. 数据集规模需要大于1000条(数据为a5a,二分类问题)

  3. libsvm对比训练精度和时间,要求在 超参一致 的情况下,精度相差不超过1%。

步骤一:数据读取和预处理

在支持向量机(SVM)的实践应用中,正确地加载和预处理数据是非常重要的。我们通常从以 LIBSVM格式 存储的文件中读取数据,每一行代表一个样本,其中包含一个样本的标签和随后的特征值。在这个教程中,我们将使用 scikit-learn 库中的工具来辅助我们处理数据。

首先,安装 scikit-learn

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scikit-learn

我们将定义一个函数来加载数据,并确保所有特征维度和标签格式一致:

python 复制代码
import numpy as np
from sklearn.datasets import load_svmlight_file

def load_and_combine_features(train_file, test_file):
    X_train, y_train = load_svmlight_file(train_file, n_features=123)
    X_test, y_test = load_svmlight_file(test_file, n_features=123)
    # 确保训练集和测试集具有相同的特征空间
    return X_train.toarray(), y_train, X_test.toarray(), y_test

# 加载数据
X_train, y_train,X_test, y_test  = load_and_combine_features("../data/a5a.txt","../data/a5a.t.txt")

这里,我们使用 load_svmlight_file 函数直接读取LIBSVM格式的数据,并通过指定 n_features=123 来确保所有数据样本具有相同数量的特征。我们还将稀疏矩阵转换为密集数组,以便于后续处理。

步骤二:初步数据分析

首先,我们查看一下训练数据和测试数据的维度,以及正负样本的分布情况。

python 复制代码
def analyze_data(X, y):
    # 数据维度
    n_samples, n_features = X.shape
    # 标签类别统计
    positive_samples = np.sum(y == 1)
    negative_samples = np.sum(y == -1)
    
    return n_samples, n_features, positive_samples, negative_samples

# 分析训练数据和测试数据
train_info = analyze_data(X_train, y_train)
test_info = analyze_data(X_test, y_test)

print("训练数据:样本数 = {}, 特征数 = {}, 正样本数 = {}, 负样本数 = {}".format(*train_info))
print("测试数据:样本数 = {}, 特征数 = {}, 正样本数 = {}, 负样本数 = {}".format(*test_info))

对SVM重要的数据特征

由于SVM对特征尺度敏感,尤其是使用高斯核时,不均匀的特征尺度可能会显著影响模型的性能。接下来,我们将计算特征的均值和标准差,以决定是否需要进行特征缩放:

python 复制代码
def feature_statistics(X):
    # 计算特征的均值和标准差
    mean_features = np.mean(X, axis=0)
    std_features = np.std(X, axis=0)
    return mean_features, std_features

train_mean, train_std = feature_statistics(X_train)
test_mean, test_std = feature_statistics(X_test)

print("训练数据特征均值: ", train_mean)
print("训练数据特征标准差: ", train_std)
print("测试数据特征均值: ", test_mean)
print("测试数据特征标准差: ", test_std)

数据分析总结

特征均值和标准差:

  • 训练数据和测试数据的特征均值及标准差相近,说明两个数据集在特征分布上具有一定的一致性
  • 特征的均值和标准差差异较大,表明数据各维度的 尺度不一 ,可能需要进行特征标准化以提高SVM的性能。

特征标准化

基于以上分析,特征标准化是必要的,以确保所有特征具有相同的尺度。这可以通过减去均值并除以标准差来实现:

python 复制代码
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

通过上述步骤,我们为SVM模型的训练和测试准备了数据,同时确保了数据的质量和一致性,为接下来的模型训练和评估奠定了基础。

步骤三:构建高斯核函数

高斯核函数

高斯核也称为径向基函数(RBF)核,它是支持向量机(SVM)中使用的一种非常流行的核函数。其主要作用是将原始特征空间中的样本映射到一个更高维的空间中,帮助处理那些在原始空间中非线性可分的数据。高斯核的公式是:

K ( x i , x j ) = exp ⁡ ( − ∥ x i − x j ∥ 2 2 σ 2 ) K(x_i, x_j) = \exp\left(-\frac{\|x_i - x_j\|^2}{2\sigma^2}\right) K(xi,xj)=exp(−2σ2∥xi−xj∥2)

其中, x i x_i xi 和 x j x_j xj 是两个样本点, σ \sigma σ 是核函数的带宽参数,控制了数据映射到新空间的分散程度

在很多机器学习库中,比如 sklearn,高斯核的表达式常写作:

K ( x , x ′ ) = e − γ ∥ x − x ′ ∥ 2 K(x, x') = e^{-\gamma \|x - x'\|^2} K(x,x′)=e−γ∥x−x′∥2

其中, γ \gamma γ 通常定义为 1 2 σ 2 \frac{1}{2\sigma^2} 2σ21, γ \gamma γ 能够控制函数的宽度,

1. 函数定义:

python 复制代码
def gaussian_kernel(x1, x2, gamma=0.00819672131147541):

首先我们定义一个名为 gaussian_kernel 的函数,接收两个样本集 x1x2,以及一个可选的 gamma 参数,默认值为 1 122 = 0.00819672131147541 \frac{1}{122} = 0.00819672131147541 1221=0.00819672131147541。

默认设置 γ = 1 特征数 \gamma = \frac{1}{\text{特征数}} γ=特征数1 是一种常见的启发式方法,尤其是在我们没有足够信息对 σ \sigma σ 进行优化调整的情况下,这可以提供一个合理的起点。

这种设置假设数据在所有维度上 均匀分布 ,且各特征的重要性相同,但在实际应用中,根据数据的具体特性来调整 γ \gamma γ (从而影响 σ \sigma σ)通常会获得更好的结果。
当然,我们可以考虑使用如交叉验证等方法来找到最优的 γ \gamma γ 值。

2. 处理不同形状的输入:

  • 两个一维向量的情况:

    python 复制代码
    if np.ndim(x1) == 1 and np.ndim(x2) == 1:
        result = np.exp(-np.linalg.norm(x1-x2)**2 * gamma )

    这种情况下,x1x2 都是单个样本(一维数组)。使用 np.linalg.norm(x1 - x2) 计算两个向量之间的 欧氏距离 ,然后根据高斯核函数的公式计算结果。

  • 一个是一维向量,一个是二维数组的情况:

    python 复制代码
    elif (np.ndim(x1) > 1 and np.ndim(x2) == 1) or (np.ndim(x1) == 1 and np.ndim(x2) > 1):
        result = np.exp(-np.linalg.norm(x1-x2, axis=1)**2 * gamma)

    这里处理的是一个样本与多个样本之间的高斯核计算。例如,x1 可能是一个二维数组(多个样本),而 x2 是一个一维数组(单个样本),或反之。np.linalg.norm(x1 - x2, axis=1) 沿着第一个轴( 每个样本的特征轴 )计算距离,适用于批量处理,从而得到一个向量,其中包含了与 x2 每个样本的核值。

  • 两个都是二维数组的情况:

    python 复制代码
    else:
        result = np.exp(-np.linalg.norm(x1[:, np.newaxis] - x2[np.newaxis, :], axis=2)** 2 * gamma)

    x1x2 都是二维数组时,该代码计算所有可能的成对样本之间的核。使用 np.newaxis 增加一个新的轴,使两个数组广播能够生成一个距离矩阵,其中包含了每对样本之间的距离。

python 复制代码
def gaussian_kernel(x1, x2, gamma=0.0081967213114754):
    """
    计算两个输入数组x1和x2之间的高斯核矩阵。
    参数:
        x1: 第一个样本数组,可以是一维或二维numpy数组。
        x2: 第二个样本数组,可以是一维或二维numpy数组。
        gamma: 高斯核的带宽参数,控制核的宽度。
    返回:
        高斯核矩阵,其中每个元素都是x1和x2中对应样本点的核函数值。
    """
    if np.ndim(x1) == 1 and np.ndim(x2) == 1:
        result = np.exp(-np.linalg.norm(x1 - x2)**2 * gamma)
    elif (np.ndim(x1) > 1 and np.ndim(x2) == 1) or (np.ndim(x1) == 1 and np.ndim(x2) > 1):
        result = np.exp(-np.linalg.norm(x1 - x2, axis=1)**2 * gamma)
    else:
        result = np.exp(-np.linalg.norm(x1[:, np.newaxis] - x2[np.newaxis, :], axis=2)**2 * gamma)
    return result

步骤四:预测输出函数

首先,我们从所有训练样本中选择一个违反KKT条件最严重的样本作为 α 1 \alpha_1 α1。违反KKT条件的程度可以通过计算 ∣ y i f ( x i ) − 1 ∣ |y_i f(x_i) - 1| ∣yif(xi)−1∣ 来量化,其中 f ( x i ) f(x_i) f(xi) 是模型在 x i x_i xi 上的 预测输出 。我们首先需要定义如何计算 f ( x i ) f(x_i) f(xi),它基于当前模型的参数:

python 复制代码
def compute_fx(X, y, alpha, b, x_i, gamma=0.0081967213114754):
    """
    计算模型在单个样本 x_i 上的预测输出。
    参数:
        X: 训练样本集。
        y: 标签数组。
        alpha: 拉格朗日乘数数组。
        b: 偏置项。
        x_i: 当前样本点。
        gamma: 高斯核的带宽参数,控制核的宽度。
    返回:
        f(x_i): 模型对 x_i 的预测输出。
    """
    # 调用高斯核函数计算核矩阵
    kernel_values = gaussian_kernel(X, x_i, gamma)
    return np.sum(alpha * y * kernel_values) + b

在这种情况下, x 1 x_1 x1 对应 X X X(二维数组), x 2 x_2 x2 对应 x_i(一维数组)。函数通过 axis=1 参数计算每行(每个样本)与 x i x_i xi 的欧式距离的平方,然后应用高斯函数变换。这样,输出结果 result 将是一个 一维数组 ,其中包含了 X X X 中每个样本与 x i x_i xi 的高斯核值。

步骤五:选择违反KKT条件最严重的 α 1 \alpha_1 α1【启发式方法】

关于整体SMO算法框架,一般会在一个循环中执行以下步骤:

  1. 选择违反KKT条件最严重的 α 1 \alpha_1 α1。
  2. 基于 α 1 \alpha_1 α1找到最优的 α 2 \alpha_2 α2。
  3. 对这两个 α \alpha α进行优化。
  4. 更新 b b b和 E E E。
    这种方法是直接在

KKT条件违反的判断

在所有支持向量机的训练样本中,选择违反KKT条件最严重的样本作为 α 1 \alpha_1 α1。这一选择是基于以下KKT条件违反的判断:

  • 当 α i = 0 \alpha_i = 0 αi=0 时,样本应在决策边界的正确一侧,即 y i f ( x i ) ≥ 1 y_i f(x_i) \geq 1 yif(xi)≥1。
  • 当 0 < α i < C 0 < \alpha_i < C 0<αi<C 时,样本应恰好在边界上,即 y i f ( x i ) = 1 y_i f(x_i) = 1 yif(xi)=1。
  • 当 α i = C \alpha_i = C αi=C 时,样本应在决策边界的错误一侧,即 y i f ( x i ) ≤ 1 y_i f(x_i) \leq 1 yif(xi)≤1。

违反程度可以通过 ∣ y i f ( x i ) − 1 ∣ |y_i f(x_i) - 1| ∣yif(xi)−1∣ 来量化,选择这个量值最大的样本。

KKT条件违反的测量

对于每个给定的训练样本 ( x i , y i ) (x_i, y_i) (xi,yi),其对应的拉格朗日乘子 α i \alpha_i αi,模型预测的输出为 f ( x i ) f(x_i) f(xi)。根据 α i \alpha_i αi 的值和 y i f ( x i ) y_i f(x_i) yif(xi),KKT条件违反我们可以通过以下方式测量:

  • 当 α i = 0 \alpha_i = 0 αi=0 且 y i f ( x i ) < 1 y_i f(x_i) < 1 yif(xi)<1,违反程度为 1 − y i f ( x i ) 1 - y_i f(x_i) 1−yif(xi)。
  • 当 0 < α i < C 0 < \alpha_i < C 0<αi<C,使用一个小的容忍度 ϵ \epsilon ϵ 来判断,若 ∣ y i f ( x i ) − 1 ∣ > ϵ |y_i f(x_i) - 1| > \epsilon ∣yif(xi)−1∣>ϵ,则视为违反。
  • 当 α i = C \alpha_i = C αi=C 且 y i f ( x i ) > 1 y_i f(x_i) > 1 yif(xi)>1,违反程度为 y i f ( x i ) − 1 y_i f(x_i) - 1 yif(xi)−1。

函数实现

通过以下步骤实现选择 α 1 \alpha_1 α1 的逻辑:

输入:

  • X: 训练样本的特征集合。
  • y: 训练样本的标签集合。
  • alpha: 拉格朗日乘数的当前值。
  • b: 当前的偏置项。
  • gamma: 核函数宽度。
  • C: 正则化参数,控制优化问题的边界硬度。

输出:

  • idx: 违反KKT条件最严重的样本的索引。
  • E[idx]: 该样本的违反程度。

处理逻辑:

  1. 初始化误差数组 E
  2. 遍历每个样本计算其预测输出 f ( x i ) f(x_i) f(xi)。
  3. 计算每个样本的误差 E i = f ( x i ) − y i E_i = f(x_i) - y_i Ei=f(xi)−yi 和KKT违反程度。
  4. 根据 α i \alpha_i αi 的值和 y i f ( x i ) y_i f(x_i) yif(xi),计算KKT违反程度。
  5. 选择违反程度最大的样本的索引作为 α 1 \alpha_1 α1。

代码示例

python 复制代码
def select_alpha1(X, y, alpha, b, gamma, C):
    m = len(y)
    E = np.zeros(m)
    tol = 1e-4  # 容忍度
    for i in range(m):
        fx_i = compute_fx(X, y, alpha, b, X[i], gamma)  # 注意这里直接传入 gamma 而不是 kernel
        E[i] = fx_i - y[i]
        KKT_violation = y[i] * fx_i

        # 根据KKT条件计算违反程度
        if (alpha[i] == 0 and KKT_violation < 1) or \
                (0 < alpha[i] < C and not (1-tol < KKT_violation < 1+tol)) or \
                (alpha[i] == C and KKT_violation > 1): 
                
            E[i] = np.abs(KKT_violation - 1)

    idx = np.argmax(E)
    return idx, E[idx]

步骤六:基于 α 1 \alpha_1 α1 找到最优的 α 2 \alpha_2 α2

选择标准

在这一步中, α 2 \alpha_2 α2 的选择依赖于找到与 α 1 \alpha_1 α1 的预测误差 E 1 E_1 E1 差距最大的 α 2 \alpha_2 α2 。理想的 α 2 \alpha_2 α2 应该最大化误差差 ∣ E 1 − E 2 ∣ |E_1 - E_2| ∣E1−E2∣,这通常可以带来最大的目标函数变化。

实现步骤

从误差向量 E E E 中选择 α 2 \alpha_2 α2

  • 给定已选的 α 1 \alpha_1 α1 的索引 i d x 1 idx1 idx1 和对应的误差向量 E E E,找出误差差 ∣ E 1 − E 2 ∣ |E_1 - E_2| ∣E1−E2∣ 最大的 α 2 \alpha_2 α2。
  • 排除 α 1 \alpha_1 α1 自身,确保 α 2 \alpha_2 α2 是不同的样本。
代码实现

这个函数首先需要计算了除 α 1 \alpha_1 α1 外所有样本的误差差的绝对值,然后从中选择误差差最大的索引作为 α 2 \alpha_2 α2。

python 复制代码
def select_alpha2(E, idx1):
    """
    选择最优的 alpha2。
    参数:
        E: 所有样本的误差数组。
        idx1: alpha1 的索引。
    返回:
        idx2: 最优 alpha2 的索引。
    """
    # 计算与 alpha1 的误差差的绝对值
    E_diff = np.abs(E - E[idx1])
    # 确保不会选择同一个样本作为 alpha2
    E_diff[idx1] = 0
    # 选择最大误差差的索引作为 alpha2
    idx2 = np.argmax(E_diff)
    return idx2

步骤七:优化 α 1 \alpha_1 α1 和 α 2 \alpha_2 α2 并更新模型偏置和误差

选择了 α 1 \alpha_1 α1 和 α 2 \alpha_2 α2 后,下一步是优化这两个拉格朗日乘子,并更新模型的偏置项 b b b 和误差向量 E E E。这一步是实现模型优化的核心,涉及到核函数的计算、乘子的更新和偏置的调整。

优化 α 1 \alpha_1 α1 和 α 2 \alpha_2 α2

优化过程包括以下几个关键步骤:

  1. 计算 η \eta η:

    • η \eta η 是核函数的负二阶导数,代表了样本 x 1 x_1 x1 和 x 2 x_2 x2 在特征空间中的距离,其计算公式为:
      η = K ( x 1 , x 1 ) + K ( x 2 , x 2 ) − 2 K ( x 1 , x 2 ) \eta = K(x_1, x_1) + K(x_2, x_2) - 2K(x_1, x_2) η=K(x1,x1)+K(x2,x2)−2K(x1,x2)
    • 如果 η \eta η 为非正,则停止当前的优化步骤。
  2. 更新 α 2 \alpha_2 α2:

    • 利用计算得到的 η \eta η,更新 α 2 \alpha_2 α2:
      α 2 n e w = α 2 o l d + y 2 ( E 1 − E 2 ) η \alpha_2^{new} = \alpha_2^{old} + \frac{y_2 (E_1 - E_2)}{\eta} α2new=α2old+ηy2(E1−E2)
    • 对 α 2 n e w \alpha_2^{new} α2new 进行剪辑,以确保其值位于合法区间 [0, C] 内。
  3. 更新 α 1 \alpha_1 α1:

    • 根据拉格朗日乘子的求和约束,更新 α 1 \alpha_1 α1:
      α 1 n e w = α 1 o l d + y 1 y 2 ( α 2 o l d − α 2 n e w ) \alpha_1^{new} = \alpha_1^{old} + y_1 y_2 (\alpha_2^{old} - \alpha_2^{new}) α1new=α1old+y1y2(α2old−α2new)

更新模型的偏置 b b b

偏置 b b b 的更新至关重要,它确保了模型的决策边界正确地反映了数据的分布:

  • 通过比较 α 1 n e w \alpha_1^{new} α1new 和 α 2 n e w \alpha_2^{new} α2new 是否位于其合法区间 (0, C),选择适当的方法来更新 b b b。
  • 新的偏置值 b n e w b_{new} bnew 是根据 α 1 \alpha_1 α1 和 α 2 \alpha_2 α2 的更新量以及它们在核空间中的位置变化计算得出的。

更新误差 E E E

更新每个样本的误差值 E i E_i Ei 是为了反映拉格朗日乘子和偏置项的最新影响:

  • 误差 E i E_i Ei 为模型在样本 x i x_i xi 上的实际输出与预期输出的差异,更新公式为:
    E [ i ] = f ( x i ) − y [ i ] E[i] = f(x_i) - y[i] E[i]=f(xi)−y[i]

代码实现

以下是对 α 1 \alpha_1 α1 和 α 2 \alpha_2 α2 进行优化以及更新 b b b 和 E E E 的 Python 函数实现:

python 复制代码
def update_alpha_and_b(X,y,alpha , b , idx1, idx2 , E , C):
    x1 , x2 = X[idx1] , X[idx2]
    y1 , y2 = y[idx1] , y[idx2]
    alpha1_old , alpha2_old = alpha[idx1] , alpha[idx2]

    # 进行迭代,迭代主要公式 alpha2_new = alpha2_old + y2(E1 - E2) / (K11 - 2K12 + K22)

    # 计算 eta = (K11 - 2K12 + K22)
    K11 = gaussian_kernel(x1, x1)
    K12 = gaussian_kernel(x1, x2)
    K22 = gaussian_kernel(x2, x2)
    eta = K11 - 2 * K12 + K22

    if eta <= 0:
        return False

    # 更新 alpha2_new
    alpha2_new = alpha2_old + y2*( abs(E[idx1] - E[idx2]) ) / eta

    L , H = 0 ,  C
    # 剪辑,使用公式
    if y1 != y2:
        L = max(0 , alpha2_old - alpha1_old)
        H = min(C , C + alpha2_old - alpha1_old)
    else:
        L = max(0 , alpha1_old + alpha2_old - C)
        H = min(C , alpha1_old + alpha2_old)


    alpha2_new = max(min(alpha2_new, H), L)

    # 计算a1,公式 a1new = a1old + y1y2(a2old - a2new)
    alpha1_new = alpha1_old + y1 * y2 * (alpha2_old - alpha2_new)

    # 计算新旧alpha之间的变化量
    delta_alpha1 = alpha1_new - alpha1_old
    delta_alpha2 = alpha2_new - alpha2_old

    b1_new = b - E[idx1] - y1 * K11 * delta_alpha1 - y2 * K12 * delta_alpha2
    b2_new = b - E[idx2] - y1 * K12 * delta_alpha1 - y2 * K22 * delta_alpha2

    if alpha1_new > 0 and alpha1_new < C:
        b = b1_new
    elif alpha2_new > 0 and alpha2_old < C:
        b = b2_new
    else:
        b = (b1_new + b2_new) / 2

    alpha[idx1] , alpha[idx2] = alpha1_new , alpha2_new

    # 更新 E
    for i in range(len(E)):
        E[i] = compute_fx(X, y, alpha, b, X[i]) - y[i]

    return True

这段代码实现了在给定 α 1 \alpha_1 α1 和 α 2 \alpha_2 α2 的情况下,对这两个乘数进行优化,并相应地更新了模型的偏置和误差。通过这些更新,我们可以确保模型逐渐逼近最优解。

步骤七:SMO算法核心框架

对于每个 α 1 \alpha_1 α1,首先计算对应的预测输出 f ( x i ) f(x_i) f(xi),然后计算预测误差 E i = f ( x i ) − y i E_i = f(x_i) - y_i Ei=f(xi)−yi。接下来,它检查是否满足KKT条件,如果违反了KKT条件,则将该 α 1 \alpha_1 α1 选择为待优化的对象。

注意: 在这里不是直接选择违反KKT条件最严重的 α 1 \alpha_1 α1,而是进行逐个检查,该方法在实践中通常能够获得不错的结果。

参数介绍

  • 迭代次数(max_passes):这是外循环的最大迭代次数。
  • 容忍度(tol):用于KKT条件违反的测量。
  • C:SVM的正则化参数。
  • gamma:核函数的参数。
python 复制代码
def smo_algorithm(X, y, C, tol, max_passes, gamma):
    ''''
        1.初始化
        2.循环优化
        3.判断违反KKT条件
        4.选择a2
        5.优化a1,a2,并更新
    '''
    m = len(y)
    b = 0
    passes = 0
    alpha = np.zeros(m)
    E = np.zeros(m)

    while passes < max_passes :
        alpha_change_times = 0
        for i in range(m):
            E[i] = compute_fx(X , y , alpha , b , X[i]) - y[i]
            if (y[i]*E[i] < -tol and alpha[i] < C) or (y[i]*E[i] > tol and alpha[i] > 0):
                j = select_alpha2(E,i)
                if update_alpha_and_b(X , y , alpha , b , i , j , E , C):
                    alpha_change_times += 1

        if alpha_change_times == 0:
            passes += 1;
        else:
            passes = 0

    return alpha , b

步骤八:主函数中调用

在这一步中,我们将配置 SMO 算法的参数并调用算法函数。这包括设置正则化参数 C,容忍度 tol,最大迭代次数 max_passes,以及高斯核的带宽参数 gamma(默认为1÷特征数)。

python 复制代码
# 运行SMO算法
C = 1.0
tol = 1e-3
max_passes = 10
gamma = 0.0081967213114754

alpha, b = smo_algorithm(X_train_scaled, y_train, C, tol, max_passes, gamma)

步骤九:记录时间和精度

此步骤涉及计算 SMO 算法的训练时间以及在测试集上的精度。这允许我们评估算法的效率和效果。首先记录算法开始的时间,然后进行预测并计算完成预测的时间,最后计算并打印出算法的精度。

python 复制代码
start_time = time.time()
# 进行预测
predictions = predict(X_train_scaled, y_train, X_test_scaled, alpha, b, gamma)
training_time = time.time() - start_time


# 计算准确率
accuracy = np.mean(predictions == y_test)
print("SMO训练时间: {:.2f}秒".format(training_time))
print("SMO测试集准确率: {:.2%}".format(accuracy))

步骤十:对比libsvm实现精度和时间

在这一步中,我们使用 sklearn 库的 SVM 实现(libsvm)进行同样的任务,以便与我们自己实现的 SMO 算法进行性能对比。我们配置与自定义 SMO 相同的参数,运行 libsvm 的 SVC,记录时间,并计算精度,以展示两种方法的性能差异。

python 复制代码
from sklearn import svm
# 使用libsvm的SVC
model = svm.SVC(kernel='rbf',tol=tol, C=1.0, gamma=0.0081967213114754)
start_time = time.time()
model.fit(X_train_scaled, y_train)
training_time = time.time() - start_time

# 进行预测
predictions_libsvm = model.predict(X_test_scaled)
accuracy_libsvm = accuracy_score(y_test, predictions_libsvm)

print("libsvm训练时间: {:.2f}秒".format(training_time))
print("libsvm测试集准确率: {:.2%}".format(accuracy_libsvm))
相关推荐
yuanbenshidiaos1 小时前
C++----------函数的调用机制
java·c++·算法
唐叔在学习1 小时前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
ALISHENGYA1 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
chengooooooo1 小时前
代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和
算法·leetcode·职场和发展
jackiendsc2 小时前
Java的垃圾回收机制介绍、工作原理、算法及分析调优
java·开发语言·算法
游是水里的游3 小时前
【算法day20】回溯:子集与全排列问题
算法
yoyobravery3 小时前
c语言大一期末复习
c语言·开发语言·算法
Jiude3 小时前
算法题题解记录——双变量问题的 “枚举右,维护左”
python·算法·面试
被AI抢饭碗的人3 小时前
算法题(13):异或变换
算法
nuyoah♂4 小时前
DAY36|动态规划Part04|LeetCode:1049. 最后一块石头的重量 II、494. 目标和、474.一和零
算法·leetcode·动态规划