可穿戴传感器人类活动识别:从数据切分到端侧部署
2026/9/17 21:55:33 网站建设 项目流程

时间序列分类里有一类任务特别适合练手,也特别容易做虚,那就是基于可穿戴传感器的人类活动识别。你手里拿到的是一串三轴加速度计读数,50Hz 采了大半天,标签只有走、跑、上楼、下楼、坐、站几类,怎么把它变成一个真能跑起来的深度学习模型,这件事的门槛从来不在网络结构上,而在窗口切分、标签对齐和评估设计这三块。这篇是系列里的第 19 篇,我打算把人类活动识别这条线从数据到端侧部署完整捋一遍,重点讲清楚各种深度学习模型在这个任务上的真实适用面,哪些是纸面好看、哪些是真能落地,以及我复现过程中踩过的那些坑。不管你手上是公开数据集还是自己拿手机采的裸数据,看完应该都能直接照着搭一套流程出来。

1. 传感器信号到分类样本:人类活动识别任务的真实边界

很多人对这个任务的第一印象是"不就是个多变量时间序列分类嘛",把数据往模型里一塞就完事。真做下来你会发现,模型可能只占整个工作量的三成,剩下七成全花在把原始信号变成"干净的、无泄漏的"样本上。这一章我先把这件事讲透,因为后面所有模型效果的好坏,都建立在这个地基上。

1.1 滑动窗口切分的三个隐性参数

加速度计输出的是连续时序,分类模型需要的是定长片段,中间靠滑动窗口衔接。窗口长度、步长、以及窗口内标签纯度阈值,这三个参数决定了你的数据集长什么样。

窗口长度本质上是在"信息量"和"时效性"之间做取舍。窗口太短,一个完整的步态周期都装不下,走路和上楼梯在频域上几乎分不开;窗口太长,跨活动边界的概率飙升,模型学到的是"混合体"。经验上,采样率 50Hz 时 2.56 秒窗口(128 个采样点)是被验证过很多次的甜点值,UCI HAR 就是这么切的,50% 重叠,步长 1.28 秒。采样率高的话按时间长度折算,比如 100Hz 采的数据,同样的 2.56 秒就是 256 个点。

步长决定样本量和冗余度。50% 重叠意味着样本量翻倍,训练时看起来收敛更快,但相邻窗口高度相关,验证集如果跟着一起重叠,指标就会虚高。我的一般做法是训练集用 50% 重叠扩样本,验证和测试切分时保证窗口之间不重叠,或者至少保证同一次连续采集的记录不会同时出现在训练和测试里。

标签纯度是被最多人忽略的一个。原始标注通常在毫秒级时间戳上打点,活动切换的那一两秒往往是"灰区",一个人从坐到站中间有个过渡姿态。如果你按窗口起点对应的标签直接赋值,就会往训练集里灌一堆噪声样本。我的做法是要求窗口内某个标签占比超过 80% 才保留,否则直接丢弃。这个丢弃比例在不同数据集上差别很大,PAMAP2 这种活动切换频繁的数据集,丢掉 15% 到 20% 的窗口很正常,别心疼。

import numpy as np def sliding_window(x, y, win=128, stride=64, purity=0.8): # x: (T, C) 连续信号;y: (T,) 逐采样点标签 X, Y = [], [] for s in range(0, len(x) - win + 1, stride): seg, lab = x[s:s + win], y[s:s + win] vals, cnts = np.unique(lab, return_counts=True) if cnts.max() / win < purity: continue # 灰区窗口直接扔 X.append(seg) Y.append(vals[cnts.argmax()]) return np.stack(X), np.array(Y)

1.2 标签对齐与灰区活动的处理

除了窗口纯度,还有两个时间维度的坑。第一个是采集设备与标注设备之间的时钟偏移,很多自采数据集用手机采信号、另一台设备做标注,两边时钟不同步个几百毫秒是常事。校验方法很简单,让受试者做一个明确的动作比如用力跺脚,在信号上找那个尖峰,跟标注时间戳对一下,差多少就整体平移多少。

