在机器学习里,我们经常默认一件事:数据越多,模型越聪明
比如,你想训练一个模型识别“跑步”“跳绳”“打篮球”,通常会希望准备成千上万段带标签的视频。

但现实常常不是这样。

很多时候,我们只能拿到很少的数据:

  • 一种罕见手术动作,只有几段示范视频
  • 某个工厂里的危险行为,历史上几乎没发生过
  • 某种特殊手语动作,采集成本很高
  • 新增的一类体育动作,刚出现不久,没有大规模数据集

这时候,就轮到 小样本行为识别(Few-Shot Action Recognition, FSAR) 登场了。它要解决的问题很直接:

只给模型看很少几个例子,它还能不能认出一种“行为”是什么?

这类任务和普通图像分类不同,因为它面对的是视频,而视频里最关键的不只是“看到了什么”,还有“这些内容是怎么随时间变化的”。近年来的综述也专门强调了这一点:小样本行为识别相较于小样本图像分类,最大的难点之一就在于时空信息建模


一、先别急着上公式:什么叫“行为识别”?

先从最朴素的例子开始。

假设你给电脑看一张图片,它要判断这是“猫”还是“狗”,这叫图像分类

而如果你给电脑看一段视频,它要判断这个人是在:

  • 挥手
  • 跑步
  • 拿起杯子喝水
  • 跳起并投篮

这就叫行为识别,也常叫动作识别(Action Recognition)

注意这里的关键区别:

  • 图像分类:看一个瞬间
  • 行为识别:看一段过程

举个生动一点的例子:

“拿起杯子”和“放下杯子”
某一帧画面里,看起来都可能是“手 + 杯子 + 桌子”。
但如果把前后几秒连起来看,你才能知道到底是“拿起”还是“放下”。

所以,行为识别不是只看“长什么样”,还要看“怎么动”。


二、那什么又叫“小样本”?

“小样本”就是:每个类别只有很少的标注样本

比如,我们要识别 5 种行为:

  1. 挥手
  2. 鼓掌
  3. 跳跃
  4. 坐下
  5. 起立

如果每一种行为只给模型 1 个样本,这叫:

  • 5-way 1-shot

如果每一种行为给 5 个样本,这叫:

  • 5-way 5-shot

这里有两个常见术语:

  • Way:一共有多少个类别
  • Shot:每个类别给多少个示例

这类设置通常会把样本分成两部分:

  • Support Set(支持集):给模型参考的少量已知样本
  • Query Set(查询集):让模型去判断的新样本

很多经典小样本方法都会采用这种“按任务切分”的 episodic training(情节式训练) 思路:每次训练不是喂一整个大数据集,而是不断构造“小任务”,让模型学会“看到几个例子后立刻分类”。


三、为什么“小样本行为识别”比想象中难?

这个问题非常重要。

如果你是初学者,可以把它理解成一句话:

它同时继承了“小样本学习难”和“视频理解难”这两种难。

1. 样本太少,模型容易“死记硬背”

深度学习模型参数很多,如果每类只给 1~5 个视频,它很容易记住训练样本,而不是学到真正的规律。
这就是常说的 过拟合(Overfitting)

比如:

  • 训练时“挥手”样本都发生在教室里
  • 测试时“挥手”发生在操场上

模型可能根本没学会“挥手”,只是误把“教室背景”当成了线索。

2. 行为是“时间过程”,不是单帧图片

“坐下”和“站起”某些帧很像。
“开门”和“关门”某些帧也很像。
真正的区别在于动作发生的顺序方向

所以,行为识别必须处理时间维度。

3. 同一种行为,不同人做出来差别很大

比如“鼓掌”:

  • 有人动作大
  • 有人动作小
  • 有人快
  • 有人慢
  • 有人坐着鼓掌
  • 有人站着鼓掌

这叫 类内差异大

4. 不同行为之间又可能非常像

比如:

  • “拿起杯子”
  • “端起碗”
  • “举起手机”

这些动作局部上很相似。
这叫 类间差异小

5. 视频里还有很多“无关信息”

比如:

  • 背景
  • 光照
  • 摄像机角度
  • 遮挡
  • 衣服颜色
  • 是否有别的人经过

