想象你是一位足球比赛的现场解说员。你不需要等整场比赛结束后再看录像回放,而是眼睛紧盯着球场,运动员每一次传球、射门、犯规,你都要在那一瞬间识别出来并脱口而出。解说员不能等“比赛踢完了再总结刚才发生了什么”,因为观众需要的是“此时此刻正在发生什么”。 AI 的在线动作检测(Online Action Detection)做的事情,就和你这位解说员一模一样。传统的视频理解模型在看一段视频时,可以“从头看到尾”再下结论,就像一位事后看录像的评论员。但在线动作检测不一样,它只被允许看到当前这一刻以及之前的画面——未来还没发生,不能偷看。它要在视频一帧一帧地流过来时,实时判断:“这个人此刻正在做什么?这个动作是否刚刚开始?” 这项技术就藏在你看直播时系统自动拦截违规画面的背后、在你家智能摄像头判断“老人是否摔倒”的警报里、在健身 App 纠正你深蹲姿势的提示音中。本文会用解说员的视角,带你搞懂在线动作检测的时序建模、滑动窗口、RNN 在线推理、Transformer 推理以及延迟与精度如何平衡。

岗位关联

学完本知识,你将理解流式视频实时分析的完整技术栈,能设计出毫秒级响应的动作识别系统——这是直播审核、智能安防、互动健身等实时 AI 产品刚需的核心能力。

目录
  1. 可视化演示
  2. 定义与场景
  3. 时序建模与特征
  4. 滑动窗口机制
  5. RNN在线推理
  6. Transformer推理
  7. 延迟精度平衡
  8. 部署与优化实践
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

本节配有交互动效(进入视口后自动加载,约 3KB)。

滑动窗口检测 固定窗口大小随数据流滑动 实时计算z-score判断异常 z = |x - μ| / σ 毫秒级响应流式数据

定义与场景

解说员深吸一口气,他站在场边,眼睛一刻也不离开球场。他必须边看边说。他的工作有一个铁律:只能根据“已经看到的画面”来解说,绝不能提前说出“接下来会发生什么”——因为连球员自己都不知道下一秒会发生什么。解说员的这个工作原则,和 AI 的在线动作检测一模一样。

在线动作检测(Online Action Detection)就是指:系统持续接收流式视频帧,在每一帧到达的当下,仅依据当前帧及之前的历史帧,实时判断“当前正在发生什么动作”。它和离线动作识别最大的区别在于因果性——离线模型可以看完整段视频再回头标注“第 3 到第 8 秒在做深蹲”,而在线模型不能等,它必须像解说员一样语速飞快地吐出判断。

具体来说,在线动作检测要解决两个关键问题:第一,动作是否正在发生(检测动作的进行状态);第二,动作何时开始、何时结束(时间边界的在线判定)。这天然对延迟提出了极高要求——从画面出现到系统给出判断,通常在几十到几百毫秒内完成,否则就失去了“实时”的意义。在直播审核(拦截违规画面)、智能安防(识别摔倒)、互动健身(纠正动作)等场景中,这个能力直接决定了产品的可用性。

1. 在线含义:“在线”意味着系统持续运行,每来一帧就要输出一次结果,像解说员一样不能停顿。

输出t=f(x1,x2,…,xt)\text{输出}_{t}=f(x_{1},x_{2},\dots ,x_{t})

2. 历史信息约束:输出只依赖于当前及之前的帧,绝不含未来帧,这是因果性的技术表达。

∀i>t:  xi∉输入集合\forall i>t:\; x_{i} \notin \text{输入集合}

部署一套在线动作检测系统,就像培训一位解说员:先让他看大量比赛录像学会识别动作(训练),然后让他上场边看边说(推理)。而这个“边看边说”的过程,正是接下来要拆解的每一步技术细节。

时序建模与特征

解说员凭什么一眼看出球员在做“射门”而不是“传球”?因为他不仅仅看某一瞬间的静止画面——他会把“助跑→摆腿→触球→球飞出去”这一连串的画面在脑中串联起来。这种把多帧画面串联起来理解的能力,在 AI 中叫时序建模。