第二个是"持续性活动"和"瞬时活动"的混标。像跳跃、开门这种瞬发动作,持续时间可能只有一秒出头,窗口一滑就淹没在相邻的静坐里。这类类别要么单独用更短的窗口处理,要么在采样阶段就控制重复次数,靠数据量硬堆。我试过在 PAMAP2 上把跳跃类别的窗口长度单独降到 64,用两套窗口并行训练再融合,macro-F1 能提两三个点,代价是工程复杂度上去了,值不值得看你的场景。

1.3 公开数据集的实际差异对照

谁也不太可能一上来就自采几千条样本,公开数据集是必经之路。但不同数据集的采集协议差得很远,跨数据集迁移时经常直接掉十几个点,所以选之前得先看清楚它们的底细。

数据集采样率受试者活动数传感器配置实际使用中的注意点
UCI HAR50Hz306腰部手机 acc+gyro官方已切好窗,拿来当基线最快
WISDM20Hz366裤兜手机 acc类别极不均衡,走路占了近四成
PAMAP2100Hz918三个 IMU + 心率切换频繁,灰区窗口多,受试者少
Opportunity30Hz417全身 72 个传感器标注粒度极细,适合做复杂任务
HAPT50Hz3012腰部手机 IMU含坐站转换,类别更细

这里有个判断标准:受试者数量少于 10 的数据集(比如 PAMAP2、Opportunity),做跨人评估时方差会非常大,某一个人表现特别差就能把整体指标拉下去三四个点,报告结果时一定要给标准差,不能只报一个均值。

2. 基线不打牢,后面全是自欺欺人

我见过太多人上来就往 Transformer 上冲,结果连一个跑通的手工特征加 SVM 基线都没有,最后模型准确率 95%,说不清是模型厉害还是数据泄漏。基线不是形式主义,它是你后面所有改进的参照系,也是发现数据问题的第一道探针。

2.1 手工特征管线的经典结构

传统管线分三步:窗口切分、特征提取、分类器。特征是关键,常用的一共就这么几类,时域上的均值、标准差、峰峰值、均方根、偏度峰度、过零率、相关性;频域上做 FFT 之后取能量、谱熵、主频;有些工作还会加小波包分解后的各子带能量。

这些特征加起来在 UCI HAR 上就是那经典的 561 维向量。用随机森林或者 SVM 在这套特征上跑,subject-wise 准确率通常能到 85% 到 90% 区间。这个数字很重要,它意味着如果你精心设计的深度模型拿不到 90% 以上,那大概率是数据处理出了问题,而不是模型不够深。

我自己的基线流程固定成三段:先跑一个只用统计特征的逻辑回归,看看线性可分性;再跑随机森林,看非线性特征的增益;最后跑 DeepConvLSTM,看时序建模的增益。三个数字摆在一起,你就能判断这个任务到底难在哪。

2.2 DeepConvLSTM为什么是绕不开的对照点

2016 年提出的 DeepConvLSTM 几乎成了这个领域的默认基线,结构极其简单:四层一维卷积负责提局部时序模式,两层 LSTM 负责跨窗口的时序依赖,最后接全连接分类。它的参数规模不大,几十万量级,在桌面 CPU 上都能训得动。

import torch, torch.nn as nn class DeepConvLSTM(nn.Module): def __init__(self, n_ch, n_cls, hid=128): super().__init__() self.conv = nn.Sequential( nn.Conv1d(n_ch, 64, 5, padding=2), nn.ReLU(), nn.Conv1d(64, 64, 5, padding=2), nn.ReLU(), nn.Conv1d(64, 64, 5, padding=2), nn.ReLU(), nn.Conv1d(64, 64, 5, padding=2), nn.ReLU(), ) self.lstm = nn.LSTM(64, hid, batch_first=True) self.fc = nn.Linear(hid, n_cls) def forward(self, x): # x: (B, C, T) h = self.conv(x).permute(0, 2, 1) # (B, T, 64) h, _ = self.lstm(h) return self.fc(h[:, -1])

它之所以值得当基准,一是实现成本低,二是效果稳定,三是在很多数据集上的表现跟后面那些花里胡哨的注意力模型差距并没有想象中大,通常就两三个点。当你看到某篇论文声称自己的模型比 DeepConvLSTM 高十个点,第一反应应该是去查它的评估协议,而不是急着复现。

