当前位置:   article > 正文

2024 年第十四届 APMCM 亚太地区大学生数学建模竞赛-B题 洪水灾害的数据分析与预测

b题 洪水灾害的数据分析与预测

目录

一、问题重述

二、解题思路

三、解题代码

问题 1.

问题 2.

问题 3.

问题 4.

四、源代码和成品论文获取方式


一、问题重述

洪水是暴雨、急剧融冰化雪、风暴潮等自然因素引起的江河湖泊水量迅速增 加,或者水位迅猛上涨的一种自然现象,是自然灾害。洪水又称大水,是河流、 海洋、湖泊等水体上涨超过一定水位,威胁有关地区的安全,甚至造成灾害的水 流。洪水一词,在中国出自先秦《尚书·尧典》。从那时起,四千多年中有过很 多次水灾记载,欧洲最早的洪水记载也远在公元前 1450 年。在西亚的底格里斯-幼发拉底河以及非洲的尼罗河关于洪水的记载,则可追溯到公元前 40 世纪。2023 年 6 月 24 日 8 时至 25 日 8 时,中国 15 条河流发生超警洪水。2023 年,全球洪水等造成了数十亿美元的经济损失。

洪水的频率和严重程度与人口增长趋势相当一致。迅猛的人口增长,扩大耕地,围湖造田,乱砍滥伐等人为破坏不断地改变着地表状态,改变了汇流条件,加剧了洪灾程度。在降水多的年份,洪水是否造成灾害,以及洪水灾害的大小,也离不开人为因素,长期以来人为的森林破坏是其重要原因。长江上游乱砍滥伐的恶果是惊人的水土流失。现已达 35 万平方千米,每年土壤浸融量达 25 亿吨。河流、湖泊、水库淤积的泥沙量达 20 亿吨。仅四川一省一年流入长江各支流的泥沙,如叠成宽高各 1 米的堤,可以围绕地球赤道 16 圈。我国第一大淡水湖洞庭湖每年沉积的泥沙达 1 亿多吨,有专家惊呼:“这样下去,要不了 50 年,洞庭湖将从地球上消失!”长江之险,险在荆江,由于泥沙俱下,如今荆江段河床比江外地面高出十多米,成了除黄河之外名副其实的地上河。对森林的肆意砍伐不仅危害自己,而且祸及子孙后代,世界上许多地方,如美索不达米亚、小亚细亚、阿尔卑斯山南坡等由于过度砍伐森林,最后都变成了不毛之地。

附件 train.csv 中提供了超过 100 万的洪水数据,其中包含洪水事件的 id、季风强度、地形排水、河流管理、森林砍伐、城市化、气候变化、大坝质量、淤积、农业实践、侵蚀、无效防灾、排水系统、海岸脆弱性、滑坡、流域、基础设施恶化、人口得分、湿地损失、规划不足、政策因素和发生洪水的概率。

附件 test.csv 中包含了超过 70 万的洪水数据,其中包含洪水事件的 id 和上 述 20 个指标得分,缺少发生洪水的概率。附件 submit.csv 中包含 test.csv 中的洪水事件的 id,缺少发生洪水的概率。

请你们的团队通过数学建模和数据分析的方法,预测发生洪水灾害的概率,解决以下问题:

问题 1. 请分析附件 train.csv 中的数据,分析并可视化上述 20 个指标中,哪些指标与洪水的发生有着密切的关联?哪些指标与洪水发生的相关性不大?并分析可能的原因,然后针对洪水的提前预防,提出你们合理的建议和措施。

问题 2.将附件 train.csv 中洪水发生的概率聚类成不同类别,分析具有高、中、低风险的洪水事件的指标特征。然后,选取合适的指标,计算不同指标的权重,建立发生洪水不同风险的预警评价模型,最后进行模型的灵敏度分析。

问题 3. 基于问题 1 中指标分析的结果,请建立洪水发生概率的预测模型,从 20 个指标中选取合适指标,预测洪水发生的概率,并验证你们预测模型的准确性。如果仅用 5 个关键指标,如何调整改进你们的洪水发生概率的预测模型?

问题 4. 基于问题 2 中建立的洪水发生概率的预测模型,预测附件 test.csv 中所有事件发生洪水的概率,并将预测结果填入附件 submit.csv 中。然后绘制这 74多万件发生洪水的概率的直方图和折线图,分析此结果的分布是否服从正态分布。

二、解题思路

数据预处理:首先对附件 train.csv 中的数据进行预处理,包括缺失值的填补、异常值的处理和数据标准化等,确保数据的可靠性和准确性。

相关性分析:通过计算每个指标与洪水发生的相关系数,来衡量指标与洪水发生的关联程度。相关系数绝对值越大,表示相关性越强。通过可视化分析,可以直观地展示各个指标与洪水发生的关联程度。

