保姆级教程:用Python+LIBSVM复现《机器学习》西瓜书习题6.2,搞定数据格式转换与可视化全流程
2026/6/2 8:38:46 网站建设 项目流程

从理论到实践:Python+LIBSVM实现西瓜数据集3.0α的核函数对比实验

在机器学习的学习过程中,理解支持向量机(SVM)不同核函数的特性是一个关键环节。周志华教授的《机器学习》一书中,习题6.2提供了一个绝佳的实践机会——在西瓜数据集3.0α上比较线性核与高斯核的表现差异。本文将带你完整走通这个实验流程,从数据准备到模型训练,再到结果可视化,让你不仅完成习题要求,更能深入理解SVM核函数选择的实际意义。

1. 实验环境搭建与数据准备

1.1 安装必要的Python库

开始实验前,我们需要配置好Python环境并安装必要的库。推荐使用Anaconda创建独立的虚拟环境:

conda create -n svm_experiment python=3.8 conda activate svm_experiment pip install libsvm openpyxl numpy matplotlib

LIBSVM是台湾大学林智仁教授团队开发的经典SVM实现,其Python接口简单易用。openpyxl用于处理Excel格式的原始数据,numpy和matplotlib则是数据处理和可视化的标配工具。

1.2 理解西瓜数据集3.0α的结构

原始数据通常以Excel表格形式存储,我们需要先理解其结构:

编号密度含糖率好瓜
10.6970.46
20.7740.376
............

数据集包含17个样本,每个样本有2个特征(密度和含糖率)和1个二分类标签(好瓜/坏瓜)。我们的首要任务是将这种表格数据转换为LIBSVM要求的格式。

2. 数据格式转换实战

2.1 LIBSVM数据格式详解

LIBSVM要求的数据格式为:

[类别标签] [特征编号1]:[特征值1] [特征编号2]:[特征值2] ...

例如:

1 1:0.697 2:0.46 0 1:0.666 2:0.091

2.2 Python实现格式转换

下面是将Excel数据转换为LIBSVM格式的完整代码:

import openpyxl def excel_to_libsvm(input_path, output_path, sheet_name='Sheet1'): workbook = openpyxl.load_workbook(input_path) sheet = workbook[sheet_name] with open(output_path, 'w') as f: for row in sheet.iter_rows(min_row=2, values_only=True): # 假设第4列是标签(0/1),第2、3列是特征 label = 1 if row[3] == '是' else 0 features = f"1:{row[1]} 2:{row[2]}" f.write(f"{label} {features}\n") # 使用示例 excel_to_libsvm('xigua3.0.xlsx', 'xigua.libsvm')

注意:实际使用时需要根据Excel文件的具体结构调整列索引。建议先用print查看row的内容确认数据结构。

3. SVM模型训练与核函数比较

3.1 加载数据与基础训练

LIBSVM的Python接口提供了简洁的API:

from libsvm.svmutil import * # 加载数据 y, x = svm_read_problem('xigua.libsvm') # 线性核训练 linear_model = svm_train(y, x, '-t 0 -c 100') p_label, p_acc, p_val = svm_predict(y, x, linear_model)

-t 0指定使用线性核,-c 100设置惩罚参数。训练完成后,我们可以直接在训练集上测试模型表现。

3.2 高斯核(RBF核)训练

# 高斯核训练 rbf_model = svm_train(y, x, '-t 2 -g 0.1 -c 100') p_label, p_acc, p_val = svm_predict(y, x, rbf_model)

-t 2选择高斯核,-g参数控制核函数的宽度。高斯核的关键优势是能够处理线性不可分的数据。

3.3 参数调优技巧

SVM性能对参数敏感,特别是高斯核中的C和gamma:

  • C(惩罚参数):控制分类错误的容忍度

    • 值越大,对错误分类的惩罚越重,可能导致过拟合
    • 值太小可能导致欠拟合
  • gamma(核系数):控制单个样本的影响范围

    • 值越大,决策边界越复杂,可能过拟合
    • 值太小会使模型过于平滑

推荐使用网格搜索寻找最优参数组合:

