在《机器学习论文复现实战---Ridge》中我们通过 Ridge 对(数据集地址)实现了回归预测,但是模型评估的 MSE 与 R^2 值不太理想,因此我们打算尝试添加 核函数 的 Ridge 模型是否回更适合我们的数据集。
一、Kernel Ridge 介绍
1.1 背景
核岭回归(Kernel Ridge Regression,KRR)是一种结合了 岭回归(Ridge Regression)和核技巧的回归方法。它主要用于解决非线性问题,同时对数据进行 L2正则化 以防止过拟合。
岭回归 是线性回归的一个变体,它通过引入正则化项来解决普通最小二乘法的某些问题,如在多重共线性情况下的不稳定性。正则化项惩罚模型的复杂度,有助于减少模型的方差,从而提高模型的泛化能力。
核技巧 是一种数学技巧,可以让我们在高维空间中计算点之间的相似度,而不需要显式地映射数据到高维空间。这使得核岭回归能够处理那些在原始空间中是非线性可分的数据。通过将数据映射到高维特征空间,它可以找到这些空间中的线性关系,这在原始空间中对应于非线性关系。
核岭回归 在实际应用中相对简单,能够有效地处理中等大小的数据集,并且由于其正则化特性,它对于含有噪声的数据也具有很好的鲁棒性。不过,与 支持向量机(SVM)等稀疏模型相比,核岭回归学习到的模型通常不是稀疏的,这意味着在预测阶段它可能比稀疏模型要慢。尽管如此,由于其在训练阶段通常比较快,核岭回归仍然是许多回归任务中的一个强大工具。
1.2 算法原理
原理部分参考《数据挖掘——使用机器学习工具与技术》 (原书第四版)的 7.2.4节。

