从数学建模到工程实践:人类活动识别(HAR)全流程解析 📅 发布时间:2026/8/23 19:57:59 👁 浏览次数: 1. 项目概述从一道赛题看人类活动识别的核心挑战刚拿到2022年小美赛C题“人类活动分类”这个题目时很多同学的第一反应可能是这不就是个分类问题吗用个机器学习模型比如SVM或者随机森林把数据喂进去训练一下不就完事了如果你也这么想那可能从一开始就低估了这道题的深度和它背后所代表的整个研究领域的复杂性。这道题之所以能成为一道经典的建模赛题恰恰是因为它完美地封装了从现实世界模糊问题到清晰数学模型再到工程化解决方案的全链条挑战。它考察的绝不仅仅是你会不会调包调用几个分类算法而是你如何定义“活动”、如何获取和预处理数据、如何从噪声中提取有效特征、如何选择并解释模型以及最终如何评估一个分类系统在真实场景下的可用性。人类活动识别英文叫Human Activity Recognition简称HAR听起来很高大上但其实离我们非常近。你手机里的健康App记录你走了多少步、睡了多久智能手表提醒你“该起来活动一下了”甚至一些家庭安防摄像头能判断画面里的人是正常行走还是突然摔倒——这些功能的背后核心都是HAR技术。而这道赛题就是把这样一个前沿且实用的研究方向抽象成了一个经典的、有明确数据边界和评价指标的数学建模问题。它要求参赛者扮演一个算法工程师的角色去构建一个能够根据传感器数据可能是加速度计、陀螺仪等自动判别佩戴者正在进行何种活动如走路、跑步、上下楼梯、坐着、站着等的系统。这道题适合所有对数据科学、机器学习应用感兴趣的同学尤其是那些已经学过一些基础模型如KNN、决策树但还没经历过完整项目实战的朋友。通过拆解这道题你不仅能巩固分类算法的知识更能学到一整套数据驱动的建模方法论如何将业务问题转化为数学问题如何处理现实世界中“脏乱差”的数据如何设计实验验证模型的有效性以及如何用严谨的论文呈现你的思考过程。接下来我就结合自己多次带队参赛和工业界项目实践的经验带你从头到尾拆解这道题我会重点讲清楚每个环节“为什么”要这么做以及那些容易踩坑的“实操细节”。2. 问题拆解与建模思路设计面对“人类活动分类”这样一个题目第一步也是最关键的一步不是急着找代码而是彻底想清楚我们要解决的具体是什么问题题目给出的条件和约束是什么只有把问题定义清晰了后续所有工作才有正确的方向。2.1 核心需求与问题定义通常这类赛题会提供一个数据集。我们假设数据集包含多个受试者在身体不同部位如手腕、腰部、脚踝佩戴传感器所采集的时序数据每个数据样本对应一段固定时间窗口例如2秒内的传感器读数并带有活动类型的标签如“Walking”, “Sitting”, “Upstairs”。那么我们的核心任务就非常明确了构建一个分类模型该模型能够根据一段新的、未标记的传感器时序数据准确预测其对应的人类活动类型。但这只是表面任务。深层需求包括高精度分类准确率Accuracy要高这是最直接的评估指标。强鲁棒性模型对于不同个体、不同传感器佩戴位置、不同数据采集环境下的差异应具有一定的适应性不能只在训练集上表现好。可解释性在某些场景下虽然深度学习模型可能精度更高但如果能用决策树、逻辑回归等模型达到可接受的精度其模型本身提供的特征重要性或决策规则对于理解活动特征更有价值。低计算成本考虑到最终可能部署在手机、手表等嵌入式设备上模型不宜过于复杂推理速度要快。基于这些需求我们的建模思路可以形成一个清晰的流水线数据预处理 - 特征工程 - 模型选择与训练 - 模型评估与优化。这个流水线是解决绝大多数HAR问题乃至通用机器学习问题的基本框架。2.2 技术路线选型与权衡确定了流水线接下来就要为每个环节选择具体的技术方案。这里没有唯一的“正确答案”只有针对不同侧重点的“权衡之选”。方案A传统机器学习流水线这是最经典、最可控也最适合数学建模竞赛展示清晰逻辑的路线。核心手动从原始时序信号中提取大量统计特征时域、频域然后使用经典分类器如随机森林、XGBoost、SVM进行训练。优点可解释性强特征含义明确模型如决策树可以生成规则。对数据量要求相对较低在特征设计得当的情况下几千个样本也能取得不错效果。计算效率高训练和预测速度快。非常适合竞赛每一步都可以详细阐述原理展示你的思考过程。缺点特征工程依赖经验需要领域知识来设计有效的特征这是一个试错过程。可能无法捕捉深层时序模式手动特征可能遗漏原始信号中的复杂关联。方案B深度学习端到端学习这是目前工业界前沿的主流方向尤其是基于卷积神经网络或循环神经网络的方法。核心将原始时序数据或进行最小化预处理如归一化直接输入神经网络如1D-CNN, LSTM, CNN-LSTM混合模型让网络自动学习特征表示并进行分类。优点省去繁琐的特征工程模型自动学习最优特征。潜力上限高在大规模数据上深度学习模型往往能达到比传统方法更高的精度。能更好地建模时序依赖LSTM等结构专为序列数据设计。缺点需要大量数据参数多容易过拟合小数据集上可能反而不如传统方法。黑盒模型可解释性差难以说清模型为什么做出某个判断。计算成本高训练耗时对硬件有要求。在竞赛中如果只是调包搭建一个复杂网络而不深入理解其原理和针对性的结构调整在论文阐述上会显得深度不足。对于小美赛这类竞赛我的强烈建议是以方案A为主方案B作为对比和升华。原因有三第一竞赛数据集通常不会特别巨大传统方法完全有发挥空间第二竞赛论文看重逻辑链条的完整性和你对问题的理解深度手动特征工程和模型选择的过程正是展示你思考的舞台第三你可以用一个精心调优的随机森林作为基线模型然后尝试一个简单的1D-CNN作为对比分析两者在不同活动上的表现差异这能让你的论文内容更丰满、更有层次。3. 数据预处理与特征工程实战解析数据决定了模型性能的上限而模型和算法只是逼近这个上限。在HAR中原始传感器数据往往是嘈杂且冗余的直接使用效果极差。因此预处理和特征工程是提升模型性能最关键、最有效的步骤没有之一。3.1 数据预处理为分析打下坚实基础拿到数据通常是.csv或.txt文件后第一步不是跑模型而是“看”数据。数据加载与探查用Pandas加载数据查看数据维度、列名、数据类型。检查是否有缺失值isnull().sum()标签分布是否均衡value_counts()。一个严重失衡的数据集会误导模型。噪声过滤加速度计、陀螺仪数据包含高频噪声。通常采用低通滤波器如Butterworth滤波器来平滑信号保留人体活动的主要频率成分一般集中在0-20Hz。你可以这样操作from scipy.signal import butter, filtfilt def butter_lowpass_filter(data, cutoff_freq, fs, order4): nyquist 0.5 * fs # 奈奎斯特频率 normal_cutoff cutoff_freq / nyquist b, a butter(order, normal_cutoff, btypelow, analogFalse) y filtfilt(b, a, data) # 使用filtfilt实现零相位滤波 return y # 假设采样频率fs50Hz截止频率设为10Hz filtered_acc_x butter_lowpass_filter(acc_x, cutoff_freq10.0, fs50.0)注意filtfilt比普通的lfilter更好因为它没有相位延迟处理后的信号在时间上是对齐的。信号分割原始数据是长序列我们需要将其切分成固定长度、有重叠或无重叠的窗口例如2秒一个窗口50Hz采样率就是100个数据点一个窗口。重叠窗口如50%重叠可以增加样本量缓解数据不足但也会引入样本间的相关性。def create_segments(data, labels, window_size, step_size): segments [] segment_labels [] for start in range(0, len(data) - window_size, step_size): end start window_size segment data[start:end] label stats.mode(labels[start:end])[0][0] # 取窗口内众数作为该窗口标签 segments.append(segment) segment_labels.append(label) return np.array(segments), np.array(segment_labels)归一化为了避免某些数值范围大的特征如加速度幅值主导模型训练需要对特征进行归一化。通常使用针对每个特征维度的Z-score标准化减均值除以标准差。切记用训练集的均值和标准差去标准化测试集这是防止数据泄露的铁律。from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) # 在训练集上拟合scaler X_test_scaled scaler.transform(X_test) # 用训练集的参数转换测试集3.2 特征工程从信号中提炼“精华”这是传统方法的核心也是最能体现你思考和创造力的地方。好的特征应该能最大程度地区分不同活动。我们从时域、频域和时频域三个角度来挖掘。时域特征直接从信号幅值随时间变化中提取。基本统计量均值、方差、标准差、最大值、最小值、范围。形态特征信号曲线下面积、过零点率、峰谷计数。相关性三轴加速度x, y, z之间的相关系数。走路时三轴运动是协调的而打字可能主要在于腕的特定轴。自定义特征例如静止状态下加速度矢量和应接近重力加速度g运动时其方差会增大。可以计算body_acc sqrt(ax^2ay^2az^2) - g的统计量。频域特征通过快速傅里叶变换将信号转换到频率域提取周期性信息。FFT变换frequencies, magnitudes np.fft.rfft(signal), np.abs(np.fft.rfft(signal))频域统计量频谱熵信号复杂度、频谱重心主要频率成分、频谱幅值的均值、方差等。频带能量将频谱划分为几个频带如0-5Hz 5-10Hz等计算每个频带的能量占比。不同活动的主导频率不同。时频域特征结合时间和频率信息适合非平稳信号。小波变换比FFT更能捕捉信号的局部频率特征。可以提取小波系数的统计量作为特征。实操心得不要盲目堆砌特征提取几十上百个特征很容易但其中很多可能是冗余或无关的。这会导致“维度灾难”增加计算负担还可能降低模型泛化能力。一定要做特征选择在特征送入模型前使用sklearn.feature_selection中的方法如基于树模型的特征重要性、递归特征消除RFE筛选出最重要的特征子集。你会发现可能只需要20%的特征就能达到95%的精度。为不同传感器和轴分别提取特征腰部加速度计和手腕加速度计反映的信息不同分别提取再合并能提供更丰富的视角。4. 模型构建、训练与评估全流程特征准备好了我们就可以开始搭建和训练模型了。这里我们以经典的随机森林为例因为它效果好、不易过拟合、能输出特征重要性非常适合作为基线模型。4.1 模型选择与训练from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split, cross_val_score from sklearn.metrics import classification_report, confusion_matrix # 1. 划分训练集和测试集如果官方没提供 X_train, X_test, y_train, y_test train_test_split(features, labels, test_size0.2, random_state42, stratifylabels) # 使用stratify确保训练测试集标签分布一致 # 2. 初始化模型 # 关键超参数n_estimators树的数量, max_depth树的最大深度, min_samples_split节点分裂所需最小样本数 rf_model RandomForestClassifier(n_estimators200, max_depth15, min_samples_split5, random_state42, n_jobs-1) # n_jobs-1使用所有CPU核心加速 # 3. 训练模型 rf_model.fit(X_train, y_train) # 4. 查看特征重要性 importances rf_model.feature_importances_ indices np.argsort(importances)[::-1] # 可以将特征名和重要性对应打印出来分析哪些特征最有用为什么选择这些参数n_estimators200树越多模型越稳定性能通常越好但计算量也越大。可以通过学习曲线观察准确率随树数量增加的变化在收益变小时停止。max_depth15限制树深度是防止过拟合的关键手段。太深会记住训练集噪声太浅则学不到模式。需要交叉验证调优。min_samples_split5节点至少需要5个样本才继续分裂也是防止过拟合。random_state固定随机种子确保结果可复现这对竞赛和实验至关重要。4.2 模型评估不止看准确率模型训练完在测试集上一测准确率95%是不是就大功告成了远远不是。一个全面的评估需要多维度审视。基础指标使用classification_report查看精确率、召回率、F1-score。对于不平衡数据集宏观平均F1macro-F1比准确率更有参考价值。y_pred rf_model.predict(X_test) print(classification_report(y_test, y_pred))混淆矩阵这是发现模型弱点的“显微镜”。它能清晰显示模型具体在哪些类别上容易混淆。import seaborn as sns cm confusion_matrix(y_test, y_pred) sns.heatmap(cm, annotTrue, fmtd, cmapBlues) plt.xlabel(Predicted) plt.ylabel(True)典型问题你很可能发现“上楼”和“下楼”容易互相误判“坐着”和“站着”在传感器数据不典型时也难区分。这非常正常也是你后续优化模型和分析的重点。交叉验证为了更稳健地估计模型性能避免因一次数据划分带来的偶然性必须使用K折交叉验证。cv_scores cross_val_score(rf_model, features, labels, cv5, scoringaccuracy) print(fCV Accuracy: {cv_scores.mean():.4f} (/- {cv_scores.std()*2:.4f}))交叉验证的均值和方差能告诉你模型性能是否稳定。4.3 模型优化与调参基线模型有了下一步就是优化。这里主要两个方向特征优化和模型超参数优化。特征优化根据随机森林输出的特征重要性剔除重要性极低如接近0的特征重新训练模型观察性能变化。有时特征减少后精度反而微升因为模型更专注了。超参数调优手动调参效率低我们可以用网格搜索或随机搜索。from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [100, 200, 300], max_depth: [10, 15, 20, None], min_samples_split: [2, 5, 10] } grid_search GridSearchCV(RandomForestClassifier(random_state42), param_grid, cv3, scoringaccuracy, n_jobs-1, verbose1) grid_search.fit(X_train_scaled, y_train) print(fBest parameters: {grid_search.best_params_}) print(fBest CV score: {grid_search.best_score_:.4f})注意网格搜索非常耗时尤其是参数组合多的时候。可以先进行大范围粗调确定最优区间后再精细调整。verbose1可以让你看到搜索进度。5. 进阶探索与方案对比当你的传统机器学习流水线已经调优到不错的状态后为了提升论文的深度和广度可以进行一些进阶探索。5.1 尝试深度学习模型我们可以构建一个简单的1D-CNN来作为对比。CNN能自动捕捉信号的局部模式。from tensorflow.keras import layers, models # 假设输入形状为 (window_size, num_channels)例如 (100, 3) 代表100个时间点3个轴 model models.Sequential([ layers.Input(shape(100, 3)), layers.Conv1D(filters64, kernel_size3, activationrelu), layers.MaxPooling1D(pool_size2), layers.Conv1D(filters128, kernel_size3, activationrelu), layers.GlobalAveragePooling1D(), # 替代Flatten参数更少对时序长度不敏感 layers.Dense(64, activationrelu), layers.Dropout(0.5), # 防止过拟合 layers.Dense(num_classes, activationsoftmax) ]) model.compile(optimizeradam, losssparse_categorical_crossentropy, metrics[accuracy]) history model.fit(X_train_cnn, y_train, validation_split0.2, epochs50, batch_size32, verbose1)关键点GlobalAveragePooling1D比Flatten更适合可变长度输入且能减少参数。一定要使用Dropout和validation_split来监控过拟合。深度学习模型在小数据集上容易过拟合如果效果不如随机森林不必气馁可以尝试数据增强如添加噪声、时间拉伸或使用预训练模型如果领域相关。5.2 集成学习与模型融合如果单个模型性能遇到瓶颈可以尝试集成学习。除了随机森林本身是一种Bagging集成你还可以Stacking用几个不同的基模型如SVM、KNN、决策树的预测结果作为新特征训练一个次级模型元模型如逻辑回归来做最终预测。这往往能提升少许性能但复杂度大增。Voting对多个训练好的模型如RF、SVM、CNN的预测结果进行硬投票少数服从多数或软投票平均概率。实操心得在竞赛中如果时间有限优先把单个模型如随机森林做到极致而不是追求复杂的集成。一个充分调优的RF通常已经非常强大。集成是锦上添花而不是雪中送炭。6. 结果分析与论文撰写要点模型做完了最后一步是把你的工作清晰、专业地呈现出来。论文是评审专家了解你工作的唯一窗口。6.1 如何系统地展示结果可视化是关键特征重要性柱状图展示Top-20最重要的特征这能直接证明你特征工程的有效性。混淆矩阵热力图清晰展示模型的分类弱点并针对性地进行分析例如“我们发现模型在‘上楼’和‘下楼’活动上存在12%的相互误判率分析原因是两者在垂直方向的加速度模式非常相似未来可考虑引入气压计数据来获取高度变化信息以进行区分。”。学习曲线绘制训练集和验证集的准确率/损失随训练轮次对于深度学习或树数量对于RF的变化图用以判断模型是否过拟合或欠拟合。t-SNE/PCA降维图将高维特征降至2维或3维进行可视化观察不同活动类别的样本在特征空间中是否能够被较好地区分开。这能从几何角度解释模型为什么有效。量化对比制作一个清晰的表格对比不同模型如基线模型、调优后的RF、CNN在测试集上的各项指标准确率、宏F1、加权F1等。模型准确率宏平均F1训练时间备注随机森林基线92.5%0.92315s特征未选择随机森林调优后95.8%0.95618s使用网格搜索调参1D-CNN94.2%0.9402min存在轻微过拟合6.2 论文核心章节逻辑一篇好的数模论文结构比文采更重要。摘要用一段话浓缩整个工作针对什么问题、用了什么方法数据预处理、特征工程、XX模型、得到了什么结果关键指标、有什么结论和亮点。务必精炼、包含所有关键信息。问题重述与分析不要照抄题目要用自己的话分析问题的背景、核心任务、难点和解决思路。模型假设与符号说明列出合理的假设如“假设传感器佩戴位置固定”、“忽略轻微的环境电磁干扰”并定义文中用到的主要数学符号。数据处理与特征工程这是最能体现工作量的部分。详细说明每一步处理的理由为什么滤波为什么用这个窗口大小为什么提取这些特征。配上关键代码片段或流程图。模型建立与求解介绍所选模型的原理如随机森林的基本思想、为什么适合本问题、以及具体的实现和调参过程。可以简述对比的其他模型。结果分析与验证展示上一步中的各种图表和表格并配以深入的分析。不要只说“准确率高”要分析“为什么高”以及“为什么在这里会出错”。模型评价与推广客观评价自己模型的优点精度高、鲁棒性好和缺点对某类活动识别差、计算成本等并提出可行的改进方向如融合更多传感器、使用更复杂的网络结构。这部分体现了你的批判性思维。参考文献与附录规范引用附录可以放核心代码。最后的叮嘱数学建模竞赛是团队合作也是时间管理艺术。合理分工一人主攻建模与算法、一人负责数据处理与实验、一人专注论文写作与图表、定期同步、留出足够时间撰写和修改论文这些和算法本身一样重要。人类活动分类这道题就像一个微缩的AI产品开发流程走完这一遍你对如何用数据驱动的方法解决一个实际问题会有完全不一样的理解。希望这份超详细的拆解能帮你少走弯路祝你在比赛中取得好成绩