2.3 我踩过的数据泄漏坑

说个真实经历。最早做自采数据时,我按 8:2 随机切分窗口,模型在测试集上 98%,高兴了没两天。后来严格改成按受试者划分,同一批数据直接掉到 76%。原因很简单,重叠窗口让相邻样本几乎完全相同,随机切分时训练集和测试集共享了大量"孪生样本",模型背下了受试者的个人特征而不是活动模式。

判断有没有泄漏,有个粗暴的办法:看验证曲线和训练曲线是不是几乎完全重合。如果两者贴着走而且都极低,八成是泄漏。另一个办法是统计训练集和测试集窗口的欧氏距离分布,如果存在大量距离接近零的样本对,说明切分不干净。这件事没有捷径,评估协议必须在动手写模型之前就定死。

3. 时序骨干网络选型:CNN、RNN、TCN与注意力的适用面

搞清楚基线之后,才轮到挑骨干网络。这个任务的输入有个鲜明特点:序列不长(常见 128 到 512 个点)、通道不多(三到九个为主)、类别间差异主要体现在局部波形的形态和节律上。理解了这几点,很多选型问题就不用纠结了。

3.1 一维卷积的感受野怎么算

CNN 是这个任务的性价比之王。原因在于活动信号里的判别信息大量来自局部形态,比如一个步态周期中加速度的上升沿和下降沿,这些东西卷积核几个点就能捕捉到。层数堆到三四层,卷积核都用 5,感受野也就十几个点,看似覆盖不了整个 2.56 秒,但配合池化或者步幅卷积,等效感受野会迅速扩大。

感受野的计算公式是:RF = 1 + Σ(kᵢ - 1) × Π(stride)。假设四层卷积核都是 5、步幅都是 1、每层后面接一个大小 2 的最大池化,那么逐层感受野大约是 5、18、44、96,到第四层就已经能覆盖 96 个采样点,接近两个步态周期。如果你不做池化,纯堆卷积,想覆盖 128 个点需要将近 32 层,参数量和过拟合风险都会失控。所以池化或者空洞卷积在这个任务里几乎是必需品。

3.2 循环结构的代价与双向结构的误用

LSTM 的价值在于建模跨时间片的依赖,比如"这个人前两秒在走,现在开始加速,可能是要跑起来了"。但代价很实在:一是慢,序列必须串行处理,GPU 利用率上不去;二是难训,梯度路径长,得靠 LayerNorm 和梯度裁剪伺候。

更值得说的是双向 LSTM 的误用。很多论文默认用 BiLSTM,在离线数据集上确实能涨点,但那是作弊——它用了未来信息。你要是做实时识别,在 t 时刻不可能知道 t+1 秒的数据。做端侧部署时,BiLSTM 直接就得拆掉,换成单向。我一般建议:离线分析任务可以用双向,但一定要在论文里说清楚这是离线设置;只要沾上实时、可穿戴设备、在线推理这些词,一律单向。

3.3 自注意力在短窗口上的真实表现

Transformer 那套自注意力机制搬到 HAR 上,效果比很多人预期的要平淡。原因不复杂:自注意力的优势是捕捉长距离依赖,而 HAR 的窗口本身就只有一两百个点,卷积堆几层就能覆盖,长距离依赖的需求并不强烈。而且 Transformer 少了卷积的归纳偏置,在样本量有限的 HAR 数据集上更容易过拟合。

实际复现下来,纯 Transformer 相比调好的 CNN 基线,收益通常在 1 到 3 个点之间,参数量翻几倍,推理延迟也上去了。真正有效的位置是把自注意力当成卷积的补充而不是替代:用卷积做局部特征提取,在最后一两层加一个轻量的多头注意力做全局聚合,或者用卷积位置编码替代正弦编码。这类混合结构我在几个数据集上都试过,效果比纯卷积稳定一点,代价可控。

3.4 InceptionTime直接搬过来的效果

