支持向量机(SVM)是一种强大的机器学习算法,主要用于分类和回归分析。它的目标是在特征空间中找到一个最优的超平面,以最好地分离不同类别的数据点
1. SVM基本概念以及特点
- 超平面: SVM的核心思想是找到一个能够最好地将不同类别的数据点分开的超平面。对于二分类问题,这是一个二维平面;对于多分类问题,可以使用多个超平面
- 支持向量: 在SVM中,支持向量是离超平面最近的数据点,它们对模型的构建起着关键作用。这些支持向量决定了超平面的位置
- 核函数: SVM可以通过核函数将数据从原始特征空间映射到更高维的空间,从而使得非线性问题也能够被解决。常用的核函数包括线性核、多项式核和径向基函数(RBF)核
- 惩罚项(C): SVM引入了一个惩罚项,用于调整分类错误的代价。这个参数(通常记为C)的调整可以影响模型的复杂度和泛化能力
- 多分类问题: SVM原本是为二分类问题设计的,但通过"一对多"(one-vs-all)或"一对一"(one-vs-one)等策略,它也可以用于处理多分类问题
SVM在实际应用中被广泛使用,特别是在图像识别、文本分类、生物信息学等领域。其优势包括对高维空间的适应性、鲁棒性以及在处理小样本数据上的性能表现。然而,对于大规模数据集,训练时间可能较长
2. 代码实例
2.1 数据展示
import numpy as np
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = 'SimHei' # 设置中文显示
plt.rcParams['axes.unicode_minus'] = False
data = pd.read_excel('附件2.xlsx', index_col = 0)
data
该数据集为全国大学生数学建模竞赛2021年E题数据集,其中OP列为红外光谱类别数据,缺失值为待分类数据,其余列皆为光谱的波数
2.2 特征提取
X = data.iloc[:,1::]
cf = pd.DataFrame(X.iloc[:,1:].values-X.iloc[:,:-1].values, index = data.index) # 进行一阶差分
cf.head()
一阶差分可以帮助识别数据中的变化趋势和模式,有助于揭示数据中的结构信息。在这种情况下,提取的特征用于分析红外光谱数据中的变化或趋势,以更好地理解数据的特性
2.3 数据可视化
def func_1(x):
plt.plot(x.index, x.values)
def func_2(data):
fontsize = 5
plt.figure(figsize=(8, 6), dpi = 300)
plt.xticks(range(551, 3999, 500), rotation = 45, fontsize = 5)
plt.yticks(fontsize = fontsize)
plt.xlabel('波数(cm^-1)')
plt.ylabel('吸光度(AU)')
plt.grid(True) # 网格线设置
data.agg(lambda x: func_1(x), axis = 1)
plt.show()
func_2(data.iloc[:,1:]) #原始数据光谱曲线图
func\_2(cf) #附件二一阶平滑后数据曲线图
2.4 数据集划分
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from hyperopt import fmin, tpe, hp, rand
from sklearn.metrics import accuracy_score
from sklearn import svm
from sklearn import datasets
data.fillna(0, inplace = True) #用0填充op空值 未知产地药材
cf['OP'] = data['OP']
prophet = cf[cf['OP'] == 0].iloc[:,:-1] # 待预测数据集
Xtrain,Xtest,Ytrain,Ytest = train_test_split(cf[cf['OP'] != 0].iloc[:,:-1],
cf[cf['OP'] != 0]['OP'],
test_size = 0.3,
stratify=cf[cf['OP'] != 0]['OP']) #分离训练集和测试集
2.5 超参数迭代选择
# 定义超参数空间
parameter_space_svc = {
'C': hp.loguniform('C', np.log(100), np.log(1000)), # 惩罚项
'kernel': hp.choice('kernel', ['rbf', 'poly']), # 核函数类型(选择rbf或poly)
'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(Xtrain, Ytrain)
# 预测测试集
prediction = clf.predict(Xtest)
# 计算准确率
score = accuracy_score(Ytest, 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)
通过使用TPE算法对支持向量机(SVM)分类器的超参数进行优化,提高了SVM模型在分类任务中的性能
2.6 模型训练
# 最佳超参数
best_params_ = {'C': 129.12544295377108, 'gamma': 100.55914557818326}
# 创建SVM分类器,并使用最佳超参数进行配置
clf = SVC(
C=best_params_['C'], # 惩罚项参数
kernel='rbf', # 核函数类型,这里选择径向基函数(RBF)
gamma=best_params_['gamma'], # 核函数系数
decision_function_shape='ovr', # 多分类问题时使用"ovr"(一对多)策略
cache_size=5000 # 缓存大小,单位为MB
)
# 使用训练数据进行模型训练
clf.fit(Xtrain, Ytrain)
2.7 模型评价指标输出及预测未知数据类别
from sklearn.metrics import classification_report
pred = clf.predict(Xtest) # 预测测试集
print(classification_report(Ytest, pred)) # 输出模型完整评价指标
在这里模型成功达到了92%的分类准确率。这表明模型在识别不同类别上表现出色,对数据中的变化趋势和模式敏感,当然为了更改的模型精确度可以增加超参数迭代次数,以便选得在迭代次数下的最优超参数
clf.predict(prophet) # 预测未知数据
3. 往期推荐
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~