这些都会干扰模型判断。

一些较新的方法会专门强调“时间关系”“局部与全局时空特征”的重要性。例如 STRM 这类方法的核心目标之一,就是增强类别区分能力,同时学习更高阶的时间表示。


四、用一个生活例子理解:人是怎么做“小样本行为识别”的?

假设你教一个小朋友认识“打招呼”这个行为。

你只给他看两段视频:

  • 视频 A:一个人举手挥了挥
  • 视频 B:另一个人笑着摆了摆手

然后你再给他看第三段新视频,问:

这是不是“打招呼”?

小朋友大概率能答对。

为什么?

因为人类会自动做几件事:

  1. 抓关键特征:手臂抬起、来回摆动
  2. 忽略无关因素:衣服、背景、男女老少
  3. 做相似度匹配:这个新动作像不像刚才那两个例子?

这其实就很像很多小样本方法的基本思想:

  • 先提取特征
  • 再比较相似度
  • 最后归类

五、小样本行为识别的核心思路,到底在做什么?

虽然论文很多,但对初学者来说,可以先把它们归纳成下面这条主线:

第一步:先把视频“变成特征”

模型不会直接理解“挥手”“跑步”,它会先把视频编码成一串数字,这叫 特征表示(Feature Representation)

你可以把它理解成:

一段视频 → 一个高维向量

这个向量里,希望包含:

  • 人的姿态信息
  • 物体变化信息
  • 时间顺序信息
  • 动作节奏信息

通常会用一个预训练的视频模型来提特征,比如 3D CNN、时序网络,或者近年的视觉大模型变体。很多新方法不是从零训练,而是先利用大模型或预训练骨干网络,再做任务适配,以减轻小样本场景下的过拟合问题。

第二步:把每一类的少量样本“总结成一个代表”

假设“挥手”类只有 3 个支持视频。
那我们可以把这 3 个视频的特征求平均,得到一个“挥手原型(prototype)”。

于是每一类都有一个“代表向量”。

第三步:新视频来了,就和这些“代表”比谁更像

比如测试视频的特征是 q

  • 它和“挥手原型”最像
  • 和“鼓掌原型”次之
  • 和“跳跃原型”最不像

那就判成“挥手”。

这就是很多 matching-based / prototype-based 方法最朴素的思路。
你可以把它理解成:

先记住每类长什么样,再看新样本更像谁。


六、一个极简例子:原型分类为什么有效?

假设我们已经把视频变成了二维特征,方便理解。

  • “挥手”这类的 3 个样本分别是:
    (1, 2)(2, 1)(1, 1.5)

那这个类别的原型可以近似看成:

(1.33, 1.5)

现在来了一个新视频,它的特征是:

(1.4, 1.6)

如果它离“挥手原型”最近,那就大概率属于“挥手”。

这和生活里“看谁最像谁”是一个道理。


七、给初学者的第一段代码:用 JavaScript 写一个“原型分类”示意

真实研究代码通常用 Python + PyTorch,但为了符合博客排版风格,这里我用 JavaScript 风格的示意代码 来讲清核心思想。

function average(vectors) {
    const dim = vectors[0].length;
    const result = new Array(dim).fill(0);

    for (const vec of vectors) {
        for (let i = 0; i < dim; i++) {
            result[i] += vec[i];
        }
    }

    for (let i = 0; i < dim; i++) {
        result[i] /= vectors.length;
    }

    return result;
}

function euclideanDistance(a, b) {
    let sum = 0;
    for (let i = 0; i < a.length; i++) {
        sum += (a[i] - b[i]) ** 2;
    }
    return Math.sqrt(sum);
}

function classifyByPrototype(supportSet, queryFeature) {
    const prototypes = {};

    for (const label in supportSet) {
        prototypes[label] = average(supportSet[label]);
    }

    let bestLabel = null;
    let bestDistance = Infinity;

    for (const label in prototypes) {
        const distance = euclideanDistance(queryFeature, prototypes[label]);
        if (distance < bestDistance) {
            bestDistance = distance;
            bestLabel = label;
        }
    }

    return bestLabel;
}