要让机器具备这种能力,第一步是把每一帧视频变成一个机器能理解的“描述向量”,这叫帧级特征提取。现代做法通常用预训练的 2D/3D CNN 网络(如 ResNet、I3D)从每帧图像中提取特征向量,就像解说员用眼睛“扫描”画面,把“绿茵场、白色球衣、腿抬起来了”浓缩成一段数字描述。

但单帧特征只是“一张照片的摘要”,动作是连续时间上的变化,所以还需要时序上下文融合——把前后多帧的特征按时间顺序拼在一起,让模型看到“腿逐渐抬起又落下”的完整过程。常见特征还包括光流(描述像素在帧间的运动方向和速度,相当于解说员眼里的“动态轨迹”)和姿态特征(提取人体骨骼关键点坐标,相当于“球员骨架的逐帧位置”)。这些不同来源的特征可以拼接成更丰富的时序表示,就像解说员同时用眼睛追球、用余光看跑位一样,多路信息综合判断。

F=[ϕ(x1);  ϕ(x2);  … ;  ϕ(xT)]\mathbf{F}=[\phi(x_{1});\;\phi(x_{2});\;\dots ;\;\phi(x_{T})]

1. 逐帧提取:对每帧图像用卷积网络提取特征向量,得到该帧的“摘要”。

ϕ(xi)∈Rd\phi(x_{i})\in \mathbb{R}^{d}

2. 时间拼接:把各帧特征沿时间轴排列成矩阵,形状为“序列长度 × 特征维度”。

[⋅;⋅]:  concatenation along time[\cdot ;\cdot ]:\; \text{concatenation along time}

如果说特征是解说员“看到的信息”,那么时序建模就是解说员“串联信息的方式”。有了这个基础,下一步就要回答一个工程问题:解说员应该回看多远的过去来判断当下?这就是滑动窗口的由来。

滑动窗口机制

解说员虽然记性好,但不可能从比赛第 1 秒回忆到第 90 分钟——他只需要记得最近十几秒的场上形势,就能准确判断“现在发生了什么”。滑动窗口就是这个思路:每次只保留最近固定长度(比如 16 帧或 32 帧)的历史帧作为判断依据,窗口随新帧到来不断向前滑动。

滑动窗口的动机很朴素:动作本身是局部连贯的。“挥手”这个动作,你只需要看最近半秒的画面就能识别,不需要回忆上个月的事。固定窗口长度 L 意味着,时刻 t 的输入是窗口内的帧序列:

Wt={xt−L+1,…,xt}\mathbf{W}_{t}=\{x_{t-L+1},\dots ,x_{t}\}

窗口每来一帧就前移一步:丢弃最旧的一帧,纳入最新的一帧。这带来一个重要的工程特性——相邻窗口重叠度极高,只有一帧的差异。既然大部分帧在前后两次判断中都被重复用到,聪明的工程师会缓存中间计算结果,避免重复提取特征,大幅降低计算量。这与解说员“眼界始终维持在场上的近景”是同一个道理:他不是每句话都从头回忆,而是顺着记忆平滑地延续。

重叠率=1−1L\text{重叠率}=1-\frac{1}{L}

1. 窗口长度 L:超参数,决定模型“记忆回看的范围”,像解说员的“近期记忆时长”。

Wt⊆{x1,…,xt}\mathbf{W}_{t}\subseteq \{x_{1},\dots ,x_{t}\}

2. 滑动步长:通常每来一帧滑动一帧,保证输出的实时粒度。

Wt+1=Wt∖{xt−L+1}∪{xt+1}\mathbf{W}_{t+1}=\mathbf{W}_{t}\setminus\{x_{t-L+1}\}\cup\{x_{t+1}\}

滑动窗口让解说员的“记忆”有了边界——他记住最近一段时间的画面,其余细节自然遗忘。但窗口不能无限长,因为解说员的嘴巴(判断速度)追不上无限回看。这就是为什么需要更聪明的记忆机制:不是所有信息都同等重要,有些瞬间必须刻骨铭心。

RNN在线推理

