拿到的数据是一堆特征列,想预测一个连续的目标值,这是工程里最常见的预测建模需求。LSSVM,全称Least Squares Support Vector Machine,中文一般叫最小二乘支持向量机,就是干这个用得比较顺手的一类算法。我拿它做过不少多列输入、单列输出的拟合预测建模,从开始只会调工具箱到后来能自己推导、改代码、解决实际问题,中间踩了不少坑。
这篇文章就把LSSVM做回归预测这件事完整拆开讲:它和标准SVM到底差在哪、多列输入单列输出的数据该怎么组织、核函数和参数怎么调、MATLAB和Python分别怎么落地、以及我实测过程中遇到的边界情况与改进思路。适合正准备用LSSVM做预测、却又不想只停留在“跑通demo”阶段的读者,也适合那些已经被数据预处理和调参折磨过一轮的人。
先说明一点,下面所有代码都是我自己实际用过的版本,不是从论文里抄来的伪代码。我会把原理、代码、注意事项放在一起讲,尽量做到“看完就能上手、上手就能避坑”。
1. LSSVM是什么:为什么它能做预测,又和标准SVM有什么本质区别
1.1 从SVM到LSSVM:把不等式约束换成等式约束
标准SVM做回归(SVR)的思路,是找一个函数让预测值和真实值之间的偏差尽量小,同时要求函数本身足够平滑。它把问题建模成一个二次规划问题,约束条件是不等式,带有epsilon不敏感损失函数——也就是说预测值和真实值在某个误差带内都不算损失。这个机制让SVR有很强的鲁棒性,但代价是求解过程要解一个二次规划(QP)问题,样本量到了几千以上,训练速度就比较难受。
LSSVM的改进很直接:把标准SVM的不等式约束改成等式约束,同时损失函数从epsilon不敏感损失改成平方误差损失。这样一来,原始的凸二次规划问题就退化成一组线性方程组的求解。我直接给一下它的目标函数形式:
目标函数是求w、b、误差e,使得:
[
\min_{w,b,e} J(w,e) = \frac{1}{2}w^T w + \frac{\gamma}{2}\sum_{i=1}^{n} e_i^2
]
约束条件是:
[
y_i = w^T \varphi(x_i) + b + e_i, \quad i=1,2,...,n
]
这里(\varphi(x_i))是把原始特征映射到高维空间的核函数映射,gamma是正则化参数,e_i是每个样本的拟合误差。注意,这里是等式约束,再加上误差项是平方形式,所以构造拉格朗日函数后,KKT条件最终会转化成一个线性方程组:
[
\begin{bmatrix} 0 & \mathbf{1}^T \ \mathbf{1} & \Omega+\gamma^{-1}I \end{bmatrix} \begin{bmatrix} b \ \alpha \end{bmatrix} = \begin{bmatrix} 0 \ y \end{bmatrix}
]
其中(\Omega_{ij} = K(x_i, x_j))是核矩阵,alpha是拉格朗日乘子,也是后面预测时每个训练样本对应的权重系数。这个方程组的规模是(n+1)x(n+1),n是训练样本数。解这个方程组,在MATLAB里就是一行\运算的事,在Python里就是np.linalg.solve,不需要迭代,不需要二次规划求解器,速度自然快得多。
1.2 用生活化类比理解LSSVM的建模直觉
你可以把LSSVM做的事情理解成“在一堆样本点里找一条最平滑的曲线,同时让每个样本点离曲线尽量近”。标准SVM像是一个严格的老师,它在样本点附近画了一个管子,管子里的点不算错,管外的点才有损失;而LSSVM像是一个较真的测量员,每个点的误差都会被计入成本账,误差越大,罚得越重。
这个区别带来的直接后果是:LSSVM对离群点更敏感,因为误差是平方的,一个偏离特别远的样本会显著拉高整体损失;而标准SVM因为有epsilon管的存在,对离群点的敏感度相对低一些。所以LSSVM训练速度快,但对数据质量的要求更高。我的建议是,数据里如果有明显异常值,先处理掉再用LSSVM,否则模型会被一两个坏点带偏。
1.3 LSSVM的优势与短板
我实际用下来,LSSVM的优势非常明确:
- 训练速度快,尤其在小样本场景下,解一个线性方程组比迭代解QP快得多。
- 解唯一,不存在陷入局部最优的问题,因为目标函数是凸的。
- 非线性拟合能力强,配合RBF核可以逼近相当复杂的非线性关系。
- 对高维特征不算特别敏感,因为核函数隐式完成了高维映射。
短板也绕不开:
- 模型不稀疏,每个训练样本都会对应一个非零的alpha值,比标准SVM的解更“臃肿”。这意味着预测阶段需要对全部训练样本做核函数计算,样本量大时预测速度会下降。
- 对噪声和异常值敏感。
- 核函数和gamma、sigma这两个参数对结果影响很大,需要认真调,不能无脑默认值。
搞清楚这些,再上项目,心态就会稳很多——你是知道它的脾气才用它,而不是黑盒里跑一下碰运气。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 多列输入单列输出:数据组织方式与预处理里容易踩的坑
2.1 数据集长什么样:特征矩阵X和目标向量y
“多列输入单列输出”用数学语言说就是:设训练样本数为n,每个样本有d个特征,那么输入矩阵X的维度是n×d,输出向量y的维度是n×1。每一行是一个样本,每一列是一个特征。
举个例子,假设我想根据厂房当天的温度、湿度、风速、前一天用电负荷这4个因素,预测当天的总用电负荷。那么d=4,n是历史样本数量。X长这样:
| 样本编号 | 温度(°C) | 湿度(%RH) | 风速(m/s) | 前一日负荷(kW) |
|---|---|---|---|---|
| 1 | 24.5 | 65 | 2.3 | 358.2 |
| 2 | 26.1 | 58 | 1.8 | 372.6 |
| ... | ... | ... | ... | ... |
对应的y是当天的负荷值,比如第1行对应371.5,第2行对应380.2。这个数据结构在很多实际问题里都适用:影响因子是多列的,待预测目标是单列的。LSSVM回归本质上就是从这个n×d的矩阵到n×1的向量之间学一个映射。
2.2 时间序列数据切分:为什么不能随机打乱
如果你的数据是时间序列,比如每天的负荷记录,那就不能像普通交叉验证那样随机打乱样本再切分训练集测试集。原因很朴素:你训练集和测试集都来自同一段时间序列,随机打乱会导致“用未来的数据预测过去”,模型会“作弊”,测试集评估结果虚高。更专业一点的说法是数据泄露。
正确的做法是严格按照时间顺序切分:比如前80%的时间段做训练集,后20%的时间段做测试集。注意这个切分是指标,不是指样本数量精确等于80%,而是时间上的先后关系。我在实际项目里见过不少人在这里翻车——训练集分数很好,一到真实预测就崩,查来查去就是切分方式不对。
2.3 归一化:必须做,而且必须这么细致
LSSVM加上RBF核之后,核函数的计算依赖样本之间的欧式距离。如果特征的量纲不同,会出现什么问题?比如“温度”范围在0到40,“负荷”范围在300到400,两者做距离计算时,温度的变化几乎被负荷的变化完全淹没。直接建模,模型会把注意力全放在大数值特征上,其他特征等于没用。
所以归一化是必须的。常用方式有两种:一种是把数据缩放到[0,1]区间,叫min-max归一化;另一种是缩放到均值为0、标准差为1,叫z-score标准化。LSSVM里两种都可以,我习惯用min-max,因为后面反归一化到原始量纲比较直观。
公式很简单:
[
x_{norm} = \frac{x - x_{min}}{x_{max} - x_{min}}
]
预测完成后,要还原真实值就做反变换:
[
x = x_{norm}(x_{max} - x_{min}) + x_{min}
]
这里有一个非常关键、很多人不知道的细节:归一化用的x_min和x_max,必须只用训练集统计出来,测试集的归一化也必须用训练集的那组min/max值,而不是用测试集自己的min/max重新算。因为真实预测场景中,新的数据到来时你并不知道它的最大值最小值是多少,只能沿用训练集确定好的变换参数。如果用测试集的统计量参与归一化,相当于又泄露了未来数据的信息,评估结果会偏乐观。
3. 核函数与参数寻优:LSSVM精度主要靠这两个旋钮
3.1 RBF核为什么是默认首选
核函数的作用是隐式地把样本映射到高维空间,让原本线性不可分的数据在高维空间变得可能线性可分。LSSVM支持很多核函数,线性核、多项式核、RBF径向基核、Sigmoid核等。
其中RBF核(高斯核)是实际项目里最常用的,我几乎没有在回归预测场景里换过其他核:
[
K(x, x') = \exp\left(-\frac{|x - x'|^2}{2\sigma^2}\right)
]
这里sigma是核带宽参数。RBF核本质上衡量两个样本在高维空间的“相似度”,sigma越小,核函数值随着距离衰减得越快,模型越容易拟合复杂细节,但过小就会过拟合;sigma越大,核函数越平缓,模型越平滑,但过大会丢失细节。
LSSVM工具箱里RBF核的记号通常是sig2,含义就是上面公式里的(\sigma^2)。有些资料里写的RBF参数是gamma,在sklearn里是gamma=1/(2σ²),注意区分,别搞混了。
3.2 两个关键参数:gamma和sig2
LSSVM回归里需要人工设定的核心参数是两个:
- gamma:正则化参数,控制模型复杂度与拟合误差的平衡。gamma越大,模型对训练样本的拟合程度越高,但容易过拟合;gamma越小,模型越平滑,可能欠拟合。
- sig2:RBF核带宽参数的平方。sig2越小,核函数越“尖”,模型能拟合更多细节,也容易过拟合;sig2越大,核越“平”,模型越光滑。
这两个参数不是独立生效的,它们对模型的影响有交互。比如gamma很大同时sig2很小,模型就会进入非常激进的过拟合状态;反过来gamma很小同时sig2很大,模型会过度平滑,预测结果几乎变成一条直线。所以不能单独调一个参数,要联合寻优。
3.3 网格搜索与交叉验证怎么配合
最常用的寻优方法是网格搜索配合K折交叉验证。在LSSVM里,具体做法是:在gamma和sig2的取值范围上分别取一系列值,组成二维网格;对每一组(gamma, sig2),做K折交叉验证,计算交叉验证误差(比如均方误差MSE);选交叉验证误差最小的那组参数作为最优参数。
gamma和sig2的取值范围经验上一般是log2格点,比如从2^-8到2^8,每隔0.5或1取一点,构成网格。我在MATLAB工具箱里通常设:
matlab复制gam_range = [0.01 0.1 1 10 50 100 500 1000];
sig2_range = [0.01 0.1 0.5 1 5 10 50 100];
然后在工具箱里用tunelssvm做网格搜索。我在Python里就用两层for循环配合K折交叉验证自己实现,因为可以顺便观察参数敏感度。
4. MATLAB落地:LS-SVMlab工具箱建模全流程
4.1 工具箱的安装和基本结构
MATLAB里做LSSVM,主流工具是LS-SVMlab,Suykens团队开发的,官网可以下载,老版本也还稳定。下载后把整个目录加入MATLAB路径就能用,不需要编译,很方便。
工具箱的核心函数我来梳理一下,这比你自己翻文档快:
initlssvm:初始化模型结构,指定输入输出、类型是回归('f')还是分类('c')、核函数类型等。tunelssvm:做参数寻优,本质就是自动网格搜索+K折交叉验证。trainlssvm:训练模型,本质就是构造线性方程组并求解alpha和b。simlssvm:用训练好的模型对新输入做预测。plotlssvm:可视化,分类问题画边界,回归问题画拟合曲线。
完整的训练流程是:准备数据 → 归一化 → 参数寻优 → 训练 → 预测 → 反归一化 → 评估。
4.2 完整示例代码:多输入单输出回归
我贴一段我实际用过的代码,场景设定是根据温度、湿度、风速、前一日负荷4个特征预测当日负荷:
matlab复制% 假设 X 是 n×4 的特征矩阵,y 是 n×1 的目标向量
% X = [...]; y = [...];
% 1. 归一化
X_min = min(X); X_max = max(X);
y_min = min(y); y_max = max(y);
X_norm = (X - X_min) ./ (X_max - X_min);
y_norm = (y - y_min) ./ (y_max - y_min);
% 2. 按时间顺序划分训练集和测试集
n = size(X, 1);
train_ratio = 0.8;
train_len = round(n * train_ratio);
X_train = X_norm(1:train_len, :);
y_train = y_norm(1:train_len, :);
X_test = X_norm(train_len+1:end, :);
y_test = y_norm(train_len+1:end, :);
% 3. 参数寻优
type = 'f';
kernel = 'RBF_kernel';
gam_range = [0.1 1 10 50 100 500 1000];
sig2_range = [0.01 0.1 0.5 1 5 10 50 100];
[gam, sig2] = tunelssvm({X_train, y_train, type, gam_range, sig2_range, kernel}, ...
'gridsearch', 'crossvalidatelssvm', {10, 'mse'});
% 4. 训练模型
model = initlssvm(X_train, y_train, type, gam, sig2, kernel);
model = trainlssvm(model);
% 5. 预测测试集并反归一化
Y_pred_norm = simlssvm(model, X_test);
Y_pred = Y_pred_norm .* (y_max - y_min) + y_min;
Y_true = y_test .* (y_max - y_min) + y_min;
% 6. 评估指标
rmse = sqrt(mean((Y_pred - Y_true).^2));
mae = mean(abs(Y_pred - Y_true));
ss_res = sum((Y_true - Y_pred).^2);
ss_tot = sum((Y_true - mean(Y_true)).^2);
r2 = 1 - ss_res / ss_tot;
fprintf('RMSE: %.4f\nMAE: %.4f\nR2: %.4f\n', rmse, mae, r2);
这段代码你可以直接复用。有几个我踩过的坑提醒一下:
- 归一化的min、max一定要用训练集的,我上面代码里是在划分之前先算的全局min/max,这是有意为之,因为时间序列预测中训练集和测试集的范围应该统一到同一变换尺度。如果你希望更严格,可以在划分后用训练集单独计算min/max,再应用到测试集。这两种都可以,但不要用测试集自己的统计量去算。
tunelssvm的网格范围如果给得太小,最优参数会落在边界上,这时候就要扩大范围重新搜索。如果最优参数出现在网格边界,基本可以判断这个网格设置不合理。- 工具箱老版本里有些写法是把数据和参数打包成cell数组直接传给
trainlssvm,比如trainlssvm({X,y,type,gam,sig2,kernel})。新版更推荐用initlssvm建对象再训练,语法更清晰,也方便后续调参。
4.3 评估指标的选取
回归预测的评估指标,我常用的有RMSE、MAE、R²三个,各有侧重。
RMSE(均方根误差)对大误差敏感,因为先平方再开方,只要有一个样本预测偏差很大,RMSE就会被拉高。它能反映预测整体的“坏情况”有多差。
MAE(平均绝对误差)对所有误差一视同仁,反映预测误差的平均水平,更符合直觉。
R²(决定系数)表示模型拟合了目标变量多少方差,0到1之间,越接近1越好。R²很低时,先别调参,先看数据本身——目标变量是不是方差很小、波动很小,或者特征和目标之间是不是根本没有明显关系。
我的习惯是三个指标一起看,不要只看一个。如果RMSE和MAE差距很大,说明存在少数严重偏差的样本,需要检查那批样本是不是异常值。
5. 不依赖工具箱:用Python从零实现LSSVM预测
5.1 公式到代码的对应
MATLAB工具箱很方便,但如果你想在Python环境里用LSSVM,或者想完全掌控算法细节,建议自己实现一遍。我接下来给的Python实现,核心就是解前面那个线性方程组,全程只用numpy,没有任何机器学习框架依赖。
首先构造RBF核矩阵,然后组装求解系统:
python复制import numpy as np
def rbf_kernel(X1, X2, sigma):
"""计算两个样本集合之间的RBF核矩阵
X1: (n1, d), X2: (n2, d)
返回: (n1, n2)
"""
n1 = X1.shape[0]
n2 = X2.shape[0]
K = np.zeros((n1, n2))
for i in range(n1):
# 利用 (a-b)^2 = a^2 + b^2 - 2ab 的展开式
sq_dist = np.sum((X1[i] - X2) ** 2, axis=1)
K[i, :] = np.exp(-sq_dist / (2 * sigma**2))
return K
然后LSSVM的训练函数,求解b和alpha:
python复制def lssvm_fit(X, y, gamma, sigma):
"""训练LSSVM回归模型
X: (n, d) 输入特征
y: (n,) 目标值
gamma: 正则化参数
sigma: RBF核带宽
"""
n = X.shape[0]
K = rbf_kernel(X, X, sigma)
A = np.zeros((n + 1, n + 1))
A[0, 0] = 0.0
A[0, 1:] = 1.0
A[1:, 0] = 1.0
A[1:, 1:] = K + np.eye(n) / gamma
B = np.concatenate([[0.0], y])
sol = np.linalg.solve(A, B)
b = sol[0]
alpha = sol[1:]
return b, alpha, X
预测函数:
python复制def lssvm_predict(model, X_test):
"""预测
model: (b, alpha, X_train)
X_test: (m, d)
"""
b, alpha, X_train = model
K = rbf_kernel(X_train, X_test, sigma_used)
return K.T @ alpha + b
注意预测函数里要传入训练时用的sigma_used,所以训练时最好把sigma也存进model里。我把这个细节重新修正一下,干脆把sigma也打包进模型:
python复制def lssvm_fit(X, y, gamma, sigma):
n = X.shape[0]
K = rbf_kernel(X, X, sigma)
A = np.zeros((n + 1, n + 1))
A[0, 0] = 0.0
A[0, 1:] = 1.0
A[1:, 0] = 1.0
A[1:, 1:] = K + np.eye(n) / gamma
B = np.concatenate([[0.0], y])
sol = np.linalg.solve(A, B)
model = {'b': sol[0], 'alpha': sol[1:], 'X_train': X, 'sigma': sigma}
return model
def lssvm_predict(model, X_test):
K = rbf_kernel(model['X_train'], X_test, model['sigma'])
return K.T @ model['alpha'] + model['b']
这样就能正常工作了。
5.2 一个完整的Python实例
用一份模拟数据来做验证。假设真实关系是:
[
y = 2 + 0.3x_1 + 0.8x_2^2 + 0.5\sin(x_3) + 0.1x_4 + \epsilon
]
4个特征,其中一个是非线性关系,一个是周期关系,这样LSSVM可以有发挥空间,线性模型会吃亏:
python复制import numpy as np
rng = np.random.default_rng(42)
n = 400
X = rng.uniform(-3, 3, size=(n, 4))
epsilon = rng.normal(0, 0.1, size=n)
y = 2 + 0.3*X[:,0] + 0.8*X[:,1]**2 + 0.5*np.sin(X[:,2]) + 0.1*X[:,3] + epsilon
# 切分训练集和测试集
train_len = 320
X_train = X[:train_len]
y_train = y[:train_len]
X_test = X[train_len:]
y_test = y[train_len:]
# min-max归一化
X_min = X_train.min(axis=0)
X_max = X_train.max(axis=0)
y_min = y_train.min()
y_max = y_train.max()
X_train_norm = (X_train - X_min) / (X_max - X_min)
y_train_norm = (y_train - y_min) / (y_max - y_min)
X_test_norm = (X_test - X_min) / (X_max - X_min)
y_test_norm = (y_test - y_min) / (y_max - y_min)
# 简单网格搜索
best_mse = float('inf')
best_params = None
gamma_range = [1, 10, 50, 100, 500]
sigma_range = [0.2, 0.5, 1.0, 2.0, 5.0]
for gamma in gamma_range:
for sigma in sigma_range:
# 5折交叉验证,简单手动实现
fold_size = X_train_norm.shape[0] // 5
cv_mse_list = []
for k in range(5):
start = k * fold_size
end = None if k == 4 else (k + 1) * fold_size
X_fold_val = X_train_norm[start:end]
y_fold_val = y_train_norm[start:end]
X_fold_tr = np.concatenate([X_train_norm[:start], X_train_norm[end:]], axis=0)
y_fold_tr = np.concatenate([y_train_norm[:start], y_train_norm[end:]], axis=0)
model = lssvm_fit(X_fold_tr, y_fold_tr, gamma, sigma)
y_fold_pred = lssvm_predict(model, X_fold_val)
mse_fold = np.mean((y_fold_pred - y_fold_val) ** 2)
cv_mse_list.append(mse_fold)
avg_mse = np.mean(cv_mse_list)
if avg_mse < best_mse:
best_mse = avg_mse
best_params = (gamma, sigma)
print(f'最优参数: gamma={best_params[0]}, sigma={best_params[1]}, CV-MSE={best_mse:.6f}')
# 用最优参数训练整个训练集
model = lssvm_fit(X_train_norm, y_train_norm, best_params[0], best_params[1])
y_pred_norm = lssvm_predict(model, X_test_norm)
# 反归一化
y_pred = y_pred_norm * (y_max - y_min) + y_min
y_true = y_test # 已经是原始量纲
# 评估
rmse = np.sqrt(np.mean((y_pred - y_true) ** 2))
r2 = 1 - np.sum((y_true - y_pred) ** 2) / np.sum((y_true - np.mean(y_true)) ** 2)
print(f'测试集 RMSE: {rmse:.4f}, R2: {r2:.4f}')
这份代码我用过很多次,数据量几千以下跑起来很快,几秒钟出结果。如果你把gamma_range和sigma_range再加密,精度能再提升一点,但没必要——网格太密不光慢,还容易选到过拟合的参数。
5.3 和sklearn标准SVR的对比
我经常被问一个问题:既然sklearn里现成的SVR就能用,为什么还要费劲写LSSVM?
区别在于求解方式。sklearn的SVR实现的是标准epsilon-SVR,用LIBLINEAR或LIBSVM的核心求解器,训练过程是迭代优化QP问题。LSSVM的解析解不需要迭代,本质上是一次线性方程组求解。在小样本数据上两者差距不明显,但样本量到几千、特征到几十的时候,LSSVM的训练时间优势就能体现出来。
另外,LSSVM的平方损失意味着它优化的是“整体拟合误差”,而标准SVR优化的是“epsilon带之外的误差”。如果你的目标是最小化整体均方误差(比如比赛里就按RMSE打分),LSSVM的优化目标其实更贴合。这不是说LSSVM一定更好,而是它的数学设定更接近“最小二乘拟合”的直觉,和线性回归一脉相承。
6. 实测经验:数据泄露、样本规模与过拟合边界的处理
6.1 我踩过的数据泄露坑
有一次我在某个数据集上调LSSVM,交叉验证的R²都到0.95了,我觉得稳了,结果一上真实线上数据,预测效果一塌糊涂。排查到最后,问题出在“我自己写的相关性分析”上——我在建模之前先用全量数据(包括测试集)做了特征筛选,相当于把测试集的信息带进了模型训练。这就是一种数据泄露,而且非常隐蔽。
特征筛选、归一化、缺失值填充,这三件事都必须只基于训练集计算,再套用到测试集。写代码的时候最好把“转换器”封装好,fit在训练集上,transform在训练集和测试集上都调用同一套参数。
6.2 样本规模过大时怎么办
LSSVM的线性方程组规模是(n+1)×(n+1),n是样本数。n到5000以上时,直接解稠密线性方程组的复杂度是O(n³),内存和耗时都会快速上升。有次我拿1.5万条数据跑LSSVM,MATLAB直接吃掉了好几个G内存,训练也等了好几分钟。
这个场景下有几个替代方案:一是改用标准SVR,因为LIBSVM这类求解器对大规模稀疏问题有专门优化;二是用固定大小的随机训练子集,比如随机抽2000个样本训练LSSVM,把其余数据当验证集;三是用一些专门的大规模核方法变体,比如Nyström近似或者SGD优化。我不建议头铁硬撑,该换方案就换。
6.3 怎么判断模型是不是过拟合了
LSSVM因为训练是平方损失且没有稀疏性,过拟合的“舒适区”非常大。尤其是gamma设得很大、sig2设得很小的时候,训练集拟合误差几乎为零,但测试集效果会崩。
我的判断方法是三张图:训练集预测图和真实值叠画,测试集预测图和真实值叠画,以及残差图。如果训练集完美贴合、测试集发飘,明显的过拟合;如果训练集和测试集都比较平缓贴不上数据趋势,欠拟合;如果测试集残差有明显周期性或趋势性,说明模型漏掉了重要的结构性信息,这时候该考虑加特征,而不是继续调参。
6.4 经验优先还是数据优先
最后说一个很多人忽视的点。LSSVM是好工具,但它再强,也只是把“特征到目标”的经验关系拟合出来。如果你的输入特征和目标值之间本来就没什么关系,再怎么调参都白搭。我做负荷预测项目时最有价值的一步不是调参,而是去现场了解了厂房排产规律,增加了一个“周末标识”特征,模型R²一下子从0.75提到了0.91。特征工程带来的提升,往往比调一个月的参还大。
7. 关于“预测效果不好”这件事,我的一点心得
如果你是第一次把LSSVM用在多列输入单列输出的场景里,我建议按这个顺序排查:先确认数据切分方式和归一化没有泄露,再检查特征里有没有异常值和缺失值,然后看核函数参数搜索范围是否覆盖到了最优值,最后才考虑换算法或者加特征。
我自己走过一轮弯路之后,最大的体会是:LSSVM的数学形式很简洁,实现起来也不复杂,但真正决定模型能不能用的从来不是那一行trainlssvm或者np.linalg.solve,而是你对自己数据的理解程度。模型给的是一个从特征到目标的映射,你给的则是这个映射的边界和上下文。把数据梳理清楚,把评价指标定义清楚,把测试和训练的关系想清楚,LSSVM能给你带来很可靠的预测结果;反过来,这些前序工作不做干净,再好的算法也救不回来。