const supportSet = {
    wave: [
        [1.0, 2.0],
        [2.0, 1.0],
        [1.2, 1.5]
    ],
    clap: [
        [5.0, 5.0],
        [4.8, 5.2],
        [5.3, 4.9]
    ]
};

const queryFeature = [1.3, 1.7];

console.log(classifyByPrototype(supportSet, queryFeature)); // wave

这段代码做了三件事:

  1. 每个类别的支持样本先求平均,形成 prototype
  2. 新样本和每个 prototype 计算距离
  3. 距离最小的类别就是预测结果

这就是很多小样本方法最核心的“雏形”。


八、但真实世界没这么简单:视频特征怎么来?

上面的代码默认我们已经有了“视频特征向量”。
可现实里最难的部分,往往恰恰是:

怎么把一段视频编码成足够好的特征?

因为一段视频不只是很多帧堆起来,它包含:

  • 空间信息:这一帧里有什么
  • 时间信息:动作是怎么变化的
  • 局部信息:手、腿、物体接触区域
  • 全局信息:整个动作过程的节奏与结构

这也是为什么一些小样本行为识别方法会强调:

  • 局部帧级特征
  • 全局时间上下文
  • 时空关系建模

例如 STRM 这类方法就明确围绕“时空关系”展开设计。


九、初学者可以把主流方法分成哪几类?

如果你去读论文,会看到很多名字,但可以先粗略分成下面几类。

1. 基于匹配的方法(Matching-based)

核心思想是:

新视频和支持集视频,谁更像?

它们通常会做相似度比较,比如:

  • 欧氏距离
  • 余弦相似度
  • 原型距离
  • 关系网络打分

这类方法通常直观、可解释、适合入门

2. 基于元学习的方法(Meta-learning)

核心思想是:

不是直接学“分类器”,而是学“如何快速学会一个新任务”。

也就是说,模型要学会一种能力:

  • 以后遇到新类别
  • 只看几个样本
  • 就能很快适应

很多 few-shot 方法都会使用 episodic training,本质上就是在模拟“未来只给你几个样本”的场景。

3. 基于预训练 + 适配的方法

这类方法近几年非常常见。

先在大规模数据上训练一个通用模型,学到比较好的视频表示;
然后在小样本任务上只做轻量适配,而不是全部重训。

这样做的好处是:

  • 利用已有大模型的知识
  • 降低小数据下过拟合的风险

Task-Adapter 这类工作就属于很典型的“冻结主干、进行任务特定适配”的路线。


十、一个更生动的例子:为什么“时间”这么重要?

假设我们要区分两个动作:

  • 坐下
  • 站起

如果只截取中间某一帧,可能都只是“人 + 椅子 + 半蹲姿势”。

但如果看视频顺序:

  • 站立 → 弯腿 → 接触椅子 → 坐稳
    这是“坐下”

  • 坐着 → 身体前倾 → 用腿发力 → 站直
    这是“站起”

所以很多行为识别问题,真正的答案不是藏在某一帧里,而是藏在:

帧与帧之间的变化关系里

这也是为什么“行为识别”不能简单等同于“每帧做图像分类再投票”。


十一、第二段代码:一个“视频特征 + 原型分类”的简化流程

下面用更接近任务流程的方式写一段示意代码。仍然是 JavaScript 风格,重点不是运行,而是帮助理解整个 pipeline。

function extractVideoFeature(videoFrames) {
    // 这里只是示意:
    // 真实情况会由视频模型提取时空特征
    let motionScore = 0;
    let appearanceScore = 0;

    for (const frame of videoFrames) {
        motionScore += frame.motion;
        appearanceScore += frame.appearance;
    }

    return [
        motionScore / videoFrames.length,
        appearanceScore / videoFrames.length
    ];
}

function buildClassPrototype(videos) {
    const features = videos.map(video => extractVideoFeature(video));
    return average(features);
}

function cosineSimilarity(a, b) {
    let dot = 0;
    let normA = 0;
    let normB = 0;

    for (let i = 0; i < a.length; i++) {
        dot += a[i] * b[i];
        normA += a[i] * a[i];
        normB += b[i] * b[i];
    }

    return dot / (Math.sqrt(normA) * Math.sqrt(normB));
}