best_accuracy = 0 best_params = {} for C in [0.1, 1, 10, 100, 1000]: for gamma in [0.01, 0.1, 1, 10]: params = f'-t 2 -c {C} -g {gamma} -v 5' # 5折交叉验证 acc = svm_train(y, x, params) if acc > best_accuracy: best_accuracy = acc best_params = {'C': C, 'gamma': gamma}

4. 结果可视化与分析

4.1 决策边界可视化

理解不同核函数的决策边界差异最直观的方式就是可视化:

import numpy as np import matplotlib.pyplot as plt def plot_decision_boundary(model, X, y, title): # 创建网格点 x_min, x_max = X[:, 0].min() - 0.1, X[:, 0].max() + 0.1 y_min, y_max = X[:, 1].min() - 0.1, X[:, 1].max() + 0.1 xx, yy = np.meshgrid(np.linspace(x_min, x_max, 100), np.linspace(y_min, y_max, 100)) # 预测网格点类别 grid = np.c_[xx.ravel(), yy.ravel()] grid = [{1:row[0], 2:row[1]} for row in grid] p_label, _, _ = svm_predict([0]*len(grid), grid, model) Z = np.array(p_label).reshape(xx.shape) # 绘制 plt.contourf(xx, yy, Z, alpha=0.3) plt.scatter(X[:, 0], X[:, 1], c=y, edgecolors='k') plt.title(title) plt.xlabel('密度') plt.ylabel('含糖率') plt.show() # 准备数据 X = np.array([[xi[1], xi[2]] for xi in x]) y = np.array(y) # 可视化比较 plot_decision_boundary(linear_model, X, y, '线性核决策边界') plot_decision_boundary(rbf_model, X, y, '高斯核决策边界')

4.2 结果分析与讨论

通过可视化对比,我们可以观察到:

线性核

  • 决策边界是一条直线
  • 在西瓜数据集上准确率约82.35%
  • 无法完美分类所有样本,因为数据在原始特征空间线性不可分

高斯核

  • 决策边界是非线性的复杂曲线
  • 通过调整参数可以达到100%训练准确率
  • 能够捕捉特征间的复杂关系,但可能过拟合

下表总结了两种核函数的关键差异:

特性线性核高斯核
决策边界线性非线性
参数数量仅需调C需调C和gamma
计算复杂度较高
适用场景线性可分或高维数据非线性可分的小规模数据
过拟合风险较高(尤其gamma较大时)

5. 工程实践中的扩展思考

5.1 数据标准化的重要性

SVM对特征的尺度敏感,特别是使用高斯核时。建议在训练前对特征进行标准化:

from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 将标准化后的数据转换为LIBSVM格式 with open('xigua_scaled.libsvm', 'w') as f: for label, features in zip(y, X_scaled): line = f"{label} 1:{features[0]} 2:{features[1]}\n" f.write(line)

标准化通常能提高模型性能,并使参数搜索范围更易确定。

5.2 支持向量的分析

理解支持向量有助于我们把握模型的关键:

# 获取支持向量 sv_indices = linear_model.get_sv_indices() support_vectors = X[sv_indices - 1] # LIBSVM索引从1开始 print(f"线性核支持向量数量: {len(support_vectors)}") print(f"高斯核支持向量数量: {len(rbf_model.get_SV())}") # 可视化支持向量 plt.scatter(X[:, 0], X[:, 1], c=y, alpha=0.3) plt.scatter(support_vectors[:, 0], support_vectors[:, 1], facecolors='none', edgecolors='r', s=100, label='支持向量') plt.legend() plt.show()

支持向量数量反映了模型的复杂度。通常,高斯核会产生更多支持向量,因为需要更多样本来定义复杂的决策边界。

5.3 模型持久化与部署

训练好的模型可以保存供后续使用:

# 保存模型 svm_save_model('linear_model.model', linear_model) svm_save_model('rbf_model.model', rbf_model) # 加载模型 loaded_model = svm_load_model('linear_model.model')

在实际应用中,我们可以将模型集成到Web服务或其他应用中,实现实时分类功能。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询