第十五届“华中杯”大学生数学建模挑战赛-C 题 空气质量预测与预警-思路解析

问题一:根据附件1和附件2,对数据进行分析和处理,筛选出与 PM2.5 浓度变化有关的因素,并说明筛选出的因素对 PM2.5 浓度影响的程度。

思路提要:首先需要对给出的数据进行基本的数据处理(数据读取与查看、空缺值填补、异常值剔除等),接着需要筛选与PM2.5浓度变化有关的因素,该题实质是特征工程(筛选),常用的方法有方差过滤、卡方检验、相关系数、rf随机森林等方法,或者是基于机器学习训练的递归特征消除方法。一般会选择两至三种方法结合来进行特征筛选。

问题二:自行划分训练集和测试集,根据附件1和附件2,基于问题一构建PM2.5浓度多步预测模型,分别使用均方根误差(RMSE)对 3 步、5 步、7 步、12步预测效果进行评估,其结果请用表1格式在正文中具体给出,并对测试集及其预测结果进行可视化。同时,用该模型预测附件3所给定时间PM2.5 浓度,其结果请用表2格式在正文中具体给出

思路提要:根据第一问的提示,我们需要建立一个多元预测的时间序列机器学习模型,常用的就是LSTM多元多步预测模型。按照题意进行3/5/7/12步预测,并输出预测误差rmse即可。

问题三:构建 AQI 多步预测模型,使用均方根误差(RMSE)对建模效果进行评估,并对测试集及其预测结果进行可视化。同时,用该模型预测附件 3 所给定时间的 AQI,并给出每天空气质量的预警等级,其结果请用表 3 和表 4 格式在正文中具体给出。

思路提要:由于AQI是由多种污染物指标计算得到的,所以不应该直接预测AQI,应该分别预测六种基本污染物的浓度,然后利用预测值计算得到AQI的预测值。同样采用LSTM模型。

这里提一下AQI计算,需要先利用各污染物浓度算出IAQI然后才能得到AQI,参考代码:

from math import ceil  #导入进位取整函数
from collections import OrderedDict  #导入有序字典模块(Python3.6以下字典无序)
 
#定义包含污染物名称、浓度区间和IAQI区间的有序字典
mapping = OrderedDict([
            ('PM2.5', ((0,0),(35,50),(75,100),(115,150),(150,200),(250,300),
                      (350,400),(500,500))),
            ('PM10', ((0,0),(50,50),(150,100),(250,150),(350,200),(420,300),
                      (500,400),(600,500))),
            ('臭氧', ((0,0),(100,50),(160,100),(215,150),(265,200),(800,300),
                      (1000,400),(1200,500))),
            ('一氧化碳', ((0,0),(2,50),(4,100),(14,150),(24,200),(36,300),
                      (48,400),(60,500))), 
            ('二氧化氮', ((0,0),(40,50),(80,100),(180,150),(280,200),(565,300),
                      (750,400),(940,500))),
            ('二氧化硫', ((0,0),(50,50),(150,100),(475,150),(800,200), (1600,300),
                      (2100,400),(2620,500)))
          ])
 
def data_validity(pollutants):
    """判断数据有效性"""
    for k, v in pollutants.items():
        if not v:
            pollutants[k] = '0'  #空白初始化为0
        elif not v.isdecimal():
            if k != '一氧化碳':  #因CO可保留3位以下小数,需单独判断
                return False
            num = v.split('.')  #以小数点为分割符切成两部分来判断
            if len(num) != 2 or (not num[0].isdecimal()) or (not num[1].isdecimal()) or len(num[1]) > 3:
                return False
        if float(pollutants[k]) > mapping[k][-1][0]:  #超过限值情况
            return False
    else:  #正常循环退出
        return True
 
def iaqi_calc(pollutants):
    """计算各污染物IAQI"""
    for k, v in mapping.items():  #遍历字典,确定污染物名称
        for i in range(len(v)-1):  #遍历嵌套元组,确定污染物浓度所处区间
            if float(pollutants[k]) <= v[i+1][0]:  #利用相似三角形相似比求值
                iaqi = ceil((float(pollutants[k])-v[i][0])*(v[i+1][1]-v[i][1])/(v[i+1][0]-v[i][0]))+v[i][1]
                pollutants[k] = iaqi  #更新污染物浓度为IAQI
                break  #计算完毕,需及时跳出(为什么^-^)
    for k, v in pollutants.items():
        print("{}-IAQI:{}".format(k, v))
 
def aqi_calc(pollutants):
    """计算AQI及相关信息"""
    aqi = max(pollutants.values())
 
    if aqi > 50:  #首要污染物
        prime_pollutants = '、'.join(k for k, v in pollutants.items() if v == aqi)
    else:
        prime_pollutants = '无'
 
    if aqi > 100:  #超标污染物
        exceed_pollutants = '、'.join(k for k, v in pollutants.items() if v > 100)
    else:
        exceed_pollutants = '无'
 
    print("AQI:{}".format(aqi))
    print("首要污染物:{}".format(prime_pollutants))
    print("超标污染物:{}".format(exceed_pollutants))
 
def main():
    """主程序"""
    while True:
        #定义临时存放各污染物浓度和IAQI数值的有序字典
        pollutants = OrderedDict([(k, input('请输入{}浓度:'.format(k))) for k in mapping])
 
        if data_validity(pollutants):
            print("-"*50)
            iaqi_calc(pollutants)
            print("-"*50)
            aqi_calc(pollutants)
            print("-"*50)
            if input("如需终止计算,请输入q后回车:").lower() == 'q':
                break
            print("-"*50)
        else:
            print("-"*50)
            print("数据无效,请重新输入!")
            print("-"*50)
 
if __name__ == '__main__':
    main()

完整版思路模型、代码与答案请私信获取~

猜你喜欢

转载自blog.csdn.net/lichensun/article/details/130453031