function predictAction(supportVideos, queryVideo) {
    const queryFeature = extractVideoFeature(queryVideo);
    let bestLabel = null;
    let bestScore = -Infinity;

    for (const label in supportVideos) {
        const prototype = buildClassPrototype(supportVideos[label]);
        const score = cosineSimilarity(queryFeature, prototype);

        if (score > bestScore) {
            bestScore = score;
            bestLabel = label;
        }
    }

    return bestLabel;
}

这段代码对应的思路是:

  • 一段视频先提取特征
  • 每个类别的多个支持视频形成原型
  • 查询视频和各类别原型计算相似度
  • 分数最高的类别就是预测结果

这就是“小样本行为识别”的最基本骨架。


十二、真实研究里还会解决哪些更细的问题?

到了这里,你已经能理解“它在干什么”了。
再往下一步,就是理解研究人员在优化哪些细节。

1. 怎么减少支持集里的“坏样本”影响?

有些支持视频质量很差:

  • 拍糊了
  • 动作没做完整
  • 背景干扰太大

一些方法会引入注意力机制,降低坏样本权重。
例如 PAL 这类方法就讨论了如何应对支持集离群点和类别重叠问题。

2. 怎么更好地理解长时间动作?

像“投篮”“倒水”“开门”这类动作,并不是一个瞬时动作,而是一个连续过程。
有些方法会专门强化时间建模,甚至关注更细粒度的时间原子动作。

3. 能不能借助图文模型或大模型知识?

近年也出现了结合预训练视觉语言模型、任务适配模块等方向的方法,思路是把大模型已有的泛化能力迁移到小样本动作任务里。


十三、初学者最容易踩的几个误区

误区 1:以为“小样本”只是“数据少一点”

不是。
它不是从 10 万样本降到 1 万样本,而往往是:

  • 每类只有 1 个
  • 每类只有 5 个
  • 甚至是从未见过的新类别

误区 2:以为视频识别就是“逐帧识别”

不够。
行为识别关心的是动作过程,不是单帧标签投票。

误区 3:以为模型学到的是“动作本质”

很多时候,模型学到的是背景、摄像角度、衣服颜色这些捷径。
所以研究里非常重视泛化能力和抗干扰能力。

误区 4:以为论文只是“换个网络堆参数”

其实不少改进点都很具体:

  • 怎么抽取时序信息
  • 怎么比较支持集和查询集
  • 怎么避免少样本过拟合
  • 怎么利用预训练知识

十四、如果你现在想入门,建议怎么学?

给初学者一个实用路线:

第 1 步:先学懂三个基础概念

  • 图像分类
  • 视频动作识别
  • 小样本学习

第 2 步:理解 few-shot 的任务设置

重点搞清楚:

  • N-way K-shot
  • support/query
  • episodic training

第 3 步:先自己实现一个“原型网络”玩具版

哪怕不是真视频,只用二维向量做分类,也能帮助你建立直觉。

第 4 步:再去看真实论文

可以优先关注这些关键词:

  • prototype
  • matching
  • meta-learning
  • temporal modeling
  • adapter
  • CLIP / pretrained backbone

第 5 步:找开源代码跑通一个 baseline

目前公开实现并不总是很完整,但已经有一些共享代码库在整理和复现 few-shot action recognition 方法,适合做入门实验参考。


十五、用一句最通俗的话总结它

如果让我只用一句话解释“小样本行为识别”,我会这样说:

它是在教电脑:只看几个示范视频,也要学会认出一个动作。

难点不只是“样本少”,还包括:

  • 行为发生在时间里
  • 同类差异大、异类差异小
  • 视频噪声多
  • 容易过拟合

而主流方法的共同目标,就是:

学到一个好的视频表示,并让模型具备“少看几个例子就能快速判断”的能力。


十六、结语

小样本行为识别是一个很有代表性的方向,因为它很贴近真实世界:

现实世界里,数据并不总是充足;
真正昂贵、有价值、稀有的行为样本,往往恰恰是最少的。

所以,这个方向的价值不仅在于“论文很前沿”,更在于它回答了一个现实问题:

当数据不够时,机器还能不能学会理解人的动作?

答案是:可以,但前提是我们要让模型学会更聪明地“看”、更合理地“比”、更稳健地“泛化”。


参考阅读