原因分析:分析相关性较强的指标和相关性较弱的指标,找出可能的原因。比如,相关性较强的指标可能是洪水发生的主要原因,相关性较弱的指标可能与洪水发生无关或者相关性较弱的原因。

建议和措施:根据分析结果,提出针对洪水的提前预防的合理建议和措施。比如,针对相关性较强的指标,可以采取措施进行调整或改善,从而减少洪水的发生;针对相关性较弱的指标,可以采取措施进行监控或预警,从而及时应对可能发生的洪水。

三、解题代码

https://www.bilibili.com/video/BV1Em421G7oT/?spm_id_from=333.999.0.0&vd_source=4799e5e94caae2e86099043a5bf8ee48icon-default.png?t=N7T8https://www.bilibili.com/video/BV1Em421G7oT/?spm_id_from=333.999.0.0&vd_source=4799e5e94caae2e86099043a5bf8ee48

问题 1.

请分析附件 train.csv 中的数据,分析并可视化上述 20 个指标中,哪些指标与洪水的发生有着密切的关联?哪些指标与洪水发生的相关性不大?并分析可能的原因,然后针对洪水的提前预防,提出你们合理的建议和措施。

首先对附件数据进行数据分析,分析代码如下:

  1. import matplotlib
  2. # 设置 matplotlib 支持中文显示
  3. matplotlib.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
  4. matplotlib.rcParams['axes.unicode_minus'] = False # 解决保存图像时负号'-'显示为方块的问题
  5. #%%
  6. import pandas as pd
  7. # 读取CSV文件
  8. def load_data(file_path):
  9. try:
  10. data = pd.read_csv(file_path, encoding='gbk', delimiter='\t')
  11. return data
  12. except Exception as e:
  13. print(f"读取文件时出错: {e}")
  14. return None
  15. # 基本统计分析
  16. def analyze_data(data):
  17. if data is not None:
  18. # 显示数据的基本描述统计
  19. print("描述性统计:")
  20. print(data.describe())
  21. # 显示数据中每个列的数据类型
  22. print("\n数据类型:")
  23. print(data.dtypes)
  24. # 检查是否有缺失值
  25. print("\n缺失值检查:")
  26. print(data.isnull().sum())
  27. # 主函数,执行程序
  28. def main():#B站UP:white学长努力中
  29. file_path = 'train.csv'
  30. data = load_data(file_path)
  31. analyze_data(data)
  32. if __name__ == "__main__":
  33. main()
  34. import pandas as pd
  35. from sklearn.model_selection import train_test_split
  36. from sklearn.preprocessing import StandardScaler
  37. from tensorflow.keras.models import Sequential
  38. from tensorflow.keras.layers import Dense
  39. from tensorflow.keras.optimizers import Adam
  40. def load_data(file_path):
  41. # 尝试使用pandas的read_csv自动检测分隔符
  42. data = pd.read_csv(file_path, encoding='gbk', sep=None, engine='python')
  43. # 删除完全为空的行
  44. data.dropna(how='all', inplace=True)
  45. # 显示数据概览
  46. print(data.head())
  47. return data
  48. #B站UP:white学长努力中
  49. def preprocess_data(data):
  50. # 移除ID列
  51. data = data.drop(columns=['id'])
  52. # 填充缺失值#B站UP:white学长努力中
  53. data.fillna(data.median(), inplace=True)
  54. # 将所有列转换为数值类型,非数值转为NaN后填充中位数
  55. data = data.apply(pd.to_numeric, errors='coerce').fillna(data.median())
  56. # 标准化数据
  57. scaler = StandardScaler()
  58. features = data.columns[:-1] # 最后一列是洪水概率
  59. X = scaler.fit_transform(data[features])
  60. y = data.iloc[:, -1] # 最后一列是标签
  61. return train_test_split(X, y, test_size=0.2, random_state=42)
  62. #B站UP:white学长努力中
  63. def build_model(input_dim):
  64. model = Sequential([
  65. Dense(64, activation='relu', input_dim=input_dim),
  66. Dense(64, activation='relu'),
  67. Dense(1, activation='linear')
  68. ])
  69. model.compile(optimizer=Adam(learning_rate=0.001), loss='mse')
  70. return model
  71. #B站UP:white学长努力中
  72. file_path = 'train.csv'
  73. data = load_data(file_path)
  74. X_train, X_test, y_train, y_test = preprocess_data(data)
  75. model = build_model(X_train.shape[1])
  76. history=model.fit(X_train, y_train, epochs=100, validation_data=(X_test, y_test), verbose=2)

  1. import matplotlib.pyplot as plt
  2. import seaborn as sns
  3. import numpy as np
  4. import pandas as pd
  5. # 设置中文字体
  6. plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
  7. plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
  8. # 绘制每个特征的直方图
  9. def plot_feature_distributions(data):
  10. features = data.columns[:-1]
  11. num_features = len(features)
  12. rows = (num_features + 3) // 4 # 计算需要多少行
  13. plt.figure(figsize=(20, 4 * rows))
  14. for i, col in enumerate(features):#B站UP:white学长努力中
  15. plt.subplot(rows, 4, i + 1)
  16. sns.histplot(data[col], kde=True)
  17. plt.title(col)
  18. plt.xticks(rotation=45) # 旋转x轴标签,防止重叠
  19. plt.tight_layout()
  20. plt.show()#B站UP:white学长努力中
  21. # 绘制训练和验证损失
  22. def plot_training_history(history):
  23. plt.figure(figsize=(10, 5))
  24. plt.plot(history.history['loss'], label='训练损失')
  25. plt.plot(history.history['val_loss'], label='验证损失')
  26. plt.title('模型训练过程中的损失变化')
  27. plt.ylabel('损失')
  28. plt.xlabel('周期')
  29. plt.legend()#B站UP:white学长努力中
  30. plt.show()
  31. # 绘制特征与洪水概率的相关性
  32. def plot_feature_correlations(data):
  33. plt.figure(figsize=(12, 10))
  34. sns.heatmap(data.corr(), annot=True, cmap='coolwarm', fmt=".2f")
  35. plt.title('特征相关性热图')#B站UP:white学长努力中
  36. plt.show()
  37. # 预测并与实际值比较
  38. def plot_predictions(X_test, y_test, model):
  39. predictions = model.predict(X_test)
  40. plt.figure(figsize=(10, 5))
  41. plt.scatter(y_test, predictions, alpha=0.2)
  42. plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=3)
  43. plt.title('预测值 vs 实际值')
  44. plt.xlabel('实际值')
  45. plt.ylabel('预测值')#B站UP:white学长努力中
  46. plt.show()
  47. plot_feature_distributions(data)
  48. plot_training_history(history)
  49. plot_feature_correlations(data)
  50. plot_predictions(X_test, y_test, model)

