pc8888888 发表于 2021-12-19 10:42

数学建模竞赛常用算法-数据挖掘、分类预测与优化算法

一系列数学建模竞赛中,常见的问题设定与模型要求有:

[*]给定一系列数据,要求进行数据降维(挑选重要数据)、数据预处理、数据特征分析、特征选择等;
[*]给定一系列数据,要求根据数据训练模型,根据输入x做出预测/分类,输出结果y;
[*]在给定的范围内搜寻最优解或者最优范围/集合。
以上三种情况,正好是2021年华为杯研究生数学建模竞赛D题考察的全部内容。也是建模竞赛中最常见的问题设定,在本篇文章中会针对性的给出建模建议并分享相关的python代码经验。以下都是我个人的经验,有错误与缺失的地方,欢迎交流指正。
数据挖掘

在建模之前,建议根据具体题目对数据进行异常值处理(包括漂移的数据点、缺失值补全)。注意,这一步是非常重要的,很多题目会在数据里埋坑,如果没有考虑到异常数据的影响,往往对于后续的分析与建模有重大影响。对于异常值的检测,常用的方法有基础的统计分析、可视化分析、分布检验;对于检测出的异常值,常用的处理方法有直接删除、根据前后数据进行平滑修正、补充为0等。接下来还可以进行一些常规的数据特征分析,比如均值、方差、最大值最小值、不同列数据的共线性分析等。
很多时候题目会给出维度丰富的数据,但其中往往很多列数据是无效/不重要的,这个时候往往题目会要求筛选出前n个重要的数据维度,用于进一步的建模等。这时候就需要进行特征选择。注意这里是在原始数据的基础上,选择最重要的n列原始数据。最常见的特征选择思路是,先剔除方差为0的列数据、对不同的列之间进行相关性检验,确保不会选择出两个蕴含相同信息的列(此处可以画一些热力图来说明选取的列之间的共线性情况,推荐使用seaborn的heatmap函数):



主要变量之间的相关度分布图

之后,可以把所有挑选过的原始数据,进行归一化数据预处理后,放进经典的机器学习模型中进行训练,根据训练后的模型反向输出每一列数据的重要性指标。这里推荐用sklearn库中的经典模型,方便训练后输出feature_importance数据。此外,有余力的同学可以用神经网络模型,根据网络输入层的weight,来判断每一列数据的重要性。
此外,还有一个与特征选择概念相近但又不能等同的任务:数据降维。数据降维更多时候指的是,对于维度丰富的数据,直接把它压缩成n维数据,这里的n维数据就不再是原始数据了。常用的数据降维算法有PCA等。
分类预测

分类任务指的是模型根据输入的样本特征x,预测样本对应的类别y(这里的y是一个离散值,比如0,1,2);
回归任务指的是模型根据输入的样本特征x,预测样本对应的分数y(这里的y是一个连续值,比如0.1,0.2)。
分类回归任务,在建模比赛中很多时候用sklearn中的经典模型,比如线性的逻辑回归、非线性的SVM / XGBoost / RandomForest / KNN等就足够了,代码上来看非常简洁。如果对于模型性能有较高要求并且有比较专业的队员,可以自行用pytorch或者TensorFlow搭建一个高性能模型并引入一系列trick/进行调参。下面贴一段相关代码仅供模型选择参考:
###########3.具体方法选择##########
####3.1 决策树回归####
from sklearn import tree
model_DecisionTreeRegressor = tree.DecisionTreeRegressor()
####3.2 线性回归####
from sklearn import linear_model
model_LinearRegression = linear_model.LinearRegression()
####3.3SVM 回归####
from sklearn import svm
model_SVR = svm.SVR()
####3.4KNN 回归####
from sklearn import neighbors
model_KNeighborsRegressor = neighbors.KNeighborsRegressor()
####3.5 随机森林回归####
from sklearn import ensemble
model_RandomForestRegressor = ensemble.RandomForestRegressor(n_estimators=500)#
这里使用 20 个决策树
####3.6Adaboost 回归####
from sklearn import ensemble
model_AdaBoostRegressor = ensemble.AdaBoostRegressor(n_estimators=500)
#这里使用 50 个决策树
####3.7GBRT 回归####
from sklearn import ensemble
model_GradientBoostingRegressor=ensemble.GradientBoostingRegressor(n_estimators=50
0)
#这里使用 100 个决策树
####3.8Bagging 回归####
from sklearn.ensemble import BaggingRegressor
model_BaggingRegressor = BaggingRegressor()
####3.9ExtraTree 极端随机树回归####
from sklearn.tree import ExtraTreeRegressor
model_ExtraTreeRegressor = ExtraTreeRegressor()优化算法

数学建模中常见的优化算法有:遗传算法、模拟退火算法、蚁群算法、粒子群算法等。笔者本人比较喜欢用遗传算法,Python中有一个宝藏优化算法库在这里强推一波(创作者本人也在知乎有号 @幼鹰me):
使用这个库可以方便快速地实现遗传算法(GA)、粒子群算法(PSO)、蚁群算法(ACA)、模拟退火算法(SA)、免疫优化算法(IA)、人工鱼群算法(AFSA),并且针对经典的TSP问题等有更方便的使用方法,官方文档撰写也很详细。在笔者本人的建模竞赛经历中,经常使用这个库。简单的安装方法就是:
pip install scikit-opt基于以上传统优化算法,可以根据具体问题设定带约束的优化算法求解。比如2021年华为杯的D题最后一问,优化目标有两个,则在定义优化算法目标函数时,加入一个惩罚项即可:
# 定义遗传算法优化函数
def schaffer(p):
p = p.reshape(1, -1)
# ADMET 约束
admet = int(cla_model1.predict(p)==1) + int(cla_model2.predict(p)==1) +
int(cla_model3.predict(p)==0) + \
int(cla_model4.predict(p)==1) + int(cla_model5.predict(p)==0)
# ERA 活性值
era = reg_model.predict(p)
# 综合优化目标:ERA + ADMET 约束
res = -era + int(admet<3)*1e5
return res
# 遗传算法实现
low_bound = data.min(axis=0)
high_bound = data.max(axis=0)
ga = GA(func=schaffer, n_dim=20, size_pop=50, max_iter=600, prob_mut=0.001,
lb=low_bound, ub=high_bound, precision=1e-7)
best_x, best_y = ga.run()
Y_history = pd.DataFrame(ga.all_history_Y)
# 绘图。红点代表每一个 iteration 中种群里每一个个体的 y 值。
# 100000 的值都是不满足 admet 至少三个为优的性质。直接忽略。
# 蓝色曲线为 ERA 活性值,越高越好。
fig, ax = plt.subplots(2, 1)
ax.plot(Y_history.index, Y_history.values, '.', color='red')
# Y_history.min(axis=1).cummin().plot(kind='line')
abs(Y_history.min(axis=1)).plot(kind='line')
plt.show()最终绘制的优化图如下,效果是非常好的:

FeastSC 发表于 2021-12-19 10:46

柏柏,太牛了吧

redhat9i 发表于 2021-12-19 10:56

这对维哥来说不是1+1=2难度
页: [1]
查看完整版本: 数学建模竞赛常用算法-数据挖掘、分类预测与优化算法