应对数据不平衡:嵌入式运动传感的定制化损失函数与分层模型设计 1. 项目概述当机器学习遇上嵌入式运动传感在智能照明、安防监控这些我们日常接触的领域运动传感器是背后的“隐形守护者”。你可能没注意过它但它时刻在判断走廊里是有人走过还是仅仅是一阵风办公室里是员工在伏案工作还是空调出风口在晃动这个看似简单的“是”或“否”的判断在工程实现上却充满了挑战。尤其是在追求极致能效和可靠性的嵌入式设备上传统的信号处理算法往往捉襟见肘而引入机器学习ML又带来了新的难题——数据不平衡。想象一下你要训练一个AI来识别“人走动的信号”和“环境噪声信号”。为了确保可靠性你需要收集海量的噪声数据可能长达数万小时只为捕捉那些偶尔出现的、容易误判的突发干扰比如无线电干扰或设备开关的瞬态脉冲。而真正有价值的“人走动”事件数据可能只有几千个总时长加起来还不到一小时。这就是典型的数据不平衡两类样本的数量可能相差上万倍。直接用这些数据去训练一个标准的分类模型比如一个神经网络结果往往是模型会“偷懒”——它发现只要把所有输入都预测为“噪声”就能获得极高的准确率比如99.99%但这对于检测“运动”这个核心任务来说是完全失败的。更棘手的是应用需求本身也是“不平衡”的。在照明控制场景中对“开灯”和“关灯”的判断要求截然不同。当灯处于关闭状态时传感器需要检测到有人接近并立即开灯这要求极低的误报率比如每1000小时最多误触发1次和极快的响应速度如0.6秒。因为一次误报可能导致深夜里空无一人的办公楼突然灯火通明。而当灯已经开启传感器需要持续检测微小的活动比如翻书、打字以保持灯光不灭这时允许一定的漏检比如检测率高于25%即可误报率要求也可以放宽如每20小时少于1次因为误报顶多是让灯多亮一会儿。面对这种“数据不平衡”叠加“需求不平衡”的双重挑战常规的“训练一个模型然后调整输出概率阈值”的方法效率低下且难以达到最优。本文要分享的正是我们团队在应对这一挑战时摸索出的一套从理论到实践的完整方案通过设计定制化的损失函数和分阶段的概率模型乘积架构实现面向嵌入式运动传感的高效、自动化机器学习优化。这套方法不仅大幅提升了训练效率降低了模型复杂度更重要的是它让模型训练直接对准最终的应用性能指标省去了繁琐且不稳定的后期手动调参。2. 核心挑战与设计思路拆解2.1 深入理解数据与需求的不平衡本质在动手设计解决方案之前我们必须先透彻理解问题本身。运动传感的数据不平衡并非简单的数量差异其背后有深刻的物理和工程原因。数据层面的不平衡噪声数据负样本海量但“信息密度”极低。绝大部分噪声时段传感器信号幅值很小近乎于基线噪声对模型训练几乎没有贡献。我们收集数万小时噪声数据核心目标是为了覆盖那占比可能不到0.01%的“棘手的突发噪声”Spurious Noise例如由远处开关电源、对讲机信号或特定电磁干扰产生的、形态上与真实运动信号有几分相似的脉冲。如图1所示左边是典型的运动信号中间是常见的环境噪声而右边就是这种棘手的突发噪声。如果我们将连续数据流切割成固定长度如3.2秒的片段那么“运动片段”和“噪声片段”的数量比将达到惊人的1:10000甚至更高。需求层面的不平衡这直接源于产品功能定义。对于“开灯检测”灯初始为关闭状态我们追求的是“宁可错过不可错杀”。因为误开灯False Positive带来的用户体验损害和能源浪费是显性的。因此我们需要极低的误报率FPR如 0.0001%和较高的查全率Recall即True Positive Rate, TPR。而对于“保持检测”灯已开启状态逻辑变为“宁可错留不可错关”。因为漏检一次微小的活动False Negative可能导致灯光意外熄灭影响用户体验而误报将噪声判为活动仅仅导致计时器重置灯光多亮一会儿代价相对较小。因此我们可以接受相对较低的查全率和较高的误报率。传统方法的瓶颈面对这种双重不平衡标准做法是类别加权在训练损失函数如二元交叉熵中给少数类运动样本赋予更高的权重。如图3所示调整权重可以改变模型在验证集上的性能曲线ROC曲线但找到恰好满足两个不对称需求的权重点需要大量的试错训练过程低效。阈值调优先训练一个模型再在其输出概率上寻找一个阈值使得在该阈值下的TPR和FPR满足要求。但问题在于对于一个在高度不平衡数据上训练出的模型其输出概率的校准性可能很差概率值集中在0或1附近导致可调节的阈值区间非常窄甚至不存在一个阈值能同时满足两个严苛且不对称的指标。我们的核心思路是绕开这些间接的、试错式的优化路径让模型的训练目标直接就是最终的应用性能指标。换句话说我们设计的损失函数其最小值点就应该对应着一个同时满足“TPR 某值”且“FPR 某值”的模型。这听起来很理想但实现起来需要解决几个关键问题性能指标TPR, FPR是基于离散计数的不可微无法直接用于梯度下降以及如何高效处理海量的、大部分是“简单样本”的噪声数据。2.2 方案架构分而治之的概率模型乘积我们的整体方案架构灵感来源于一个朴素的想法既然大部分噪声样本都很“简单”易于区分为什么不让一个简单的模型先把它们过滤掉从而让后面更复杂的模型专注于处理那些“困难的”样本包括复杂噪声和运动呢我们构建一个总的分类模型p(x, w)但它不是单一的网络而是两个子模型的乘积p(x, w) S(w_{2a} * L(p1(x, w1)) w_{2b}) * p2(x, w_{2r})这里p1(x, w1)第一级过滤器。它是一个极其简单的模型例如就是一个基于信号能量的线性分类器。它的任务不是直接区分运动和噪声而是区分“简单噪声”和“复杂噪声/运动”。它的设计目标是高召回率即尽可能放过所有可能是运动或复杂噪声的样本。S(w_{2a} * L(p1(...)) w_{2b})一个可学习的门控函数。其中S是Sigmoid函数L是Logit函数即Sigmoid的反函数。这个部分的作用是动态调整第一级过滤器p1的“严格程度”。w_{2a}和w_{2b在训练中学习相当于自动为p1的输出寻找一个最优的过滤阈值。p2(x, w_{2r})第二级精细分类器。这是一个相对复杂的模型例如一个小型卷积神经网络它只接收通过第一级过滤的样本。它的任务是最终区分“复杂噪声”和“真实运动”。这种架构的巧妙之处在于训练效率在训练主模型p(x, w)时对于任何一个噪声样本如果S(...)部分的值很低意味着被p1判定为“简单噪声”那么无论p2的输出是什么整个p(x, w)的输出都会趋近于0。在计算损失函数的梯度时这些样本的贡献为零。这意味着在每一次训练迭代中我们实际上只用了那些“困难”的样本被p1放过或p2需要仔细判断的样本来计算梯度从而实现了对海量数据的高效训练训练速度可提升数十甚至上百倍。自动化门控函数的参数w_{2a}, w_{2b是端到端训练得到的与p2一同优化。这避免了手动设置p1阈值的过程让整个系统能自动学习如何分配两级模型的工作。模型简化由于p1和p2各自只需要完成相对简单的子任务p1抓大放小p2精雕细琢它们各自都可以设计得比一个试图解决所有问题的单一模型更简单、参数更少。这对于嵌入式部署至关重要。3. 定制化损失函数的设计与实现要让模型训练直接优化最终指标核心在于设计一个可微的、能够编码具体TPR和FPR要求的损失函数。我们的方法是将离散的“计数”转化为连续的“分数”从而使其可导。3.1 从离散计数到连续分数对于一个样本i模型会输出一个预测概率y_pred_i介于0和1之间。在最终决策时我们设定一个阈值通常是0.5若y_pred_i 0.5则判为正类运动。传统的TPR和FPR计算是硬性的TPR (TP计数) / (总正样本数)FPR (FP计数) / (总负样本数)。计数是不可微的。我们的技巧是引入一个“软化”的计数。定义一个“分数正例”函数fp_i对于单个样本fp_i ∫_{1/2}^{∞} s(y, y_pred_i, λ) dy其中s(y, y_pred_i, λ)是一个以y_pred_i为中心、宽度为2λ的矩形窗函数当λ→0时它趋近于一个冲激函数。如图4所示这个函数在[y_pred_i - λ, y_pred_i λ]区间内值为1/(2λ)否则为0。这样设计的意义当λ→0时fp_i就退化成了硬判决如果y_pred_i 0.5则fp_i 1否则为0。当λ 0时fp_i是一个关于y_pred_i的连续、可微的函数。特别是当y_pred_i 0.5 - λ时fp_i恒为0。这意味着对于那些被模型非常确信为负例噪声的样本它们对损失函数的梯度贡献为0。这正是我们实现“聚焦困难样本”的数学基础。基于此我们定义整个数据集上的分数假正例FFP和分数真正例FTPFFP(w) Σ_{i ∈ 负样本} fp_i近似于FP计数FTP(w) Σ_{i ∈ 正样本} fp_i近似于TP计数3.2 构建直接面向需求的损失函数有了连续的FFP和FTP我们就可以构建一个直接衡量模型表现与目标差距的损失函数。假设我们的需求是FTP TPreq真正例分数要求且FFP FPreq假正例分数要求。我们定义两个误差项E_FP(w) [ (FFP(w) / FPreq) - 1 ] * θ( FFP(w) - FPreq )E_TP(w) [ (TPreq / FTP(w)) - 1 ] * θ( TPreq - FTP(w) )这里的θ是阶跃函数Heaviside step function。这个设计非常精妙E_FP只有当实际的FFP超过了允许的FPreq时该项才不为零。超过得越多惩罚越大。如果FFP满足要求小于等于FPreq该项为零模型不会在降低FFP上浪费优化能力。E_TP只有当实际的FTP低于要求的TPreq时该项才不为零。低得越多惩罚越大。如果FTP满足要求该项为零。最终的损失函数是两者的欧几里得范数E(w) sqrt( E_FP(w)^2 E_TP(w)^2 )这个损失函数的优化目标非常明确驱动模型参数w使得FFP和FTP同时满足要求。它是一个“可行域搜索”过程而不是传统的“最小化所有错误”。3.3 参数λ的作用与训练策略宽度参数λ在这里扮演着“平滑度控制”和“训练引导”的双重角色。控制平滑度较大的λ使得fp_i函数更平滑损失函数的景观Landscape也更平滑有助于在训练初期避免陷入糟糕的局部极小值。控制样本选择如前所述λ定义了“梯度消失区域”。对于负样本如果y_pred_i 0.5 - λ则其梯度为零。通过调整λ我们可以控制有多少“简单负样本”被排除在梯度计算之外。因此我们采用了一种退火式训练策略阶段一使用较大的λ值开始训练。此时损失函数平滑模型可以自由地探索参数空间初步学习区分模式。阶段二随着训练进行逐步减小λ例如每次减半。随着λ变小损失函数越来越接近真实的、离散的指标同时梯度计算也越来越聚焦于那些预测概率在决策边界0.5附近的“困难样本”。阶段三在训练p(x,w)时我们固定第一级模型p1的参数w1只训练第二级门控和分类器的参数w2a, w2b, w_{2r}。每次迭代我们只选取那些对当前损失函数有贡献即fp_i 0的样本参与计算这构成了一个动态的、自适应的困难样本挖掘机制极大提升了训练效率。4. 实战从数据到嵌入式友好型模型4.1 数据准备与特征工程我们使用的数据集来自实际的微波运动传感器运动数据869段时长3.2秒的时间序列采样率240Hz总计不到1小时的数据。噪声数据超过840万段同样3.2秒的时间序列总计约7600小时。数据按2:1划分为训练集和验证集。这种极端不平衡约1:10000是现实场景的真实写照。特征提取流程针对每3.2秒的768个原始采样点去均值减去该片段的均值消除直流偏移。加窗FFT使用一个长度为128点的汉宁窗以32点为步长滑动对768点数据计算出21个重叠的窗口。计算幅度谱对每个窗口做FFT取前64个正频率点的幅度值得到21x64的幅度谱矩阵。第0个频率点直流分量被丢弃。归一化使用一个随机数据子集计算平均功率谱然后将所有特征除以这个平均功率谱的均值进行归一化。这一步有助于稳定训练。注意这里只使用了幅度谱丢失了相位信息。对于检测信号中的不连续性如运动的起始点相位信息可能很有用。在实际项目中可以根据需要引入复数频谱或其他的时频特征。4.2 模型具体实现第一级模型 p1(x, w1)简单能量过滤器这个模型的目标是快速过滤掉“安静”的噪声。我们计算每个3.2秒片段内所有21个窗口、64个频率点的平均能量E。p1(x, w1) S(w11 * E w12)这本质上是一个逻辑回归模型w11和w12是两个可训练参数。它非常简单计算量极小非常适合作为第一道粗筛。第二级模型 p2(x, w2)轻量级卷积神经网络这个模型负责精细分类。我们借鉴了用于手写数字识别如MNIST的经典轻量CNN架构并针对嵌入式场景进行了约束优化其结构如图5所示卷积层使用5个3x3的卷积核。为了控制模型大小和提升部署稳定性我们对卷积核施加了单位范数约束即每个卷积核的权重向量L2范数为1对偏置施加了[0,1]区间的约束。激活函数使用ReLU。池化层3x3的最大池化层用于降维和引入平移不变性。展平层将多维特征拉平为一维向量。全连接层110个神经元权重和偏置同样约束在[0,1]区间激活函数为ReLU。全连接层2输出层1个神经元使用Sigmoid激活函数输出最终概率权重和偏置约束在[0,1]区间。实操心得对权重和偏置施加[0,1]的约束是一个关键技巧。这并非为了提升精度而是为了部署友好性。在嵌入式设备如ARM Cortex-M系列MCU上运行定点数或低精度浮点数计算时有界的参数值能极大减少量化误差和溢出风险提高模型在边缘设备上的推理稳定性。这是工业级嵌入式AI与纯学术研究的一个显著区别。4.3 训练过程与结果分析我们使用Keras和TensorFlow后端进行训练。作为对比首先尝试了两种常规方法不平衡训练直接使用原始数据批量大小32768。由于每个批次中运动样本占比极低约0.5%模型无法有效学习训练失败。类别平衡训练在每个批次中平衡正负样本数量。模型可以训练但其性能如表1所示远未达到目标需求TPR 50% FPR 0.0044%。无论怎么调整输出阈值都无法同时满足两个指标。随后我们应用了本文提出的分阶段训练与定制损失函数方法关键步骤如下第一阶段训练p1从训练集的噪声数据中随机抽取一部分与全部运动数据组成一个平衡的数据集共65536个样本。使用类别平衡的二元交叉熵损失函数训练p1。如表2第1行所示p1能有效区分大部分简单噪声将约98.4%的噪声滤除同时保留了60%的运动信号这正是我们想要的高召回率。第二阶段端到端训练p(x,w)冻结p1的参数w1。使用完整的训练集约56万个噪声样本运动样本以及我们设计的定制损失函数来训练p(x,w)中的参数w2即门控参数w2a, w2b和CNN参数w_{2r}。我们采用退火策略初始设置较大的λ值如0.49。在每次训练迭代中自动选择那些S(...)值较高的样本即未被p1完全过滤的样本参与梯度计算。这使每次迭代的有效批量大小远小于总数据量训练非常高效。训练收敛或达到最大迭代次数后将λ值减半继续训练如此重复。最终结果如表2第4行所示经过多轮λ退火训练后模型在测试集上的性能达到了TPR 49%接近50%的目标和FPR 0.0011%优于0.0044%的目标成功满足了“保持检测”场景的严苛要求。整个训练过程仅使用了最多65536个样本/迭代相比使用全部56万样本的传统方法训练时间减少了约100倍。5. 避坑指南与扩展思考5.1 常见问题与排查技巧在实际复现和应用该方法时你可能会遇到以下问题问题现象可能原因排查与解决思路损失函数不下降或震荡剧烈。初始λ值设置过小。λ是平滑因子。初始值应设得较大如0.3-0.5以确保损失函数在初期足够平滑便于优化器找到下降方向。采用退火策略逐步减小λ。模型性能始终无法同时满足TPR和FPR要求。1. 模型容量不足。2. 特征工程不到位信号与噪声难以区分。3. 需求指标过于严苛超出数据可提供的信息限度。1. 适当增加p2模型的复杂度如增加卷积核数量、全连接层神经元数。2. 重新审视特征尝试引入时域特征过零率、峰值、相位谱、或更复杂的时频分析小波变换。3. 与产品部门确认需求是否合理或收集更多、更具代表性的“困难样本”复杂噪声。训练后期λ很小时梯度爆炸或消失。λ过小导致fp_i函数过于尖锐梯度不稳定。1. 设置λ的下限如不小于0.01。2. 使用梯度裁剪Gradient Clipping技术。3. 尝试更稳定的优化器如AdamW并调小学习率。在嵌入式设备上部署后性能下降明显。1. 训练与部署时的数据分布不一致协变量偏移。2. 定点量化或低精度计算引入误差。1. 确保部署环境采集的校准数据参与最终模型的微调Fine-tuning。2. 在训练后引入量化感知训练QAT或使用[0,1]约束的模型本身就更利于量化。测试时在目标硬件上验证精度。p1过滤器过于激进过滤掉了太多运动样本。p1模型太复杂或训练数据中的“简单噪声”定义不清。p1的目的应是高召回率。确保用于训练p1的“负样本”确实是典型的、简单的噪声。可以手动检查被p1过滤掉的运动样本看是否是信号极弱的边缘案例。5.2 方案优势与适用场景总结回顾整个方案其核心价值在于提供了一条通往“需求驱动、嵌入式友好”机器学习模型的清晰路径效率革命通过“困难样本挖掘”机制训练过程自动忽略海量的简单样本将计算资源集中在关键的数据上训练速度提升百倍使得在有限算力下迭代优化模型成为可能。自动化与最优化定制损失函数将业务需求TPR, FPR直接转化为优化目标省去了繁琐且不精确的阈值调优步骤得到的模型在指定指标上就是Pareto最优的。嵌入式友好分阶段的模型设计简单过滤器复杂分类器和参数约束[0,1]区间使得最终模型更轻量、更稳定易于在资源受限的微控制器MCU上部署和运行。这套方法不仅适用于微波/红外运动传感其思想可以推广到任何面临极端数据不平衡和明确、不对称性能指标的嵌入式分类场景。例如工业异常检测正常生产数据海量故障样本极少且对误报和漏报的成本要求不同。关键词唤醒日常环境音频数据极多特定唤醒词片段很少需要极低的误唤醒率。物联网设备的状态识别设备大部分时间处于空闲状态简单样本需要识别少数几种特定工作模式。5.3 个人实操体会在实际项目中落地这套方法有几个点让我感触颇深。首先特征工程依然是基石。无论损失函数设计得多巧妙如果原始特征不能有效表征信号的本质差异模型的天花板会很低。在运动传感中我们花了很多时间对比不同时频变换、不同窗函数的效果。其次λ退火策略的节奏需要耐心调试。初期λ大学习率可以稍大后期λ小模型在做精细调整学习率必须相应减小否则容易在最优解附近震荡。最后与硬件团队的早期沟通至关重要。我们之所以对p2网络施加[0,1]约束就是因为硬件工程师明确告知了他们定点数DSP的位宽和动态范围限制。让算法从一开始就拥抱部署约束能避免后期大量的移植和优化工作。这套框架的价值在于它提供了一套系统化的“解题思路”而不仅仅是几个技巧。当你面对一个不平衡的、有明确性能红线的嵌入式分类问题时你可以沿着“分析需求 - 设计目标函数 - 构建分层模型 - 实施聚焦训练”这条路径一步步将模糊的业务问题转化为可执行、可优化的机器学习任务。