基于贝叶斯优化的支持向量机(SVM)模型构建
背景
支持向量机(SVM)是一种监督学习算法,广泛应用于分类问题中,SVM 通过寻找最优的超平面来区分不同类别的数据,为了提升 SVM 模型的表现,超参数调优至关重要,然而,传统的超参数调优方法,如网格搜索和随机搜索,往往需要大量的计算资源和时间,贝叶斯优化通过构建超参数与目标函数之间的概率模型,能更有效地寻找最优超参数,进而提高模型性能
本文介绍如何利用贝叶斯优化算法对 SVM 模型进行超参数调优,并应用于多分类问题,基于 Python 的 Scikit-learn 和 Hyperopt 库,构建了一个基于贝叶斯优化的 SVM 模型,以下内容详细介绍了实验步骤、模型实现以及结果分析
代码实现
数据集处理
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False
df = pd.read_excel("模拟数据.xlsx")
from sklearn.model_selection import train_test_split
# 分割数据集
X = df.drop(['OP'], axis = 1)
y = df['OP']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3,
stratify=df['OP']) #分离训练集和测试
df.head()
先加载了一个多分类数据集,并将数据集拆分为特征变量和目标变量,接着使用 train_test_split 方法将数据集分为训练集和测试集,确保模型能够基于不同的数据进行训练和测试,数据集的特征矩阵 X 包含所有用于分类的特征,而 y 是数据的分类标签,为了保证类别分布一致,我们使用 stratify 参数保持数据集中的类别平衡,该数据集中的每一行代表某个中药材在多个波长/频率下的红外光谱信息,第一列是对应的中药类别标签,后面的列是光谱强度值
贝叶斯优化中的超参数选择
from sklearn.svm import SVC
from hyperopt import fmin, tpe, hp
from sklearn.metrics import accuracy_score
from sklearn import svm
# 定义超参数空间
parameter_space_svc = {
'C': hp.loguniform('C', np.log(100), np.log(1000)),
'kernel': hp.choice('kernel', ['rbf', 'poly']), # 有时推荐只使用rbf核函数
'gamma': hp.loguniform('gamma', np.log(100), np.log(1000))
}
# 初始化计数器
count = 0
# 定义优化目标函数
def func(args):
global count
count += 1
print(f"\nIteration {count}: Hyperparameters - {args}")
# 创建SVM分类器,传递超参数
clf = svm.SVC(**args)
# 训练模型
clf.fit(X_train, y_train)
# 预测测试集
prediction = clf.predict(X_test)
# 计算准确率
score = accuracy_score(y_test, prediction)
print(f'Test accuracy: {score}')
# 由于fmin函数默认是最小化目标函数,所以返回负准确率作为目标
return -score
# 使用TPE算法进行超参数优化,最大评估次数为100
best = fmin(func, parameter_space_svc, algo=tpe.suggest, max_evals=100)
# 将最佳的核函数类型从索引值转换为相应的字符串
kernel_list = ['rbf', 'poly']
best['kernel'] = kernel_list[best['kernel']]
# 输出最佳超参数
print('\nBest hyperparameters:', best)
SVM 模型有两个关键的超参数,即 C 和 gamma,分别控制决策边界的平滑度和核函数的复杂度,为了提高模型的准确率,需要对这些超参数进行优化,在本文中,通过 Hyperopt 库实现基于贝叶斯优化的超参数搜索
贝叶斯优化的目标是在超参数空间内找到使模型性能最优的超参数组合,我们通过定义超参数搜索空间,并采用TPE算法进行搜索,定义的超参数空间如下:
- C:SVM 的正则化参数,取值范围为 [100,1000] 的对数均匀分布
- gamma:核函数系数,取值范围为 [100,1000] 的对数均匀分布
- kernel:选择两种常见的核函数,分别为 rbf(径向基函数)和 poly(多项式核)
接下来,定义优化目标函数,该函数首先根据给定的超参数训练 SVM 模型,并在测试集上进行预测,然后,计算模型的准确率,作为目标函数的评估指标,由于贝叶斯优化中的 fmin 函数默认是最小化目标函数,因此返回负准确率作为优化目标,经过 100 次迭代寻找最佳的超参数组合
最优模型构建
# 创建SVM分类器,并使用最佳超参数进行配置
clf = SVC(
C=best['C'], # 惩罚项参数
kernel=best['kernel'], # 核函数类型,这里选择径向基函数(RBF)
gamma=best['gamma'], # 核函数系数
decision_function_shape='ovr', # 多分类问题时使用"ovr"(一对多)策略
cache_size=5000 # 缓存大小,单位为MB
)
# 使用训练数据进行模型训练
clf.fit(X_train, y_train)
利用找到的最佳超参数,构建最终的 SVM 模型
模型评估与结果分析
分类报告
# 使用模型在测试集上进行预测
y_pred= clf.predict(X_test)
from sklearn.metrics import classification_report
# 输出模型报告, 查看评价指标
print(classification_report(y_test, y_pred))
分类报告显示了每个类别的精确率、召回率和F1值,这些指标可以帮助评估模型在不同类别上的表现
混淆矩阵
from sklearn.metrics import confusion_matrix
# 计算混淆矩阵
confusion_matrix = confusion_matrix(y_test, y_pred)
# 绘制混淆矩阵
fig, ax = plt.subplots(figsize=(10, 7),dpi=1200)
cax = ax.matshow(confusion_matrix, cmap='Blues')
fig.colorbar(cax)
# 设置英文标签
ax.set_xlabel('Predicted')
ax.set_ylabel('Actual')
ax.set_xticks(np.arange(11))
ax.set_yticks(np.arange(11))
ax.set_xticklabels([f'Class {i}' for i in range(1, 12)])
ax.set_yticklabels([f'Class {i}' for i in range(1, 12)])
for (i, j), val in np.ndenumerate(confusion_matrix):
ax.text(j, i, f'{val}', ha='center', va='center', color='black')
plt.title('Confusion Matrix Heatmap')
plt.savefig('Confusion Matrix Heatmap.pdf', format='pdf', bbox_inches='tight')
plt.show()
为了更直观地展示分类效果,最后绘制了混淆矩阵热力图,混淆矩阵展示了模型在各类别上的分类结果,包括正确分类的样本数量和错误分类的数量
总结
本文展示了如何使用贝叶斯优化对 SVM 模型进行超参数调优,并将其应用于多分类问题。相比于传统的网格搜索和随机搜索,贝叶斯优化能更高效地找到最优超参数,减少了计算资源的消耗。最终的实验结果表明,通过优化后的 SVM 模型能够在测试集上取得较高的分类准确率,并且分类效果在各类别上相对均衡。混淆矩阵和分类报告清晰展示了模型的性能,进一步验证了优化后模型的有效性,贝叶斯优化为机器学习模型的调优提供了一种强有力的工具,尤其在大规模超参数搜索问题中,能够大幅提升效率和模型表现