发布日期:2024-08-26 来源: 网络 阅读量()
一系列数学建模竞赛中,常见的问题设定与模型要求有: 以上三种情况,正好是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/进行调参。下面贴一段相关代码仅供模型选择参考: 数学建模中常见的优化算法有:遗传算法、模拟退火算法、蚁群算法、粒子群算法等。笔者本人比较喜欢用遗传算法,Python中有一个宝藏优化算法库在这里强推一波(创作者本人也在知乎有号 @幼鹰me): 使用这个库可以方便快速地实现遗传算法(GA)、粒子群算法(PSO)、蚁群算法(ACA)、模拟退火算法(SA)、免疫优化算法(IA)、人工鱼群算法(AFSA),并且针对经典的TSP问题等有更方便的使用方法,官方文档撰写也很详细。在笔者本人的建模竞赛经历中,经常使用这个库。简单的安装方法就是: 基于以上传统优化算法,可以根据具体问题设定带约束的优化算法求解。比如2021年华为杯的D题最后一问,优化目标有两个,则在定义优化算法目标函数时,加入一个惩罚项即可: 最终绘制的优化图如下,效果是非常好的:###########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()
pip install scikit-opt
# 定义遗传算法优化函数
def schaffer(p):
p = p.reshape(1, -1)
# ADMET 约束
admet = int(cla_model1.predict(p)[0]==1) + int(cla_model2.predict(p)[0]==1) +
int(cla_model3.predict(p)[0]==0) + \\
int(cla_model4.predict(p)[0]==1) + int(cla_model5.predict(p)[0]==0)
# ERA 活性值
era = reg_model.predict(p)[0]
# 综合优化目标: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[0].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()