如果不想自己从零设计,来自时间序列分类领域的 InceptionTime 是个现成的强基线。它把 GoogLeNet 的多尺度思想搬到一维:同一条输入并行走多个不同核长的卷积(9、19、39),再拼接,外面套残差连接,最后集成五个模型取平均。多尺度这一点恰好贴合 HAR 的特点,不同活动的特征尺度本来就不一样,走路是低频慢节奏,跳跃是高频突变。

直接搬过来的注意点是输入归一化方式。InceptionTime 的原版实现对每条序列做 z-score 标准化,这在单变量数据上没问题,但 HAR 是多通道的,如果对每个通道独立标准化,会破坏通道间的幅值关系。我的做法是先按通道算全局均值和方差,对整个训练集统一标准化,再切分序列。

骨干参数量级推理延迟(端侧参考)适合场景
统计特征 + 随机森林极小极低快速基线、资源受限
DeepConvLSTM数十万中等通用基线、离线分析
多层 1D-CNN数万至数十万端侧实时
TCN(空洞卷积)十万级需要长感受野的实时任务
卷积 + 自注意力混合百万级数据量大、追求精度
InceptionTime 集成百万级离线竞赛、精度优先

4. 小样本困境:数据增强、自监督与对比学习

HAR 数据集普遍小得可怜,几十个受试者、几百条记录,训一个百万参数的模型本来就捉襟见肘。这一章聊聊我是怎么补样本的,以及哪些增强是真有用、哪些纯属安慰剂。

4.1 传感器特有的增强算子

通用时间序列增强里,抖动(加高斯噪声)和缩放(乘一个随机因子)是最便宜也最稳的,几乎不会带来负面效果。时间扭曲(随机拉伸局部时间轴)要小心,幅度太大会把步态周期打乱,模型学到的就成了无意义波形。

真正值得强调的是三轴旋转。加速度信号里,重力分量和传感器佩戴朝向强耦合,同一个人把手机换个角度放兜里,信号分布就变了。对这些通道做三维随机旋转,模拟的是佩戴朝向的变化,能明显改善跨位置泛化。实现上取一个随机旋转矩阵 R,对每个时间点的三轴向量做 R·v 就行。这比简单地在通道上做置换要物理合理得多。

还有一种叫窗口切片的老办法:从长序列里随机截取子段当新样本。它本质上是采样增强,在样本量极少时能救急,但要注意别让切片和验证集重叠。

4.2 对比学习预训练值不值得做

如果把标签样本很少、又有一大堆无标签数据,自监督预训练是值得投入的。主流做法是时序对比学习:把同一条序列的两个增强视图拉近,把不同序列的视图推远,学一个编码器,再拿少量标签微调。TS-TCC 和 TS2Vec 是我用得比较多的两套实现,前者额外引入了一个时序预测任务,让你学到的表示既有判别性又保留了时序结构。

我自己的观察是:当标注样本在几百条这个量级、无标签数据有十倍以上时,对比学习预训练能带来 3 到 8 个点的提升;但当标注样本已经上万条时,提升几乎消失,纯监督训练就够。也就是说,这是一剂针对小样本的药,不是通用增益。

4.3 生成式增强的边界

用 GAN 或扩散模型生成合成样本的思路在文献里很常见,实话说我在这上面踩的坑最多。生成的加速度波形往往"太顺滑",缺少真实信号的毛刺和高频噪声,判别器又不够强,结果就是模型见到合成样本很兴奋,见到真数据反而懵。真要用,建议只生成少数类别做类别平衡,而且生成样本在训练时权重要压低,别当成真数据用。

5. 跨人、跨设备、跨佩戴位置:泛化才是主线

这个方向做久了会有个转变:你会发现单数据集上刷到 97% 意义不大,真正决定能不能落地的是换个人、换个手机、换个佩戴位置之后还剩多少分。泛化才是这条线的主线,其他都是支线。

5.1 LOSO评估与常见的数据泄漏

跨人评估的标准协议是留一受试者(LOSO):每次留一个受试者当测试集,其他所有人训练,最后把所有受试者的结果平均。这个协议下 UCI HAR 上能到 90% 以上已经算不错,PAMAP2 这种只有 9 个受试者的数据,经常只有 80% 出头。