是目标变量,
是特征矩阵,
是回归系数,
是 L2正则化参数,
是核矩阵: 它的每个元素
是
和
在高维空间中的内积。
1.3 核方法的原理:
核方法的核心思想是将数据映射到高维空间,使得在原始空间中非线性可分的数据在新空间中线性可分。核方法的精妙之处在于,它不需要显式地计算出映射后的数据点,而是通过一个核函数直接计算数据点在高维空间中的内积。
二、模型训练过程
2.1 导入Python库
'''====================导入Python库===================='''
import pandas as pd #python科学计算库
import numpy as np #Python的一个开源数据分析处理库。
import matplotlib.pyplot as plt #常用Python画图工具
from sklearn.kernel_ridge import KernelRidge # 导入 KernelRidge 模型
from sklearn.model_selection import train_test_split # 数据划分模块
from sklearn.preprocessing import StandardScaler # 标准化模块
from sklearn.metrics import mean_squared_error,r2_score #误差函数MSE,误差函数R^2,
from sklearn.model_selection import GridSearchCV #超参数网格搜索
2.2 导入数据
'''========================导入数据========================'''
data = pd.read_excel('D:/复现/trainset_loop6.xlsx') #读取xlsx格式数据
# date = pd.read_csv('D:/复现/trainset_loop6.csv') #读取csv格式数据
print(data.isnull().sum()) #检查数据中是否存在缺失值
print(data.shape) #检查维度
print(data.columns) #数据的标签
data = data.drop(["PN","AN"], axis = 1) #axis = 1表示对列进行处理,0表示对行
Y, X = data['Eads'] , data.drop(['Eads'] , axis = 1) #对Y、X分别赋值
2.3 标准化
'''=========================标准化========================'''
#利用StandardScaler函数对X进行标准化处理
scaler = StandardScaler()
X = scaler.fit_transform(X)
'''====================划分训练集与测试集==================='''
X_train,X_test,y_train,y_test = train_test_split(X , Y , test_size=0.2 , random_state=42)
2.4 模型训练
'''=======================模型训练========================'''
#模型训练
model = KernelRidge() # 模型实例化,最大训练10000轮直到收敛小于tol=1e-4。
'''======================SVR超参数======================='''
# alpha: L2正则化强度,对应于岭回归中的正则化参数。较大的值表示更强的正则化。
# kernel:算法中所使用的核函数类型,其中有(‘linear’,‘poly’, ‘rbf’,‘sigmoid’,默认使用‘rbf’)。
# degree:多项式核函数的次数,默认为3,所以当核函数为‘poly’时用到,其它核函数忽略。
# gamma:核函数的系数,在核函数为‘rbf’,‘poly’,‘sigmoid’时使用,其他核函数忽略。gamma的值必须大于0,随着gamma的增大,对于测试集分类效果越差,对于训练集分类效果好,并且使模型的复杂度提高,泛化能力(对未知数的预测能力)较差,从而出现过拟合的情况。
# coef0:核函数中的常数值(y = kx + b中的b值),只在核函数为‘poly’跟‘sigmoid’时使用。
# kernel_params (default=None): 传递给核函数的其他参数。
# 定义超参数网格。
alpha = [0.001,0.01,0.1,1,10,100,1000] # L2正则化强度
kernel = ["linear","poly", "rbf"] #核函数类型,我们的数据类型不适合‘sigmoid’分类核函数。
# 网格搜索,并进行cv=5的5折交叉验证
grid_search = GridSearchCV(estimator = model,cv = 5, param_grid={'alpha': alpha,'kernel':kernel}, scoring='neg_mean_squared_error')
grid_search.fit(X_train, y_train) # 模型训练
# 最佳模型与超参数
best_model = grid_search.best_estimator_ # 最佳模型
best_alpha = grid_search.best_params_['alpha'] # 最佳超参数L1正则
best_kernel = grid_search.best_params_['kernel'] # 最佳超参数#L2正则
print(f'Best alpha:{best_alpha:.3f}'"\n",f'Best_kernel:{best_kernel}')
超参数详解 :
alpha: L2正则化强度;较大的值表示更强的正则化。
kernel(default=‘rbf’): 核函数类型,其中有(回归:‘linear’,‘poly’, ‘rbf’,分类‘sigmoid’)。
degree(default=3): ‘poly’多项式核函数的次数,默认为3,其它核函数忽略。
gamma:核函数的系数,在核函数为‘rbf’,‘poly’,‘sigmoid’时使用,其他核函数忽略。gamma>0,且随着gamma的增大,对于测试集分类效果越差,对于训练集分类效果好,并且使模型的复杂度提高,泛化能力(对未知数的预测能力)较差,从而出现过拟合的情况。
coef0: 核函数中的常数值(如:y = kx + b中的b值),只在核函数为‘poly’跟‘sigmoid’时使用。
kernel_params (default=None): 传递给核函数的其他参数。
通过 GridSearchCV 搜索最优的 超参数:
Best alpha:1.000
Best_kernel:rbf
2.5 模型预测与评估
'''=======================模型预测========================'''
y_pred_train = best_model.predict(X_train)
y_pred_test = best_model.predict(X_test)
'''=======================模型评估========================'''
mse_train=mean_squared_error(y_train,y_pred_train) #均方误差越小模型越好
mse_test=mean_squared_error(y_test,y_pred_test) #R2 表示模型对因变量的解释能力,取值范围从 0 ~ 1,越接近 1 表示模型对数据的拟合程度越好。
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)
print(f'MSE(Train):{mse_train:.3f}') #保留3位小数
print(f'MSE(Test):{mse_test:.3f}')
print(f'R^2(Train):{r2_train:.3f}')
print(f'R^2(Test):{r2_test:.3f}')
MSE 与结果:( 相对于 Ridge 回归,Kernel Ridge 更适合此数据集 )
Kernel Ridge: Ridge:
MSE(Train):0.074 MSE(Train):0.10
MSE(Test):0.081 MSE(Test):0.09
R^2(Train):0.652 R^2(Train):0.53
R^2(Test):0.561 R^2(Test):0.50
2.6 可视化
'''======================结果可视化======================='''
plt.figure(figsize=(8,8))
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
colors = ['b', 'r'] # 设置颜色
markers = ["*","o"] # 设置点的形状
Y_train_picture = [y_train,y_test] #可视化图的x轴数据
Y_pred_picture = [y_pred_train,y_pred_test] #可视化图的y轴数据
for i in range(0,2):
plt.scatter(Y_train_picture[i],
Y_pred_picture[i],
s = 20, # 表示点的大小
c = colors[i], # 颜色
marker = markers[i], # 点的形状
edgecolors='b', # 散点边框颜色
alpha=0.6) # 透明度
plt.plot([-1.0,1.0],[-1.0,1.0],'r--') #可视化图数据范围
plt.xlabel('Actual') #x轴标签
plt.ylabel('Predicted') #y轴标签
plt.legend(['train', 'test'], loc='upper right',frameon=False) #图例,位置位于右上方,去掉图例边框
plt.title('Actual vs Predicted',fontsize=15, c='r')
# 将图保存为*.jpg图
plt.savefig('./KernelRidge_可视化.jpg',dpi = 1200) #在当前文件夹下保存jpg格式图,dpi = 1200
plt.show()