解说员记性其实很聪明:他不会平均用力记住每一帧,而是对关键瞬间(比如那记漂亮的倒挂金钩)记忆特别深刻,对平淡的传球瞬间一晃而过。这种“有选择地记住重要信息、自然地淡忘次要信息”的能力,正是循环神经网络(RNN)的核心天赋。

RNN 的核心思想是隐藏状态传递:它维护一个内部记忆向量 h(解说员的“脑内笔记”),每来一帧 x,就结合当前帧和上一时刻的记忆,更新出新的记忆,同时输出判断结果。用 LSTM 或 GRU 这样的门控 RNN,还能通过“输入门”“遗忘门”等机制,决定记住什么、忘掉什么——就像解说员会忘掉上个平淡回合的细节,但牢牢记住刚才那次越位争议。

RNN 对在线推理是天然友好的,因为它的计算是增量式的:时刻 t 的输出只依赖当前输入帧和上一步传递来的隐藏状态,不依赖早期所有帧的重新计算。这使得每来一帧,只需一次前向计算即可得到结果,计算量恒定,非常适合流式处理。简化的更新过程如下:

ht=RNN(ht−1,  ϕ(xt))yt=Softmax(Wht)\mathbf{h}_{t}=\text{RNN}(\mathbf{h}_{t-1},\;\phi(x_{t}))\qquad \mathbf{y}_{t}=\text{Softmax}(\mathbf{W}\mathbf{h}_{t})

1. 隐藏状态更新:新记忆由旧记忆和当前帧共同决定,实现“增量式记忆刷新”。

ht=tanh⁡(Whht−1+Wxϕ(xt)+b)\mathbf{h}_{t}=\tanh(\mathbf{W}_{h}\mathbf{h}_{t-1}+\mathbf{W}_{x}\phi(x_{t})+\mathbf{b})

2. 当前判断输出:从记忆状态解码出各类动作的概率分布,取最大者为判断结果。

yt=softmax(Woht+bo)\mathbf{y}_{t}=\text{softmax}(\mathbf{W}_{o}\mathbf{h}_{t}+\mathbf{b}_{o})

解说员凭借“脑内笔记”游刃有余,但 RNN 也有短板:记忆是串行传递的,看第 100 帧时必须先算完第 99 帧,难以并行。而且长距离依赖会衰减。这时,一位“过目不忘”的新解说员出现了——Transformer。

Transformer推理

想象一位天赋异禀的解说员,他的记忆方式完全不同:他不依赖“记笔记”,而是每当需要判断时,就把过去所有画面快速回放一遍,并且特别关注其中和当前时刻最相关的片段——比如判断“是否射门”时,他会重点回放“触球瞬间”的画面,而不是盯着守门员发呆。这种“全局回放 + 重点关联”的机制,就是 Transformer 的自注意力(Self-Attention)。

Transformer 在每一步推理时,计算当前帧(查询 Q)与历史所有帧(键 K)的相似度,再据此加权融合历史帧的信息(值 V)。这种机制能显式建模长距离依赖——第 1 秒的“助跑”信息可以跨越几十帧直接影响第 2 秒的“射门”判断,而不会被中间的无关帧冲淡。

但 Transformer 有个“犯规风险”:标准的自注意力会看到全局所有帧,包括未来帧——这等于解说员偷看了结果。所以在线推理必须加因果掩码(Causal Mask):强制注意力只能关注当前及之前的帧,未来的位置全部置为负无穷,softmax 后权重归零。这相当于给解说员戴上一副“不透明眼罩”,只允许他回看过去。