有几个隐蔽的泄漏点需要专门排查。第一是归一化统计量:均值和方差只能用训练集算,绝不能把测试集算进去,哪怕只是算一个全局的也不允许。第二是窗口重叠:同一受试者的相邻窗口如果在训练和测试里各占一半,就是泄漏。第三是特征工程阶段的泄漏,比如用全体数据跑的 PCA 或者 FFT 的全局频谱分布。这三个点我在不同项目里都遇到过,每次排查都要重跑一遍。

5.2 域自适应与迁移方法对比

处理跨人差异,方法上大致有这么几类,我在下面按投入产出比排个序。

方法核心思路实现成本我的实测收益
数据增强旋转、缩放、加噪模拟域变化3 到 6 个点,最稳
批量归一化调优用目标域无标签数据重估 BN 统计量很低2 到 5 个点,性价比最高
对抗域适应用判别器对齐源域和目标域特征分布3 到 8 个点,训练不稳定
伪标签自训练用目标域预测高置信样本参与训练5 到 10 个点,需要仔细设阈值
元学习学一个能快速适应新人的初始化变化大,受试者极少时才有优势

我实际项目里用得最多的是前两个。批量归一化统计量重估几乎不花算力,只要目标域有几条无标签数据就能做,收益却相当可观。伪标签自训练属于进阶手段,关键在于置信度阈值的选取,我会从 0.9 开始试,逐步下调,同时监控目标域上的类别分布,一旦某类被大量吸走就说明塌缩了。

6. 端侧落地:模型压缩、量化与实时推理链路

论文里的模型再漂亮,最后要跑到一块只有几百 KB 内存的 MCU 上,该做的妥协一个都躲不掉。这一章讲讲我从训练完到真正在设备上跑通的那段路。

6.1 参数量与延迟的权衡

在 50Hz 采样、2.56 秒窗口的设置下,每 1.28 秒来一个新窗口,意味着单次推理必须在 1.28 秒内完成,这是实时性的硬约束。桌面实验里这个约束基本无感,模型都能跑得飞快,但端侧上就得精打细算。

我的经验值是这样:多层小通道卷积的网络最适合端侧,参数量控制在 5 万以内,int8 量化后模型文件能压到几十 KB,推理延迟在几十毫秒量级。DeepConvLSTM 也可以,但要砍掉一半卷积核,LSTM 隐层降到 64。至于那些百万参数的注意力模型,除非你的设备是带 NPU 的手机,否则别硬塞。

量化的坑主要在激活值动态范围上。加速度信号经过标准化后集中在 -3 到 3 之间,但 ReLU 输出是无界的,某些窗口上会窜到很大,导致量化分辨率被压扁。解决办法是在网络里加裁剪激活,把上界定在 6 左右,实测对精度影响不到一个点,量化后的稳定性却好得多。

6.2 部署链路上的坑

第一个坑是数据管道。训练时数据是整段读进来切窗,部署时是流式的,你得自己维护一个环形缓冲区,每来一个新采样点推进一格,凑够一个窗口就推理一次。缓冲区边界处理不好,会出现窗口错位,导致同一动作在相邻两次推理里给出不同结果,表现出来就是标签在屏幕上跳。

第二个坑是前处理的复现。训练时的标准化参数、通道顺序、重采样方式,都必须一模一样地在设备上复刻。我见过最典型的问题是训练时用 float32 标准化,端侧用定点近似,累积几百个点之后偏差就出来了,最终分类直接翻车。

第三个坑是平滑。单窗口预测噪声很大,直接输出会闪。通用做法是维护一个长度为 5 到 8 的预测队列,取多数投票或者概率平均,代价是响应滞后几百毫秒。这个滞后在走路识别这种慢节奏任务上完全可接受,但如果你做的是跌倒检测,那得单独处理,宁可牺牲平滑也要保证高召回。

最后说一个我个人比较看重的点:评估指标一定要落到宏平均 F1 和每一类的混淆情况上,别只盯准确率。HAR 数据集类别极不均衡,走路坐站占了七成以上,一个把所有样本都判成走路的模型准确率也能到七成。只有看宏平均 F1,你才知道那些少数类到底学没学会。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询