问题 2.

将附件 train.csv 中洪水发生的概率聚类成不同类别,分析具有高、中、低风险的洪水事件的指标特征。然后,选取合适的指标,计算不同指标的权重,建立发生洪水不同风险的预警评价模型,最后进行模型的灵敏度分析。

具体讲解请看B站视频

  1. import pandas as pd
  2. from sklearn.preprocessing import StandardScaler
  3. from sklearn.cluster import KMeans
  4. from sklearn.ensemble import RandomForestRegressor
  5. from sklearn.model_selection import train_test_split
  6. from sklearn.metrics import mean_squared_error
  7. def load_data(filepath):
  8. # 加载数据,并尝试自动检测分隔符
  9. data = pd.read_csv(filepath, encoding='gbk', sep=None, engine='python')
  10. # 删除完全为空的行
  11. data.dropna(how='all', inplace=True)
  12. print("#B站UP:white学长努力中\n", data.head())
  13. return data
  14. def preprocess_data(data):
  15. # 移除ID列,假设它是第一列
  16. data = data.iloc[:, 1:]
  17. # 填充缺失值
  18. data.fillna(data.median(), inplace=True)
  19. # 转换所有列为数值型,如果转换失败则填充NaN并使用中位数替换
  20. data = data.apply(pd.to_numeric, errors='coerce').fillna(data.median())
  21. # 标准化数据,假设最后一列是洪水概率
  22. scaler = StandardScaler()
  23. features = data.columns[:-1]
  24. X = scaler.fit_transform(data[features])#B站UP:white学长努力中
  25. y = data.iloc[:, -1]
  26. return train_test_split(X, y, test_size=0.2, random_state=42)
  27. def perform_clustering(X_train):
  28. # 进行K-means聚类,假设3个簇
  29. kmeans = KMeans(n_clusters=3, random_state=0)
  30. clusters = kmeans.fit_predict(X_train)
  31. return clusters
  32. def feature_importance(X_train, y_train):#B站UP:white学长努力中
  33. # 特征重要性评估
  34. model = RandomForestRegressor(n_estimators=50, random_state=42)
  35. model.fit(X_train, y_train)#B站UP:white学长努力中
  36. importances = model.feature_importances_
  37. print("Feature Importances:", importances)
  38. return model
  39. def sensitivity_analysis(model, X_test):
  40. # 灵敏度分析
  41. baseline = model.predict(X_test)
  42. sensitivities = {}#B站UP:white学长努力中
  43. for i in range(X_test.shape[1]):
  44. X_test_copy = X_test.copy()
  45. X_test_copy[:, i] += 0.1 * X_test_copy[:, i].std()
  46. perturbed = model.predict(X_test_copy)
  47. sensitivity = mean_squared_error(baseline, perturbed)
  48. sensitivities[i] = sensitivity
  49. print("Sensitivities:", sensitivities)
  50. #B站UP:white学长努力中
  51. filepath = 'train.csv'
  52. data = load_data(filepath)
  53. X_train, X_test, y_train, y_test = preprocess_data(data)
  54. clusters = perform_clustering(X_train)#B站UP:white学长努力中
  55. model = feature_importance(X_train, y_train)
  56. sensitivity_analysis(model, X_test)

