其中,第一项是正则化项,控制模型复杂度;第二项是惩罚项,控制对误差的惩罚;C是惩罚参数,用于权衡误差和复杂度。 和 是松弛变量,用于表示超过 ε 的误差。
约束条件为:
将上述约束条件通过拉格朗日乘数法结合到目标函数中,再将问题转化为对偶形式求解,构造最终预测函数为:
其中,K是核函数(Kernel Function),用于处理非线性问题。和是拉格朗日乘子。
废话说得有点多,可考虑到核函数在机器学习中是一个比较重要的概念,这里还得再啰嗦几句。核函数是一种将数据从原始空间映射到高维特征空间的技术。通过核函数,我们可以在原始的输入空间中进行计算,但得到的结果相当于是在高维空间中计算的。举个简单的例子,在二维空间中,下图是一张无法线性分割的环形数据。
机器学习库scikit-learn中提供了现成的SVR实现,我们可以使用内置的核函数,并通过交叉验证在不同的核函数与参数组合中找到最适合数据集训练的最佳模型。我们还是以发动机剩余寿命预测案例为例,具体方法如下:
import random
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.svm import SVR
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from tqdm import tqdm
from scipy.stats import uniform
# 定义超参数分布
param_distributions = {
'C': uniform(loc=0.1, scale=10),
'epsilon': uniform(loc=0.01, scale=0.5),
'gamma': ['scale', 'auto'] + list(uniform(loc=0.001, scale=0.1).rvs(size=10)),
'kernel': ['linear', 'poly', 'rbf', 'sigmoid']
}
# 初始化 SVR 模型
model = SVR()
# 手动进行超参数随机搜索
param_list = []
for _ in range(50): # 随机采样 50 组参数组合
param_list.append({
'C': param_distributions['C'].rvs(),
'epsilon': param_distributions['epsilon'].rvs(),
'gamma': random.choice(param_distributions['gamma']),
'kernel': random.choice(param_distributions['kernel'])
})
# 设置交叉验证
cv_splitter = KFold(n_splits=3, shuffle=True, random_state=42)
# 执行随机搜索并显示进度条
results = []
with tqdm(total=len(param_list), desc="Random Search Progress") as pbar:
for params in param_list:
model.set_params(**params) # 更新模型参数
scores = []
for train_idx, val_idx in cv_splitter.split(flat_seq_array, label_array.ravel()):
# 在训练集上训练模型
model.fit(flat_seq_array[train_idx], label_array.ravel()[train_idx])
# 在验证集上预测并计算误差
preds = model.predict(flat_seq_array[val_idx])
score = mean_squared_error(label_array.ravel()[val_idx], preds)
scores.append(score)
avg_score = np.mean(scores)
results.append({'params': params, 'mean_test_score': avg_score})
pbar.update(1)
SVR
实现并不支持 GPU,所以这个训练过程可能会很慢!不同的核函数适用于不同的数据类型核问题,如果你知道数据的大致分布和特征,大可不必像我上面的代码将所有的核函数都罗列出来,这样的计算量太大了!光是搜索最优参数组合就花了47小时'C': np.float64(2.7986),
'epsilon': np.float64(0.4045),
'gamma': np.float64(0.0982),
'kernel': 'poly'
minhangjiwuluntan