References:
【引入】 支持向量机是针对二分类问题提出的,其通过最大化间隔来找到一个分离超平面,使得绝大多数样本点位于两个决策边界的外侧
而支持向量回归(Support Vector Regression) 是支持向量机的一种改进,用于解决回归问题,其同样是考虑最大化间隔,但是考虑的是两个决策边界之间的点,使尽可能多的样本点位于间隔内
换句话说,SVM 要使超平面到最近的样本点的间隔最大,SVR 则要使超平面到最远的样本点的间隔最小
【假设形式】 对于给定的容量为 的训练集 ,第 组样本中的输入 具有 个特征值,即:,输出 ,支持向量机学习到的模型为 ,使得
假设能容忍 与 间最多有 的偏差,即仅当 与 之间差距的绝对值大于 时才计算损失,这相当于以 为中心,构建了一个宽度为 的间隔带,若训练样本落于该间隔带,则认为预测正确
由此,可给出支持向量回归的优化问题:
其中, 是间隔带大小
通过求解最优化问题,可以得到超平面:
以及相应的回归函数:
【原始问题】 为每个样本点 引入松弛变量 和 ,即每个样本点分别到两个决策边界的距离
此时,支持向量回归的优化问题可写为:
即为支持向量回归的原始问题,其中, 为正则化常数
可以发现,支持向量回归只对间隔外的样本进行惩罚,当样本点位于间隔内,不计算其损失
【对偶问题】 对偶问题的转化 为求解支持向量回归的原始问题:
应用拉格朗日对偶性,通过求解对偶问题来得到原始问题的最优解
首先,构建拉格朗日函数,即为每个不等式约束引入拉格朗日乘子 、、、,即:
其中,、、、 为拉格朗日乘子向量
此时,根据拉格朗日对偶性,原始问题的对偶问题就变为极大极小问题,即:
因此,为了得到对偶问题的解,就要先求拉格朗日函数 对 、、、 的极小,再求对 、、、 的极大
对偶问题中的极小问题 对于对偶问题中的极小问题:
令拉格朗日函数 分别对 、、、 求偏导,并令其等于 ,即:
可得:
将上式带回拉格朗日函数 中,有:
故有:
对偶问题中的极大问题 对于对偶问题中的极大问题:
即为对偶问题,有:
假设上述的对偶问题对 、、、 的一个解为 , 、, 、
可以发现,对偶问题满足 KKT 条件,即:
故而有:
可以看出,当且仅当 时, 可取非零值,当且仅当 时, 可取非零值,换言之,仅当样本 不落于 间隔带时,相应的 和 才可取非零值
此外,约束 和 不能同时成立,否则有 ,因此 和 中至少有一个为零,即
而对于每个样本 ,都有 且 ,于是在得到 后,若存在 ,那么必有 ,进而对此 有:
理论上来说,可以任意选取满足 的样本,通过上式得到 ,但在实际应用中,常选取所有的满足 的样本,求取相应的 后求其平均值
故而,当 时,有回归函数:
【非线性支持向量回归】 对于回归函数:
若考虑到非线性问题,可以参照非线性支持向量机的思路,使用核方法进行特征构建,引入核函数即可,故非线性 SVR 可表示为:
关于核函数,详见:特征构建与核方法
【sklearn 实现】 线性支持向量回归 以 sklearn 中的波士顿房价数据集为例,实现线性支持向量回归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.datasets import load_bostonfrom sklearn.model_selection import train_test_splitfrom sklearn.svm import LinearSVRfrom sklearn.metrics import mean_squared_errorfrom sklearn.metrics import mean_squared_errorfrom sklearn.metrics import mean_absolute_errorfrom sklearn.metrics import r2_scoredef deal_data () : boston = load_boston() df = pd.DataFrame(boston.data, columns=boston.feature_names) df['result' ] = boston.target data = np.array(df) return data[:, :-1 ], data[:, -1 ] def train_model (features, labels) : model = LinearSVR(random_state=0 , tol=1e-05 ) model.fit(features, labels) return model def estimate_model (y_true, y_pred) : MSE = mean_squared_error(y_true, y_pred) RMSE = np.sqrt(MSE) MAE = mean_absolute_error(y_true, y_pred) R2 = r2_score(y_true, y_pred) indicators = {"MSE" : MSE, "RMSE" :RMSE, "MAE" :MAE, "R2" :R2} return indicators def visualization (y_true, y_pred, model) : plt.plot(range(y_true.shape[0 ]), y_true, "b-" ) plt.plot(range(y_true.shape[0 ]), y_pred, "r-." ) plt.legend(["original value" , "predicted value" ]) plt.xlabel("samples" , fontsize="15" ) plt.ylabel("y" , fontsize="15" ) plt.show() if __name__ == "__main__" : x, y = deal_data() x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3 , random_state=0 ) model = train_model(x_train, y_train) y_pred = model.predict(x_test) print("y test:" , y_test[:10 ]) print("y pred:" , y_pred[:10 ]) indicators = estimate_model(y_test, y_pred) print("MSE:" , indicators["MSE" ]) print("RMSE:" , indicators["RMSE" ]) print("MAE:" , indicators["MAE" ]) print("R2:" , indicators["R2" ]) visualization(y_test, y_pred, model)
非线性支持向量回归 以 sklearn 中的波士顿房价数据集为例,实现线性支持向量回归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom sklearn.datasets import load_bostonfrom sklearn.model_selection import train_test_splitfrom sklearn.svm import SVRfrom sklearn.metrics import mean_squared_errorfrom sklearn.metrics import mean_squared_errorfrom sklearn.metrics import mean_absolute_errorfrom sklearn.metrics import r2_scoredef deal_data () : boston = load_boston() df = pd.DataFrame(boston.data, columns=boston.feature_names) df['result' ] = boston.target data = np.array(df) return data[:, :-1 ], data[:, -1 ] def train_model (features, labels) : model = SVR(kernel='rbf' , degree=3 , C=1.0 , epsilon=0.2 ) model.fit(features, labels) return model def estimate_model (y_true, y_pred) : MSE = mean_squared_error(y_true, y_pred) RMSE = np.sqrt(MSE) MAE = mean_absolute_error(y_true, y_pred) R2 = r2_score(y_true, y_pred) indicators = {"MSE" : MSE, "RMSE" :RMSE, "MAE" :MAE, "R2" :R2} return indicators def visualization (y_true, y_pred, model) : plt.plot(range(y_true.shape[0 ]), y_true, "b-" ) plt.plot(range(y_true.shape[0 ]), y_pred, "r-." ) plt.legend(["original value" , "predicted value" ]) plt.xlabel("samples" , fontsize="15" ) plt.ylabel("y" , fontsize="15" ) plt.show() if __name__ == "__main__" : x, y = deal_data() x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3 ,random_state=0 ) model = train_model(x_train, y_train) y_pred = model.predict(x_test) print("y test:" , y_test[:10 ]) print("y pred:" , y_pred[:10 ]) indicators = estimate_model(y_test, y_pred) print("MSE:" , indicators["MSE" ]) print("RMSE:" , indicators["RMSE" ]) print("MAE:" , indicators["MAE" ]) print("R2:" , indicators["R2" ]) visualization(y_test, y_pred, model)
Be the first person to leave a comment!