此图表示,数据点越靠近中间红线模型越好。
三、代码全部注释
'''====================导入Python库===================='''
import pandas as pd #python科学计算库
import numpy as np #Python的一个开源数据分析处理库。
import matplotlib.pyplot as plt #常用Python画图工具
from sklearn.kernel_ridge import KernelRidge # 导入 KernelRidge 模型
from sklearn.model_selection import train_test_split # 数据划分模块
from sklearn.preprocessing import StandardScaler # 标准化模块
from sklearn.metrics import mean_squared_error,r2_score #误差函数MSE,误差函数R^2,
from sklearn.model_selection import GridSearchCV #超参数网格搜索
'''========================导入数据========================'''
data = pd.read_excel('D:/复现/trainset_loop6.xlsx') #读取xlsx格式数据
# date = pd.read_csv('D:/复现/trainset_loop6.csv') #读取csv格式数据
print(data.isnull().sum()) #检查数据中是否存在缺失值
print(data.shape) #检查维度
print(data.columns) #数据的标签
data = data.drop(["PN","AN"], axis = 1) #axis = 1表示对列进行处理,0表示对行
Y, X = data['Eads'] , data.drop(['Eads'] , axis = 1) #对Y、X分别赋值
'''=========================标准化========================'''
#利用StandardScaler函数对X进行标准化处理
scaler = StandardScaler()
X = scaler.fit_transform(X)
'''====================划分训练集与测试集==================='''
X_train,X_test,y_train,y_test = train_test_split(X , Y , test_size=0.2 , random_state=42)
'''=======================模型训练========================'''
#模型训练
model = KernelRidge() # 模型实例化,最大训练10000轮直到收敛小于tol=1e-4。
'''======================SVR超参数======================='''
# alpha: L2正则化强度,对应于岭回归中的正则化参数。较大的值表示更强的正则化。
# kernel:算法中所使用的核函数类型,其中有(‘linear’,‘poly’, ‘rbf’,‘sigmoid’,默认使用‘rbf’)。
# degree:多项式核函数的次数,默认为3,所以当核函数为‘poly’时用到,其它核函数忽略。
# gamma:核函数的系数,在核函数为‘rbf’,‘poly’,‘sigmoid’时使用,其他核函数忽略。gamma的值必须大于0,随着gamma的增大,对于测试集分类效果越差,对于训练集分类效果好,并且使模型的复杂度提高,泛化能力(对未知数的预测能力)较差,从而出现过拟合的情况。
# coef0:核函数中的常数值(y = kx + b中的b值),只在核函数为‘poly’跟‘sigmoid’时使用。
# kernel_params (default=None): 传递给核函数的其他参数。
# 定义超参数网格。
alpha = [0.001,0.01,0.1,1,10,100,1000] # L2正则化强度
kernel = ["linear","poly", "rbf"] #核函数类型,我们的数据类型不适合‘sigmoid’分类核函数。
# 网格搜索,并进行cv=5的5折交叉验证
grid_search = GridSearchCV(estimator = model,cv = 5, param_grid={'alpha': alpha,'kernel':kernel}, scoring='neg_mean_squared_error')
grid_search.fit(X_train, y_train) # 模型训练
# 最佳模型与超参数
best_model = grid_search.best_estimator_ # 最佳模型
best_alpha = grid_search.best_params_['alpha'] # 最佳超参数L1正则
best_kernel = grid_search.best_params_['kernel'] # 最佳超参数#L2正则
print(f'Best alpha:{best_alpha:.3f}'"\n",f'Best_kernel:{best_kernel}')
'''=======================模型预测========================'''
# best_model模型预测
y_pred_train = best_model.predict(X_train)
y_pred_test = best_model.predict(X_test)
#评估
mse_train=mean_squared_error(y_train,y_pred_train) #均方误差越小模型越好
mse_test=mean_squared_error(y_test,y_pred_test) #R2 表示模型对因变量的解释能力,取值范围从 0 ~ 1,越接近 1 表示模型对数据的拟合程度越好。
r2_train=r2_score(y_train,y_pred_train)
r2_test=r2_score(y_test,y_pred_test)
print(f'MSE(Train):{mse_train:.3f}') #保留3位小数
print(f'MSE(Test):{mse_test:.3f}')
print(f'R^2(Train):{r2_train:.3f}')
print(f'R^2(Test):{r2_test:.3f}')
'''======================结果可视化======================='''
plt.figure(figsize=(8,8))
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
colors = ['b', 'r'] # 设置颜色
markers = ["*","o"] # 设置点的形状
Y_train_picture = [y_train,y_test] #可视化图的x轴数据
Y_pred_picture = [y_pred_train,y_pred_test] #可视化图的y轴数据
for i in range(0,2):
plt.scatter(Y_train_picture[i],
Y_pred_picture[i],
s = 20, # 表示点的大小
c = colors[i], # 颜色
marker = markers[i], # 点的形状
edgecolors='b', # 散点边框颜色
alpha=0.6) # 透明度
plt.plot([-1.0,1.0],[-1.0,1.0],'r--') #可视化图数据范围
plt.xlabel('Actual') #x轴标签
plt.ylabel('Predicted') #y轴标签
plt.legend(['train', 'test'], loc='upper right',frameon=False) #图例,位置位于右上方,去掉图例边框
plt.title('Actual vs Predicted',fontsize=15, c='r')
# 将图保存为*.jpg图
plt.savefig('./KernelRidge_可视化.jpg',dpi = 1200,bbox_inches='tight') #在当前文件夹下保存jpg格式图,dpi = 1200,bbox_inches='tight'消除空白边距
plt.show()
参考:
sklearn实现核岭回归(Kernel ridge regression)
持续更新中。。。

---论文实战&spm=1001.2101.3001.5002&articleId=143429101&d=1&t=3&u=da69340980b0434eac59b3b76afa4c5c)
1280

被折叠的 条评论
为什么被折叠?



