小P:小H,有没有什么好的办法预测下未来的销售额啊 小H:很多啊,简单的用统计中的一元/多元回归就好了,如果线性不明显,可以用机器学习训练预测
# 导入库
import pandas as pd
import numpy as np
from sklearn.linear_model import BayesianRidge, ElasticNet
from sklearn.svm import SVR
from xgboost import XGBRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import explained_variance_score, mean_absolute_error, \
mean_squared_error, r2_score
import matplotlib.pyplot as plt
from sklearn.model_selection import GridSearchCV
# 读取数据
raw_data = pd.read_csv('regression.txt', delimiter=' ', header=None) # 读取数据文件
raw_data.head()
image-20230206153224474
# 拆分因变量
X_raw,y = raw_data.iloc[:, :-1],raw_data.iloc[:, -1] # 分割自变量,因变量
# 数据标准化
model_ss = StandardScaler()
X = model_ss.fit_transform(X_raw)
X = pd.DataFrame(X, columns=raw_data.columns[:-1])
# 样本拆分
num = int(X.shape[0]*0.7)
X_train,X_test = X.iloc[:num,:],X.iloc[num:,:] # 拆分训练集和测试集
y_train,y_test = y[:num],y[num:] # 拆分训练集和测试集
# 初选回归模型
model_names = ['BayesianRidge', 'XGBR', 'ElasticNet', 'SVR', 'GBR'] # 不同模型的名称列表
model_br = BayesianRidge() # 贝叶斯岭回归
model_xgbr = XGBRegressor(random_state=0) # XGBR
model_etc = ElasticNet(random_state=0) # 弹性网络回归
model_svr = SVR(gamma='scale') # 支持向量机回归
model_gbr = GradientBoostingRegressor(random_state=0) # 梯度增强回归
model_list = [model_br, model_xgbr, model_etc,model_svr, model_gbr]
pre_y_list = [model.fit(X_train, y_train).predict(X_test) for model in model_list] # 各个回归模型预测的y值列表
# 模型效果评估
n_samples, n_features = X.shape # 总样本量,总特征数
model_metrics_functions = [explained_variance_score, mean_absolute_error, mean_squared_error,r2_score] # 回归评估指标对象集
model_metrics_list = [[m(y_test, pre_y_list[i]) for m in model_metrics_functions] for i in range(len(model_list))] # 回归评估指标列表
regresstion_score = pd.DataFrame(model_metrics_list, index=model_names,
columns=['explained_variance', 'mae', 'mse', 'r2']) # 建立回归指标的数据框
print('all samples: %d \t features: %d' % (n_samples, n_features),'\n','-'*60) # 打印输出样本量和特征数量
regresstion_score # 模型回归指标
all samples: 506 features: 13
------------------------------------------------------------
image-20230206153244927
# 模型效果可视化
plt.figure(figsize=(10, 10))
for i, pre_y in enumerate(pre_y_list):
plt.subplot(len(pre_y_list)+1,1,i+1) # 子图6行*1列
plt.plot(np.arange(len(y_test)), y_test, color='k', label='true y')
plt.plot(np.arange(len(y_test)), pre_y_list[i], 'g--', label=model_names[i])
plt.title('True and {} result comparison'.format(model_names[i]))
plt.legend(loc='upper right')
plt.tight_layout() # 自动调整子图间隔
output_14_0
# 上述初始模型XGBR与GBR表现较优。这里以XGBR为例进行网格搜索+交叉验证
clf = XGBRegressor(random_state=0) # 建立GradientBoostingRegressor回归对象,该模型较好处理特征量纲与共线性问题
parameters = {
'n_estimators': [10, 50, 100, 500],
'learning_rate': [0.05, 0.1, 0.3, 0.5],
'max_depth': [5, 6, 7, 10]} # 定义要优化的参数信息
model_gs = GridSearchCV(estimator=clf,
param_grid=parameters, cv=5, scoring='r2', n_jobs=-1) # 建立交叉检验模型对象
model_gs.fit(X_train, y_train) # 训练交叉检验模型
print('Best score is:', model_gs.best_score_) # 获得交叉检验模型得出的最优得分
print('Best parameter is:', model_gs.best_params_) # 获得交叉检验模型得出的最优参数
Best score is: 0.7624423570088324
Best parameter is: {'learning_rate': 0.1, 'max_depth': 5, 'n_estimators': 50}
# 获取最佳训练模型
model_xgbr = model_gs.best_estimator_ # 获得交叉检验模型得出的最优模型对象
pre_y = model_xgbr.predict(X_test)
# 模型评估 优于上次
model_metrics_list = [[m(y_test, pre_y) for m in model_metrics_functions]] # 回归评估指标列表
regresstion_score = pd.DataFrame(model_metrics_list, index=['model_xgbr'],
columns=['explained_variance', 'mae', 'mse', 'r2']) # 建立回归指标的数据框
regresstion_score # 模型回归指标
explained_variance | mae | mse | r2 | |
---|---|---|---|---|
model_xgbr | 0.253889 | 4.861756 | 50.986239 | 0.231513 |
# 模型效果可视化
plt.figure(figsize=(10, 2)) # 创建画布
plt.plot(np.arange(len(y_test)), y_test, color='k', label='true y') # 画出原始值的曲线
plt.plot(np.arange(len(y_test)), pre_y, 'g--', label='XGBR') # 画出每条预测结果线
plt.title('True and {} result comparison'.format('XGBR')) # 标题
plt.legend(loc='upper right') # 图例位置
plt.tight_layout() # 自动调整子图间隔
output_19_0
机器学习中用于回归的算法也较多,而且不难发现XGBoost在回归预测中也具有较好的表现,因此在日常业务中,碰到挖掘任务可首选XGBoost~
共勉~