ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

数学建模竞赛数据预处理与探索性分析实战:以任务定价为例

数学建模竞赛数据预处理与探索性分析实战:以任务定价为例 1. 项目概述与核心价值2017年的全国大学生数学建模竞赛B题题目是“拍照赚钱”的任务定价。这道题在当时乃至现在都是数模竞赛中一个非常经典的“数据驱动决策”案例。它不像一些纯理论推导的题目而是给你一堆真实的、看似杂乱无章的数据让你去分析、建模最终解决一个实际的商业问题。第一小题通常是整个赛题的基石它的核心是数据预处理与探索性分析。很多队伍在这里就拉开了差距——处理得好后续建模顺风顺水处理得粗糙后面全是坑。这道题给了我们什么主要是一份任务数据包含了任务的位置信息经纬度、定价、以及是否被成功完成。我们的目标很明确分析这些定价的规律找出问题。听起来简单但魔鬼全在细节里。经纬度怎么可视化定价和地理位置有什么关系哪些任务定价“不合理”这些问题都需要通过严谨的数据分析来回答。这个过程不仅仅是套用几个统计函数更是培养我们面对真实数据时的“嗅觉”和“手感”。接下来我就以当年参赛者的视角复盘第一小题的完整思路与实操过程重点分享那些在标准答案里不会写但实际比赛中至关重要的“野路子”和避坑指南。2. 数据预处理清洗、转换与质量评估拿到数据的第一步绝不是急着画图或跑模型。就像厨师做菜前要洗菜、切配一样数据预处理决定了你这道“菜”的底味。2017年B题的数据虽然整体质量不错但也存在一些需要警惕的细节。2.1 数据加载与初步审查我们当时使用的是Python的Pandas库。第一步是加载数据并立刻查看数据的基本信息。import pandas as pd import numpy as np # 假设数据文件为 task_data.csv df pd.read_csv(task_data.csv) print(df.head()) # 查看前几行了解数据结构 print(df.info()) # 查看数据类型、非空值数量 print(df.describe()) # 查看数值型字段的统计摘要df.info()会告诉我们是否有缺失值。幸运的是国赛提供的数据通常比较干净但这一步绝不能省。df.describe()则重点关注定价比如列名是price的统计特征均值、标准差、最小最大值。这时一个关键动作是观察定价的分布范围。如果发现定价有0或者极大、极小的异常值比如别的任务都是50-100元突然冒出一个0.5元或1000元就需要高度警惕这可能是数据录入错误也可能是特殊的任务类型必须在后续分析中单独标记或处理。注意不要一看到异常值就武断地删除。在数学建模中异常值可能是问题的关键线索。例如一个定价极低的任务却完成了可能说明该地点有常驻人员顺手就做了一个定价极高的任务却失败了可能说明该地点极其偏僻或要求苛刻。正确的做法是先标记在后续的空间分析和建模中将其作为特殊案例深入研究。2.2 核心字段的转换与创建原始数据中的经纬度是进行分析的基石但直接使用经纬度计算距离很不方便单位是度。我们需要将其转换为更易于空间度量的形式。通常我们会计算每个任务到某个中心点如所有任务的地理中心或城市中心的平面投影距离。这里涉及到坐标投影的问题。一个在比赛中高效且足够精确的做法是使用Haversine公式计算球面距离或者使用UTM投影将经纬度转换为平面直角坐标x, y单位米。对于中国范围内的数据UTM投影更为精确。我们可以使用pyproj库来实现from pyproj import Proj # 假设数据大致位于东经110-120度北纬20-30度可选用UTM Zone 50N (适用于东经114-120度) utm_proj Proj(projutm, zone50, ellpsWGS84, preserve_unitsFalse) # 将经纬度转换为UTM坐标单位米 df[x], df[y] utm_proj(df[longitude].values, df[latitude].values)现在我们有了以米为单位的平面坐标x和y。接下来创建一个至关重要的衍生字段任务密度。我们可以以每个任务点为圆心一定半径如1公里或2公里内统计其他任务的数量。这个“密度”特征能直观反映该区域的竞争程度或需求集中度是解释定价规律的关键变量。计算密度可以使用scipy的KDTree进行快速空间检索from scipy.spatial import KDTree coords df[[x, y]].values tree KDTree(coords) radius 2000 # 2公里半径 df[density] tree.query_ball_point(coords, rradius, return_lengthTrue)2.3 数据质量评估与问题清单预处理最后一步是形成一份“数据质量报告”这能让你和你的队友对数据现状有统一认知。报告应包括缺失值情况确认无缺失。异常值清单列出定价、坐标的异常值如用箱线图判定并记录其ID。分布检查定价的分布是正态、偏态还是多峰这直接影响后续是否需要对定价取对数。关键衍生字段确认x,y,density字段已正确生成。完成这些你的数据才算“洗好了”可以进入下一阶段的探索分析。3. 探索性数据分析可视化与规律挖掘探索性数据分析是发现故事、形成假设的阶段。对于这道题EDA的核心是建立“位置-定价-完成情况”三者之间的直观联系。3.1 空间分布可视化定价的地理热图这是最直观的一步。我们需要将任务点画在地图上并用颜色表示其定价高低。可以使用matplotlib或seaborn的散点图但更专业的是使用folium或kepler.gl生成交互式地图。在静态报告中我们可以用散点图气泡图来近似。import matplotlib.pyplot as plt import seaborn as sns plt.figure(figsize(12, 10)) scatter plt.scatter(df[x], df[y], cdf[price], cmapviridis, sdf[density]/10, alpha0.6) plt.colorbar(scatter, label任务定价 (元)) plt.xlabel(UTM X坐标 (米)) plt.ylabel(UTM Y坐标 (米)) plt.title(任务定价与密度空间分布图气泡大小代表周围任务密度) plt.grid(True, alpha0.3) plt.show()通过这张图你能立刻发现一些模式定价高的点是否集中在某些区域这些区域是市中心、商业区还是偏远郊区定价和密度气泡大小有无负相关关系即任务越密集的地方单价是否越低3.2 定价与完成情况的关联分析题目数据中一定有“任务是否完成”的标记如finished。我们需要量化定价对完成率的影响。一个简单的分析是计算不同定价区间的完成率df[price_bin] pd.cut(df[price], bins10) # 将定价分为10个区间 completion_rate df.groupby(price_bin)[finished].mean().reset_index() print(completion_rate) plt.figure(figsize(10, 6)) plt.plot(completion_rate[price_bin].astype(str), completion_rate[finished], markero) plt.xlabel(定价区间) plt.ylabel(任务完成率) plt.title(不同定价区间的任务完成率) plt.xticks(rotation45) plt.tight_layout() plt.show()你可能会发现一个关键现象定价与完成率并非简单的线性正相关。可能存在一个“甜蜜点”定价过低无人问津定价过高也未必能提高完成率可能因为任务本身太难。这个拐点需要被找出来。3.3 多维特征交叉分析单变量分析不够我们需要交叉分析。例如密度 vs 定价绘制散点图并计算相关系数。预期是负相关密度高竞争大定价低。密度 vs 完成率密度高的地方完成率是否更高因为接单的人多空间聚类分析使用K-Means等算法对任务点进行聚类观察不同类簇的平均定价、完成率、密度特征。这能帮你发现“高价区”、“低价高完成区”、“低价低完成区”等模式。from sklearn.cluster import KMeans # 使用坐标和密度进行聚类 X df[[x, y, density]].values kmeans KMeans(n_clusters4, random_state42) # 假设分为4类 df[cluster] kmeans.fit_predict(X) # 分析每个簇的特征 cluster_summary df.groupby(cluster).agg({price:mean, finished:mean, density:mean}) print(cluster_summary)通过EDA你应该能回答第一小题的核心问题定价的规律是什么初步结论可能是定价呈现明显的空间异质性与任务密度强负相关且存在一个最优定价区间使得完成率最高。同时你会发现一些“离群点”即定价明显偏离其所在区域普遍规律的任务这些就是需要深入分析的“问题定价”任务。4. 问题定价的识别与量化分析探索性分析给了我们直觉现在需要用更严谨的方法来识别“问题定价”。这里的“问题”通常指两类定价明显偏低导致无人接单以及定价不合理偏高导致平台成本浪费。4.1 建立基准定价模型要判断一个定价是否“有问题”首先得知道“正常”的定价应该是多少。因此我们需要建立一个简单的基准模型来预测任务的“合理”定价。在第一小题不需要复杂的机器学习一个基于地理和密度的多元线性回归或地理加权回归就非常合适。多元线性回归模型from sklearn.linear_model import LinearRegression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score # 选取特征坐标(x,y)、任务密度(density) 还可以加入到市中心的距离等 X df[[x, y, density]] y df[price] X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42) model LinearRegression() model.fit(X_train, y_train) y_pred model.predict(X_test) print(f模型R^2分数{r2_score(y_test, y_pred):.3f}) print(f均方根误差RMSE{np.sqrt(mean_squared_error(y_test, y_pred)):.2f}) # 将预测值加入原数据框 df[predicted_price] model.predict(X)地理加权回归考虑到空间自相关性邻近地点定价相似GWR模型比普通OLS更合适。虽然计算复杂但在数模论文中提及并使用会是一个亮点。可以使用mgwr库。4.2 残差分析与问题点定位模型预测值predicted_price代表了在给定位置和密度下的“合理”定价。那么每个任务的实际定价price与预测定价的差值就是残差。df[residual] df[price] - df[predicted_price]残差 0实际定价高于模型预测的“合理”价。可能是定价过高也可能是该任务有其他未建模的附加价值如难度大、耗时长。残差 0实际定价低于“合理”价。这很可能就是导致任务失败的原因——定价过低缺乏吸引力。我们需要结合完成情况finished来分析残差高残差定价过高且未完成这不一定是个问题可能任务本身太难。高残差定价过高但完成了平台可能多付了钱这是成本浪费属于“问题定价”。低残差定价过低且未完成这是最典型的“问题定价”定价缺乏吸引力导致失败。低残差定价过低但完成了可能是“捡漏”或者执行者有其他动机如顺路但也提示定价有提升空间。我们可以定义一个简单的“问题指数”来量化problem_index -residual * (1 - finished)对于未完成的任务残差越低负得越多问题指数越大说明定价过低的问题越严重。4.3 空间自相关性与局部异常值检测定价在空间上可能不是独立的。莫兰指数可以检验定价是否存在空间聚集性。更精细的可以使用局部空间自相关分析如LISA聚类图来识别“高-高”高价聚集区、“低-低”低价聚集区以及空间异常点“高-低”或“低-高”即一个高价点被低价点包围或反之。这些空间异常点往往就是问题定价的候选者。可以使用esda和libpysal库来实现。import libpysal as lps from esda.moran import Moran_Local # 创建空间权重矩阵例如基于K近邻 w lps.weights.KNN.from_dataframe(df[[x, y]], k8) # 计算局部莫兰指数 local_moran Moran_Local(df[price], w) # 将结果分类高-高低-低高-低低-高不显著并加入df df[local_moran_cluster] local_moran.q将local_moran_cluster中的“高-低”和“低-高”类点筛选出来这些就是与其周边环境格格不入的定价点需要重点审视。5. 综合结论与优化建议的生成第一小题的最终产出不是一堆图表和数字而是一个清晰的、数据驱动的结论并为第二小题的定价模型优化提供方向。5.1 问题定价的综合性描述基于以上分析你需要总结出问题定价的几类典型模式模式一低估型失败。主要集中在城市外围或低密度区域其实际定价显著低于基于地理位置和竞争度预测的合理价格导致任务缺乏吸引力而失败。这是最主要的优化方向。模式二高估型浪费。少量位于中心城区或高密度区域的任务定价明显高于预测值但任务依然被完成。这表明平台支付了不必要的溢价存在成本优化空间。模式三空间异常型。个别任务与其周边环境的定价模式截然相反如“孤岛式”高价或“洼地式”低价这些可能是数据误差也可能是特殊案例需结合任务具体说明如果有的话进一步判断。5.2 可视化呈现与报告整合将你的发现用一张综合仪表盘图呈现出来会非常出彩。例如使用子图子图1定价地理热图用红圈高亮标注“问题定价”任务点模式一和模式二。子图2残差实际价-预测价与完成率的散点图用象限划分出上述四种情况。子图3局部莫兰指数LISA聚类图展示空间异常点。 配合简洁的图注让评委一眼就能抓住你的核心发现。5.3 对后续建模的指导性建议第一小题的结论必须自然地引出第二小题的工作。你的建议应该具体、可操作模型输入特征EDA证实了“任务密度”和“空间位置”是影响定价的关键因素必须作为核心特征纳入定价模型。模型选择由于存在空间异质性建议第二小题采用能够处理空间效应的模型如地理加权回归、空间误差模型或引入网格化、区域聚类作为控制变量。优化目标定价模型不应只追求预测准确而应是一个“成本-完成率”的权衡优化模型。可以定义目标函数为“在保证整体完成率不低于某阈值的前提下最小化总定价成本”。第一小题识别的“高估型浪费”点就是成本下降的潜在空间“低估型失败”点则是完成率提升的突破口。特殊案例处理对于识别出的空间异常点或极端值建议在第二小题中考虑设立特殊规则或单独建模而不是用一个全局模型去硬套。6. 常见问题与实战避坑指南回顾整个第一小题的解题过程有几个坑是很多队伍包括我们当时都容易踩进去的。6.1 坐标处理与距离计算的陷阱坑点直接使用经纬度计算欧氏距离。经纬度一度在不同的纬度上对应的实际距离是不同的赤道上最长向两极递减。用这种“错误距离”算出的密度和任何空间分析都是不准确的。避坑务必进行坐标投影转换如UTM。如果时间紧迫或编程实现有困难至少使用Haversine公式计算球面距离。在论文中必须明确说明你采用了何种方法处理地理坐标这是专业性的体现。6.2 过度依赖复杂模型与“黑箱”算法坑点一上来就用随机森林、XGBoost甚至神经网络去预测定价并把模型精度作为第一小题的全部。这犯了本末倒置的错误。避坑第一小题的核心是“探索”和“解释”而不是“预测”。简单透明的模型如线性回归及其残差分析比一个高精度但无法解释的“黑箱”模型更有价值。你的目标是理解数据而不是赢得Kaggle比赛。复杂模型可以留到第二小题用于最终的定价优化。6.3 忽略统计检验与结论的武断坑点看到“定价高密度低”的散点图趋势就直接下结论说“定价与密度负相关”但没有给出任何统计检验如皮尔逊相关系数及其p值。避坑任何规律性的陈述都要有统计检验支撑。“通过散点图观察我们怀疑定价与密度存在负相关关系。为验证这一点我们计算了二者的皮尔逊相关系数结果为-0.65且p值小于0.001在99.9%的置信水平下显著。这证实了我们的观察。”这样的表述才严谨。6.4 可视化图表的“美颜”过度或不足坑点图表要么过于花哨颜色混乱信息过载要么过于简陋就是matplotlib默认样式看不清细节。避坑遵循“简洁即美”的原则。使用清晰的色系如viridis, plasma确保颜色有逻辑如用连续色系表示价格高低。添加必要的图例、坐标轴标签和标题。在多子图布局中保持风格统一。一张好的图表应该让读者在10秒内抓住核心信息。6.5 与后续小题的衔接生硬坑点第一小题的结论写成了孤立的分析报告与第二、三小题毫无关联。避坑在每一部分的结尾尤其是综合结论部分都要有意识地“抛砖引玉”。例如“上述分析表明基于地理位置和任务密度的线性模型已能解释大部分定价变异但残差分析揭示了系统性偏差这提示我们在第二小题中需要引入更复杂的非线性项或交互项。” 这样整篇论文就形成了一个连贯的故事线。第一小题是整个赛题的“地基”地基打得牢后面的建模“高楼”才能稳。它考验的是参赛者的数据基本功、逻辑思维和讲故事的能力。把数据背后的故事讲清楚把问题精准地定位出来你的第一小题就成功了一大半。记住评委想看到的不是你用了多高级的算法而是你发现问题、分析问题、清晰表达问题的完整逻辑链条。
返回列表