问题 3.

基于问题 1 中指标分析的结果,请建立洪水发生概率的预测模型,从 20 个指标中选取合适指标,预测洪水发生的概率,并验证你们预测模型的准确性。如果仅用 5 个关键指标,如何调整改进你们的洪水发生概率的预测模型?

  1. import pandas as pd
  2. import numpy as np
  3. from sklearn.preprocessing import StandardScaler
  4. from sklearn.ensemble import RandomForestRegressor
  5. from sklearn.model_selection import train_test_split
  6. from sklearn.metrics import mean_squared_error, r2_score
  7. import matplotlib.pyplot as plt
  8. import seaborn as sns
  9. def load_data(filepath):
  10. data = pd.read_csv(filepath, encoding='gbk', sep=None, engine='python')
  11. data.dropna(how='all', inplace=True)
  12. return data
  13. def preprocess_data(data):
  14. data = data.iloc[:, 1:]
  15. data.fillna(data.median(), inplace=True)
  16. data = data.apply(pd.to_numeric, errors='coerce').fillna(data.median())
  17. scaler = StandardScaler()
  18. features = data.columns[:-1]
  19. X = scaler.fit_transform(data[features])
  20. y = data.iloc[:, -1]
  21. return train_test_split(X, y, test_size=0.2, random_state=42), features
  22. def feature_importance(X_train, y_train, feature_names):
  23. model = RandomForestRegressor(n_estimators=50, random_state=42)
  24. model.fit(X_train, y_train)
  25. importances = model.feature_importances_
  26. feature_importance_dict = dict(zip(feature_names, importances))
  27. print("Feature Importances:", feature_importance_dict)
  28. return model, importances
  29. def plot_feature_importance(importances, features):
  30. plt.figure(figsize=(12, 8))
  31. indices = np.argsort(importances)[::-1]
  32. plt.bar(range(len(importances)), importances[indices], align="center")
  33. plt.xticks(range(len(importances)), [features[i] for i in indices], rotation=45)
  34. plt.title('特征重要性')
  35. plt.show()
  36. def build_and_evaluate_model(X_train, X_test, y_train, y_test):
  37. model = RandomForestRegressor(n_estimators=50, random_state=42)
  38. model.fit(X_train, y_train)
  39. predictions = model.predict(X_test)
  40. mse = mean_squared_error(y_test, predictions)
  41. r2 = r2_score(y_test, predictions)
  42. print(f"模型评估结果:MSE = {mse}, R^2 = {r2}")
  43. return model, predictions
  44. def main():
  45. filepath = 'train.csv'
  46. data = load_data(filepath)
  47. (X_train, X_test, y_train, y_test), feature_names = preprocess_data(data)
  48. # 使用所有特征进行训练和评估
  49. model_all_features, importances = feature_importance(X_train, y_train, feature_names)
  50. plot_feature_importance(importances, feature_names)
  51. model_all, predictions_all = build_and_evaluate_model(X_train, X_test, y_train, y_test)
  52. # 选择前5个重要特征
  53. top_5_indices = np.argsort(importances)[::-1][:5]
  54. top_5_features = feature_names[top_5_indices]
  55. print(f"Top 5 Features: {top_5_features}")
  56. # 基于前5个特征重新进行训练和评估
  57. X_train_top5 = X_train[:, top_5_indices]
  58. X_test_top5 = X_test[:, top_5_indices]
  59. model_top5, predictions_top5 = build_and_evaluate_model(X_train_top5, X_test_top5, y_train, y_test)
  60. if __name__ == "__main__":
  61. main()

问题 4.

请查看源代码包

四、源代码和成品论文获取方式

成品论文:

http://app.niucodata.com/mianbaoduo/recommend.php?id=62066icon-default.png?t=N7T8http://app.niucodata.com/mianbaoduo/recommend.php?id=62066

思路与完整源代码:

http://app.niucodata.com/mianbaoduo/recommend.php?id=62064icon-default.png?t=N7T8http://app.niucodata.com/mianbaoduo/recommend.php?id=62064

内含思路讲解视频和完整代码(python,都可以单独运行),如有问题可以加Up的QQ(购买后即可看到)资料内容预计7月4日晚全部更新完成

更新1-4问基础代码使用tensorflow,今晚更新使用常规库的代码

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/代码探险家/article/detail/988443
推荐阅读
相关标签
  

闽ICP备14008679号