一、前言
在《机器学习论文复现实战---linear regression》中通过Pearson 相关性分析,去除了2个高相关性特征 "PN" 和 "AN" ,数据维度变为890*25。(数据集地址)
这里我们不做前期处理,直接就将数据放入 DecisionTreeRegressor 模型中进行训练了。
二、模型训练过程
2.1 导入Python库
'''====================导入Python库===================='''
import pandas as pd #python科学计算库
import numpy as np #Python的一个开源数据分析处理库。
import matplotlib.pyplot as plt #常用Python画图工具
from sklearn.tree import DecisionTreeRegressor # 导入 DecisionTreeRegressor 模型
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 = DecisionTreeRegressor() # 模型实例化。
'''======================超参数======================='''
# "squared_error":平均平方误差,即方差减少,使用每个终端节点的平均值最小化L2损失;
# "friedman_mse":使用平均平方误差与Friedman改进得分寻找潜在的分裂;
# "absolute_error":平均绝对误差,使用每个终端节点的中位数最小化L1损失;
# "poisson":使用减少泊松偏差寻找分裂。
# splitter 参数决定了选择每个节点分割的策略,可选的策略有:"best":选择最佳分割;"random":选择最佳随机分割。
# max_depth 参数限制了树的最大深度。如果未设置,节点将继续展开直到所有叶子都是纯净的,或者每个叶子包含的样本少于 min_samples_split 指定的数量。
# min_samples_split 参数规定了分割内部节点所需的最小样本数。可以是整数或者浮点数,如果是浮点数,则表示最小样本数占总样本数的比例。
# min_samples_leaf 参数指定了一个叶子节点所需的最小样本数。这个参数可以平滑模型,特别是在回归中。
# max_features 参数决定了寻找最佳分割时考虑的特征数量。可以是整数、浮点数、"sqrt" 或 "log2"。
# random_state 参数控制估计器的随机性。即使 splitter 设置为 "best",特征在每次分割时也会随机排列。
# min_impurity_decrease 参数表示如果分割导致不纯度的减少大于或等于该值,则会进行分割。
# ccp_alpha 参数用于最小成本复杂性剪枝。选择成本复杂性最大且小于 ccp_alpha 的子树。
# 定义超参数网格。
max_depth = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]
min_samples_leaf = [1,3,5,7,9,11,13,15,17]
# 网格搜索,cv = 5表示进行5折交叉验证
grid_search = GridSearchCV(estimator = model,cv = 5, param_grid={'max_depth': max_depth,'min_samples_leaf':min_samples_leaf}, scoring='neg_mean_squared_error')
grid_search.fit(X_train, y_train)
# 最佳模型与超参数
best_model = grid_search.best_estimator_ # 最佳模型
best_max_depth = grid_search.best_params_['max_depth'] # 最佳超参数L1正则
best_min_samples_leaf = grid_search.best_params_['min_samples_leaf'] # 最佳超参数#L2正则
print(f'Best max_depth:{best_max_depth:.3f}',"\n",f'Best_min_samples_leaf:{best_min_samples_leaf:.3f}')
通过 GridSearchCV 搜索最优的 Best alpha:
Best max_depth:9.000
Best_min_samples_leaf:11.000
2.5 模型预测与评估
'''=======================模型预测========================'''
# 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}') #保留2位小数
print(f'MSE(Test):{mse_test:.3f}')
print(f'R^2(Train):{r2_train:.3f}')
print(f'R^2(Test):{r2_test:.3f}')
MSE与结果:
MSE(Train):0.050
MSE(Test):0.079
R^2(Train):0.762
R^2(Test):0.569
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('./DecisionTreeRegressor_可视化.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.tree import DecisionTreeRegressor # 导入 DecisionTreeRegressor 模型
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 = DecisionTreeRegressor() # 模型实例化。
'''======================超参数======================='''
# "squared_error":平均平方误差,即方差减少,使用每个终端节点的平均值最小化L2损失;
# "friedman_mse":使用平均平方误差与Friedman改进得分寻找潜在的分裂;
# "absolute_error":平均绝对误差,使用每个终端节点的中位数最小化L1损失;
# "poisson":使用减少泊松偏差寻找分裂。
# splitter 参数决定了选择每个节点分割的策略,可选的策略有:"best":选择最佳分割;"random":选择最佳随机分割。
# max_depth 参数限制了树的最大深度。如果未设置,节点将继续展开直到所有叶子都是纯净的,或者每个叶子包含的样本少于 min_samples_split 指定的数量。
# min_samples_split 参数规定了分割内部节点所需的最小样本数。可以是整数或者浮点数,如果是浮点数,则表示最小样本数占总样本数的比例。
# min_samples_leaf 参数指定了一个叶子节点所需的最小样本数。这个参数可以平滑模型,特别是在回归中。
# max_features 参数决定了寻找最佳分割时考虑的特征数量。可以是整数、浮点数、"sqrt" 或 "log2"。
# random_state 参数控制估计器的随机性。即使 splitter 设置为 "best",特征在每次分割时也会随机排列。
# min_impurity_decrease 参数表示如果分割导致不纯度的减少大于或等于该值,则会进行分割。
# ccp_alpha 参数用于最小成本复杂性剪枝。选择成本复杂性最大且小于 ccp_alpha 的子树。
# 定义超参数网格。
max_depth = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21]
min_samples_leaf = [1,3,5,7,9,11,13,15,17]
# 网格搜索,cv = 5表示进行5折交叉验证
grid_search = GridSearchCV(estimator = model,cv = 5, param_grid={'max_depth': max_depth,'min_samples_leaf':min_samples_leaf}, scoring='neg_mean_squared_error')
grid_search.fit(X_train, y_train)
# 最佳模型与超参数
best_model = grid_search.best_estimator_ # 最佳模型
best_max_depth = grid_search.best_params_['max_depth'] # 最佳超参数L1正则
best_min_samples_leaf = grid_search.best_params_['min_samples_leaf'] # 最佳超参数#L2正则
print(f'Best max_depth:{best_max_depth:.3f}',"\n",f'Best_min_samples_leaf:{best_min_samples_leaf:.3f}')
'''=======================模型预测========================'''
# 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}') #保留2位小数
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('./DecisionTreeRegressor_可视化.jpg',dpi = 1200) #在当前文件夹下保存jpg格式图,dpi = 1200
plt.show()
其中,有几个点,需要大家注意下~
树模型的参数较多,调参复杂,需要仔细调节参数,以找到最优解。(避免过拟合)
持续更新中。。。