Attention(Q,K,V)=softmax(QK⊤+Mdk)V,Mij={0j≤i−∞j>i\text{Attention}(Q,K,V)=\text{softmax}\left(\frac{QK^{\top}+M}{\sqrt{d_{k}}}\right)V,\qquad M_{ij}=\begin{cases}0 & j\leq i\\ -\infty & j>i\end{cases}

1. 相似度计算:当前帧与历史帧的点积除以维度平方根,得到“关联分数”。

QK⊤dk\frac{QK^{\top}}{\sqrt{d_{k}}}

2. 掩码遮罩:未来位置的分数设为负无穷,softmax 后权重变为 0,杜绝偷看。

Mij=−∞  (j>i)  ⇒  softmax=0M_{ij}=-\infty \;(j>i)\;\Rightarrow \;\text{softmax}=0

Transformer 虽强,但“全局回放”成本不低——每次判断都把整个历史重新过一遍,计算量随时间线性增长。工程上常用 KV 缓存解决:把已经算好的键值对存起来,新帧只计算自己的 Q/K/V,与缓存的历史 K/V 做注意力,避免了重复计算,让推理速度大幅提升。

新的解说员过目不忘,但“回放全部画面”费时费力。到底该用记笔记的 RNN,还是用回放的 Transformer?这要看比赛的重要程度和你能接受的解说延迟——这就引出在线动作检测最核心的工程权衡:延迟与精度的跷跷板。

延迟精度平衡

解说员总在纠结:如果给他 1 秒时间回忆,他几乎不会说错;但观众要求他 0.2 秒内接话,他就只能凭直觉说个大概。在线动作检测面临同样的延迟-精度权衡:看的历史信息越多(窗口越长、模型越大、帧率越高),判断越准,但耗时就越多;反过来,追求低延迟就难免牺牲精度。

这条权衡关系可以画成一条精度-延迟曲线:横轴是端到端延迟(从画面出现到结果返回的毫秒数),纵轴是检测精度(如 mAP、准确率)。曲线通常呈上升趋势——延迟越高、精度越高,但会逐渐饱和。曲线的“甜点区”在拐点附近:再增加延迟,精度提升甚微,却白白浪费时间。

实操中做权衡有几个杠杆:第一,窗口长度——短窗口响应快但上下文不足,长窗口信息足但延迟高;第二,模型轻量化——用 MobileNet、轻量 Transformer 替换大模型,精度略降、速度倍增;第三,帧采样策略——不必每帧都推理,可以每隔 k 帧推理一次,中间帧沿用上次结果,把计算成本摊薄。

延迟≈t特征提取⏟单帧耗时+t时序推理⏟窗口内计算耗时+t传输/后处理⏟固定开销\text{延迟}\approx \underbrace{t_{\text{特征提取}}}_{\text{单帧耗时}}+\underbrace{t_{\text{时序推理}}}_{\text{窗口内计算耗时}}+\underbrace{t_{\text{传输/后处理}}}_{\text{固定开销}}

1. 特征提取耗时:单帧过 CNN 的时间,决定了每秒能处理多少帧。

tfeat=latency of ϕ(xt)t_{\text{feat}}=\text{latency of }\phi(x_{t})

2. 时序推理耗时:窗口内做 RNN/Transformer 推理的时间,与模型规模相关。

tseq=latency of RNN/Transformer on windowt_{\text{seq}}=\text{latency of RNN/Transformer on window}

解说员最终明白:不存在“又准又快”的免费午餐。接到什么解说任务,就配什么策略——体育直播要求最高实时性,就牺牲一点精度用轻模型;安防回查允许几秒延迟,就跑大模型换高精度。理清这笔账后,最后一步就是把这套系统真正“派上场”。

部署与优化实践

解说员的水平再高,也得坐到正确的转播席、戴上耳机、连好信号才能开口。在线动作检测模型训练得再好,也要解决上线部署的最后一公里:视频从哪里来?模型跑在哪里?出了问题怎么办?

首先是流式视频接入。常见做法是从 RTSP/RTMP 拉流或直接读取摄像头 SDK 输出的帧数据,做解码、缩放、归一化后送入模型。这一步要保证“帧不断流”,像解说员的耳机信号必须稳定——掉帧、卡顿会直接导致判断失败。实践中常用 FFmpeg 做视频解码与抽帧,通过队列缓冲实现拉流与推理的解耦。

其次是推理加速手段,梯次组合使用:用 TensorRT/ONNX Runtime 做模型编译优化,将 FP32 转成 FP16 或 INT8 量化,能获得 2-4 倍加速;对滑动窗口的重叠区域做特征缓存,避免重复计算;对多路视频流用 GPU 上的批处理(batching)进一步提升吞吐。像解说员会提前熟悉球队名单和战术一样,系统也要通过预热和缓存把“功课”做在前面。

然后是边缘端部署:在摄像头附近的小盒子(如 Jetson、树莓派 + NPU)上直接推理,省去视频上传云端的网络延迟,把“现场解说”变成“现场判断”。最后是监控与容错回退:系统要记录推理延迟、准确率漂移、模型置信度等指标,当延迟超阈值或置信度持续过低时,自动切换降级策略(比如降采样率、切备份模型),确保服务不中断。这套护栏就像导播台的应急预案——解说员嗓子哑了,立刻切备用麦克风。

从定义到部署,在线动作检测的完整链路就像培训一位解说员从观看录像、练习口播,到最终坐在直播间里面对真实比赛的整个过程。技术的每个环节,都在回答同一个问题:如何让 AI 边看边说,说得快,也说得好。

AI 应用场景

直播审核:实时拦截违规内容

阶段:在线推理部署

解决的问题:直播平台每秒产生海量视频流,传统人工审核延迟高达分钟级,违规画面流出后再封禁已造成恶劣影响。在线动作检测在主播画面出现违规动作(如吸烟、暴力行为)的几百毫秒内即发出告警,直接触发断流或转人工复查,将响应时间压缩到亚秒级。

具体案例:某游戏直播平台接入在线动作检测模型,对主播摄像头画面做每秒 10 帧的流式推理。当模型检测到“击打屏幕”“展示违禁物品”等动作时,置信度超过阈值即在 300ms 内通知审核员复核,同时自动降低直播间推荐权重。上线后违规内容平均存续时间从 4 分钟降至 20 秒。

智慧养老:老人跌倒实时告警

阶段:时序建模与 RNN 在线推理

解决的问题:独居老人跌倒后如果无人发现,可能错过黄金救援时间。传统方案用红外传感器只能检测移动,无法识别“跌倒”这一具体动作。基于姿态特征 + LSTM 在线推理的方案,持续分析老人骨骼关键点的时序变化,在“倒地”动作发生的 1 秒内触发告警,并保持全程不录制视频、只传特征,保护隐私。

具体案例:某养老院在 200 个房间部署边缘计算盒,接入普通摄像头。模型每 200ms 输出一次“跌倒概率”,连续 3 次超阈值即触发呼叫值班护士,并附上所在房间号。系统上线 6 个月成功告警 47 次真实跌倒事件,平均响应时间 1.5 秒。

互动健身:动作纠错实时反馈

阶段:滑动窗口 + 轻量模型推理

解决的问题:健身 App 用户跟着视频做深蹲、平板支撑时,姿势错误容易受伤。传统方案是录制完整视频后回传分析,反馈延迟导致用户早已做完动作。在线动作检测用短滑动窗口(32 帧)+ 轻量 CNN 实时判断髋部高度、膝盖角度等时序特征,在动作变形发生的瞬间用语音提示“膝盖内扣,向外打开”。

具体案例:某居家健身 App 在手机端调用自研轻量模型,仅用 CPU 即可实现 20ms 单帧推理。用户做深蹲时,系统在“下蹲过浅”持续 0.5 秒后立即推送振动 + 语音纠正。该功能上线后,用户平均动作完成度提升 31%,受伤投诉下降 52%。

Python 演示

python59 行
import numpy as npfrom collections import deque  class SlidingWindowDetector:    def __init__(self, window_len=16, frame_dim=2048, num_classes=5):        self.window_len = window_len        self.frame_dim = frame_dim        self.num_classes = num_classes        self.buffer = deque(maxlen=window_len)        self.hidden = np.zeros(256)        self.W_h = np.random.randn(256, 256) * 0.05        self.W_x = np.random.randn(256, frame_dim) * 0.05        self.W_o = np.random.randn(num_classes, 256) * 0.05        self.b_h = np.zeros(256)        self.b_o = np.zeros(num_classes)        self.feat_cache = {}        self.frame_count = 0     def extract_feature(self, frame_id):        if frame_id in self.feat_cache:            return self.feat_cache[frame_id]        # 模拟 CNN 提取特征: 此处用随机向量替代真实视频        feat = np.random.randn(self.frame_dim)        self.feat_cache[frame_id] = feat        return feat     def online_step(self, frame_id):        feat = self.extract_feature(frame_id)        self.buffer.append(feat)        if len(self.buffer) == self.window_len:            window = np.array(self.buffer)            for t in range(window.shape[0]):                self.hidden = np.tanh(                    self.W_h @ self.hidden + self.W_x @ window[t]                )            logits = self.W_o @ self.hidden + self.b_o            probs = np.exp(logits - logits.max())            probs = probs / probs.sum()            return int(np.argmax(probs)), probs        return None, None     def run_stream(self, total_frames=100):        events = []        for fid in range(total_frames):            action, probs = self.online_step(fid)            if action is not None:                events.append((fid, action, probs.max()))        return events  if __name__ == "__main__":    np.random.seed(42)    detector = SlidingWindowDetector()    results = detector.run_stream(200)    detected = [(fid, act) for fid, act, conf in results if conf > 0.5]    print(f"共推理 {len(results)} 次, 高置信事件 {len(detected)} 个")    for fid, act in detected[:5]:        print(f"帧 {fid}: 检测到动作类别 {act}")
目的:演示在线动作检测的核心流程——滑动窗口缓存历史帧 + 简易 RNN 增量更新隐藏状态 + 每步输出当前动作概率。
  1. deque(maxlen=window_len)用双端队列实现滑动窗口,自动丢弃最旧帧,正是“解说员只看最近一段记忆”的实现。
  2. extract_feature模拟 CNN 帧特征提取,用 feat_cache 缓存已算特征,避免重叠窗口重复计算。
  3. online_step每来一帧只做一次更新:把当前特征推进 RNN,不重新处理整个历史。
  4. self.hidden = np.tanh(self.W_h @ self.hidden + self.W_x @ window[t])这就是 RNN 隐藏状态更新的核心:新记忆 = 旧记忆 + 当前帧。
  5. logits = self.W_o @ self.hidden + self.b_o从隐藏状态解码出各类别得分,再 softmax 成概率。
  6. run_stream模拟一整段流式视频逐帧喂入,输出每个时刻的动作判断。
  7. conf > 0.5实践中常设置信度阈值过滤低可靠判断,减少误报。

常见误区

误区我只要把视频攒够 10 秒,然后每隔 1 秒跑一次离线动作识别模型,不也是实时的吗?

正解这种“攒批处理”方式有严重问题:动作开始后要攒满 10 秒才出结果,导致 10 秒级延迟,且每个批次的判断彼此独立,没有时序连贯性。真正的在线推理是每帧输入立即输出,中间状态(RNN 隐藏态或 Transformer KV 缓存)跨帧持续传递,像解说员说话时“脑子里始终存着场上局势”,而不是每 10 秒发一次呆再总结。

为何常见:大家对“实时”的直觉是“经常跑一跑就行”,没意识到在线检测对“逐帧因果输出 + 状态增量更新”的根本要求。

误区训练时用因果掩码,推理时模型反正只看到历史帧,掩码可有可无。

正解推理时同样需要掩码。虽然输入序列只给到当前帧,但 Transformer 的注意力计算会遍历输入序列内的所有位置对;如果模型没有学过掩码对应的注意力模式,训练和推理的分布不一致,精度会下降。更关键的是,推理时若利用 KV 缓存加速,依然要保证每个历史位置的注意力只覆盖更早的位置,否则缓存结果无法复用。

为何常见:以为“只要输入不含未来帧就够了”,忽略了注意力机制内部覆盖的是序列全部位置。

误区滑动窗口越长,模型看到的历史信息越多,在线检测的精度应该单调上升,所以尽量选最大窗口。

正解窗口过长会带来三个问题:一是噪声累积,很久前的无关历史反而干扰当前判断;二是延迟线性增长,每条检测结果要等窗口攒满才输出;三是计算量剧增,长序列的推理耗时和内存占用成倍上升。实际工程中,窗口长度需要结合动作的固有持续时间(比如“挥手”约 0.5 秒,“深蹲”约 2 秒)来选择,并在验证集上画精度-延迟曲线找甜点。

为何常见:把“信息越多越好”的直觉直接搬到了在线场景,忽略了实时系统的延迟预算。

误区在线是一帧一帧来的,RNN 天生支持流式,Transformer 必须把整个序列整体输入,所以在线检测只能用 RNN。

正解Transformer 配合因果掩码 + KV 缓存完全可以支持在线推理:每来一帧只计算该帧的注意力,历史 K/V 缓存复用,推理耗时与序列长度近似解耦。实际应用中,轻量 Transformer(如 TimeSformer 的因果变体)在长序列建模上往往优于 RNN,只是工程复杂度略高。

为何常见:早期在线检测文献以 LSTM 为主流,导致大家形成“在线=RNN”的思维定式,忽略了注意力机制也能因果化。

误区边缘设备部署在线检测很简单,把训练好的模型放到 Jetson 上,用 PyTorch 直接推理就行。

正解边缘端推理要面对内存受限、无 GPU、散热约束等多重限制,通常需要模型转换(PyTorch→ONNX→TensorRT)、量化(FP32→FP16/INT8)、算子裁剪,甚至重新训练一个轻量版模型(知识蒸馏)。此外,拉流解码、帧缓冲、推理线程的流水线设计,以及掉线重连、模型热更新等运维能力,都是边缘部署的核心工程问题。

为何常见:初学者只在服务器上跑过离线流程,误以为“部署”只是换台机器,忽略了边缘环境的算力墙和工程复杂度。

面试题

Q1. 在线动作检测与离线动作识别最本质的区别是什么?

单选题 · easy

  • A.在线模型用更深的网络结构,离线模型用更浅的网络
  • B.在线模型只能使用当前及之前的帧做判断,不能偷看未来帧← 正确答案
  • C.在线模型只处理灰度图,离线模型处理彩色图
  • D.在线模型不需要训练,离线模型需要训练

答案:B。在线动作检测的核心约束是因果性——只用历史信息判断当下(B)。选项 A 无关网络深度;C 说反了,在线模型同样处理彩色帧;D 在线模型当然也需要训练。像解说员不能预知未来一样,在线检测的输入天然被“时间之墙”限制。

Q2. 滑动窗口机制中,相邻两次窗口的重叠率大约是多少?

单选题 · easy

  • A.取决于窗口长度,约 1 - 1/L← 正确答案
  • B.固定为 50%
  • C.固定为 0%
  • D.与窗口长度无关,固定为 90%

答案:A。窗口每来一帧滑动一帧,即丢 1 帧、进 1 帧,重叠帧数为 L-1,重叠率为 (L-1)/L = 1 - 1/L。L=16 时约 94%,L=32 时约 97%。不是固定 50% 或 0%。高重叠率意味着重叠区域的特征可以缓存复用,是滑动窗口工程优化的基础。

Q3. RNN 做在线推理时,隐藏状态 h 的作用是什么?

单选题 · mid

  • A.存储全部历史视频帧的原始像素
  • B.作为压缩的历史信息载体,跨帧传递并参与当前判断← 正确答案
  • C.只保存当前一帧的特征,不跨帧传递
  • D.用于存储训练集的标签

答案:B。隐藏状态 h 是 RNN 的“脑内笔记”——把过去所有帧压缩成一个固定维度的向量,每来一帧就结合新信息更新它,并基于它输出判断。它不存原始像素(A 错),不是只存单帧(C 错),更不是训练标签(D 错)。

Q4. Transformer 在线推理中,因果掩码(Causal Mask)矩阵 M 的作用是什么?

单选题 · mid

  • A.提升模型在训练时的收敛速度
  • B.让注意力只能覆盖当前及之前的位置,未来位置权重为 0← 正确答案
  • C.减少参数量,让模型更轻量
  • D.把视频帧压缩成低分辨率

答案:B。因果掩码把未来位置的注意力分数设为负无穷,softmax 后权重归零,使每个位置只能 attend 到历史位置。这是 Transformer 支持在线推理的前提。它不是加速训练(A)、不是减少参数(C)、也不是降分辨率(D)。

Q5. 以下哪些手段能有效降低在线动作检测的端到端延迟?

多选题 · mid

  • A.用 TensorRT 做 INT8 量化加速模型推理← 正确答案
  • B.增大滑动窗口长度以获取更多上下文
  • C.缓存滑动窗口重叠区域的特征,避免重复提取← 正确答案
  • D.把模型换成一个更深更强的 ResNet-200

答案:AC。量化(A)和特征缓存(C)都直接减少计算量,降低延迟。增大窗口(B)增加推理耗时,更深模型(D)也更慢。像解说员想提速,应该是“提前背熟资料”(缓存)和“加快语速”(量化),而不是“回忆更久远的事”(长窗口)或“查阅更厚的词典”(更深模型)。

Q6. 在线动作检测中,光流特征主要描述的是视频的什么信息?

单选题 · mid

  • A.单帧图像的色彩分布
  • B.像素在帧间的运动方向和速度← 正确答案
  • C.视频的音频信号强度
  • D.画面的整体亮度均值

答案:B。光流刻画相邻帧之间像素的位移矢量场,表达“谁在动、往哪动、动多快”,相当于解说员眼中的动态轨迹。它不是色彩统计(A)、不是音频(C)、也不是亮度(D)。动作识别中光流能补充 CNN 单帧特征的动态信息。

Q7. 在延迟预算紧张的场景(如直播审核),合理的工程策略有:

多选题 · hard

  • A.采用轻量主干网络提取帧特征← 正确答案
  • B.每隔 k 帧推理一次,中间帧沿用上次结果← 正确答案
  • C.使用完整视频离线后处理,保证最高精度
  • D.在边缘端部署模型,避免视频上传云端延迟← 正确答案

答案:ABD。轻量网络(A)和跳帧推理(B)都是经典的延迟-精度折中手段;边缘部署(D)省去网络传输延迟,也是有效方案。C 是离线处理,完全违背在线实时要求。注意 B 虽然有精度损失,但在“延迟预算紧张”的前提下是合理折中。

Q8. 在线动作检测输出结果通常采用什么形式?

单选题 · easy

  • A.直接输出动作的起始帧和结束帧标签
  • B.输出视频的整体分类标签
  • C.每帧输出各动作类别的概率分布,取高置信者判断← 正确答案
  • D.输出下一个动作的预测文本描述

答案:C。在线检测是逐帧流式输出,每帧产生一个概率向量,如 [挥手 0.7, 跳跃 0.2],超过阈值即判为正在做某动作。它不输出时间区间标注(A),因为动作可能还在进行中;也不是整个视频分类(B);更不是预测未来文本(D)。

Q9. 关于“延迟-精度曲线”的说法正确的是:

多选题 · hard

  • A.一般来说,延迟越高,可用信息越多,精度越高,但会逐渐饱和← 正确答案
  • B.曲线存在拐点,拐点之后提升延迟对精度帮助不大← 正确答案
  • C.精度和延迟完全无关,由模型参数量单方面决定
  • D.工程上选点应结合业务需求,在拐点附近找“甜点区”← 正确答案

答案:ABD。精度-延迟曲线通常单调上升但斜率递减,最终饱和(A、B 对)。C 明显错误,窗口、模型规模、采样率都同时影响精度和延迟。选型时要根据业务的实际延迟预算决定甜点(D),比如直播审核要 300ms 以下,安防回查允许 3 秒。

Q10. 在线推理中,Transformer 的 KV 缓存技术的主要作用是:

单选题 · hard

  • A.将历史帧的 Key 和 Value 结果缓存下来,新帧只计算自己的 QKV 并与缓存做注意力计算← 正确答案
  • B.用字典存储所有视频帧的原始像素,减少内存占用
  • C.将训练数据缓存到显存中,加速训练过程
  • D.对模型权重做哈希缓存,避免重复加载

答案:A。KV 缓存是把历史位置的 Key、Value 注意力向量保存下来,新帧到来时只需计算当前帧的 Q、K、V,再与缓存的 K/V 拼接做注意力。这避免了每个新帧都重新计算全部历史位置的 K/V,是 Transformer 支持线性时间在线推理的关键。B、C、D 都与 KV 缓存的语义无关。