开学第一天,班主任张老师还没见到学生们的脸,只在报到时听过他们录的一句“大家好,我是×××”。他手里攥着一本厚厚的声音点名册。上课铃一响,门外有人喊“老师好!”张老师头也不抬:“李小明,大点声。”全班哄堂大笑——他只听声音,就把人认出来了。 这就是说话人识别(Speaker Identification,简称 SID):机器像张老师一样,听一句话,就能从“声音档案库”里找出这是谁在说。这篇文章会用“声音点名册”这个比喻,带零基础读者走一遍完整流程:声音档案怎么录、声音“指纹”怎么提取、机器怎么比对、点名册怎么维护、遇上嘈杂教室怎么办,以及如何评价张老师点名准不准。

岗位关联

掌握说话人识别 SID,你就拥有了声纹系统里最核心的“找谁”能力,直接支撑会议纪要分人、客服实名路由、多人通话分析等落地场景,是语音技术工程师的必备技能。

目录
  1. 可视化演示
  2. SID 与 SV:点名还是核对证件
  3. 说话人辨识流程:从一句话到一张脸
  4. 声纹嵌入模型:把声音压缩成指纹
  5. 注册库管理:维护声音点名册
  6. 部署实战难点:在嘈杂教室找声音
  7. 评价与调优:张老师的期中考试
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示说话人识别SID的完整工作流程:从语音输入到声纹嵌入再到注册库匹配辨识身份,以及SID的1:N辨识与SV的1:1验证任务对比。

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

说话人辨识完整流程 语音经特征提取网络编码为固定维度声纹嵌入向量 嵌入向量与注册库中所有模板计算余弦相似度 取相似度最高的注册者作为辨识结果 cos(x, eᵢ) → argmax SID是1:N的身份辨识任务。

SID 与 SV:点名还是核对证件

张老师有两个经典场景。场景一:教室里有人喊“老师好”,他要在 40 本声音档案里找出这是谁,这是“点名”;场景二:保安称自己是“王小明家长”,张老师只需点头或摇头,这是“核对证件”。同样是处理声音,前者是从一堆人里挑一个(1:N 辨识),后者只判断是不是(1:1 验证)。本文主角 SID(说话人识别)就是场景一:给定一段语音,从已注册的说话人库中找出那个说话人的身份,回答“这是谁”。

SID 和 SV 不是两套割裂的技术,而是互通的。把验证的阈值拿出来,对库内所有说话人逐一打分、排序,取分数最高者并判断是否超过阈值,验证就“升级”成了辨识;反过来,当注册库里只有一个人时,SID 就自然退化为 SV。所以很多商用系统内部用同一套模型,只是任务封装不同:门禁用 SV,会议纪要分人用 SID。

在数学上,SID 的决策可以写成:

回到点名场景:张老师点名的本事,正是从“认人”升级到了“找人”。库越大,可比对的抽屉越多,挑战也越大——这就引出了完整的辨识流程。

y^=arg⁡max⁡i∈{1,…,N}s(x,ei)\displaystyle \hat{y}=\arg\max_{i\in\{1,\dots,N\}} s(\mathbf{x},\mathbf{e}_i)
公式含义:把所有人的声音指纹贴好名字放在抽屉里,听到一句话就拿出“查询指纹”和每个抽屉里的指纹比相似度,谁最像就选谁。
  1. 候选集合注册库里有 $N$ 个说话人,每个说话人 $i$ 对应一个声音模板向量 $\mathbf{e}_i$,相当于点名册上的一页。
    i∈{1,…,N}\displaystyle i\in\{1,\dots,N\}
  2. 逐一打分用相似度函数 $s(\cdot,\cdot)$ 计算待识别语音向量 $\mathbf{x}$ 与每个模板的匹配分数,分数越高越可能同一个人。
    s(x,ei)\displaystyle s(\mathbf{x},\mathbf{e}_i)
  3. 取最大值$\arg\max$ 表示在所有分数中挑最大者,返回对应的下标 $i$,得到系统认定的身份。
    arg⁡max⁡i\displaystyle \arg\max_{i}
  4. 输出身份$\hat{y}$ 就是最终答案——“这句话属于第 $i$ 位说话人”,注意这是闭集假设下的结果。
    y^\displaystyle \hat{y}

说话人辨识流程:从一句话到一张脸

张老师听到“老师好”后,不会立刻翻点名册,而是先“掏耳朵”:忽略翻书声、窗外车流、同桌嘀咕,只把干净的人声捞出来。这一步叫语音预处理,包括静音切除、噪声抑制、语音活动检测(VAD,先判断哪段是人在说话)。接着,他把这段语音切成若干小段,每 10~25 毫秒算一组声学特征(如 MFCC 倒谱系数),等于把声音的轮廓描出来。做完这两步,才轮到“指纹比对”。

标准的 SID 流程有四个环节:预处理(降噪、去静音)→ 特征提取(分帧计算声学特征)→ 嵌入编码(把整段变长语音压缩成一个固定维度的声纹向量 $\mathbf{q}$)→ 打分与决策(与注册库中每个向量算相似度,再套阈值判断是否接受)。前两步让系统“听清”,后两步让系统“认出”。

嵌入编码后,最常用的打分方式是余弦相似度:

张老师其实不需要“放大音量”,他只需要比较两个声音箭头指向是否一致。这就是为什么注册时轻声细语、识别时正常说话,只要音色本质没变,依然能认出同一个人。

s=q⋅e∥q∥2∥e∥2\displaystyle s=\frac{\mathbf{q}\cdot\mathbf{e}}{\lVert\mathbf{q}\rVert_2\lVert\mathbf{e}\rVert_2}
公式含义:两个声音指纹都画成高维空间里的箭头,夹角越小,余弦值越接近 1,说明越像同一个人。
  1. 向量点积把查询向量 $\mathbf{q}$ 和注册模板 $\mathbf{e}$ 逐位相乘再求和,结果体现两个向量方向的一致程度。
    q⋅e\displaystyle \mathbf{q}\cdot\mathbf{e}
  2. 模长归一除以两个向量各自的 L2 模长 $\lVert\mathbf{q}\rVert_2$ 和 $\lVert\mathbf{e}\rVert_2$,相当于把箭头的长短拉齐,只保留方向信息。
    ∥q∥2∥e∥2\displaystyle \lVert\mathbf{q}\rVert_2\lVert\mathbf{e}\rVert_2
  3. 数值范围余弦值落在 $[-1,1]$,越接近 1 越像;实际系统中分数通常被映射为正的百分比方便展示。
    s∈[−1,1]\displaystyle s\in[-1,1]

声纹嵌入模型:把声音压缩成指纹

张老师怎么记住 40 个人的声音?他绝不会背下整段波形——太占脑容量了。他只记几个关键点:音调是偏高还是偏低、语速是急促还是从容、咬字有没有特殊习惯。这几个数字串在一起就是“声音指纹”,学名叫嵌入向量(embedding)。每个说话人,在高维空间里就是一个点。

现代声纹系统的主流方案是说话人嵌入模型。输入语音先分帧,每帧送给一个帧级编码器——通常是 TDNN、ResNet 或 ECAPA 这类神经网络——输出一长串帧级向量 $\mathbf{h}_1,\mathbf{h}_2,\dots,\mathbf{h}_T$。但每一帧只代表 20 毫秒的局部信息,一长串向量长短不一,没法直接当指纹用。这时需要一个池化层(pooling layer),把 $T$ 个向量汇总成一个固定长度的向量。最经典的是统计池化:

训练这类模型常用 AM-Softmax 或 AAM-Softmax(ArcFace)损失函数,它在分类边界的夹角上加入一个“角度间隔”,逼着模型把同一说话人的样本在球面上聚成一个团、不同说话人的团彼此推开。正如张老师记住的不是每个字,而是说话习惯——同桌模仿你读课文也许骗得过语音转写,却骗不过熟悉你音色的张老师。

μ=1T∑t=1Tht,σ=1T∑t=1T(ht−μ)2\displaystyle \boldsymbol\mu=\frac{1}{T}\sum_{t=1}^{T}\mathbf{h}_t,\qquad \boldsymbol\sigma=\sqrt{\frac{1}{T}\sum_{t=1}^{T}\left(\mathbf{h}_t-\boldsymbol\mu\right)^2}
公式含义:一节课 45 分钟有几千帧,就像几千个成绩,最终只统计成“平均分”和“波动分”两个数,既保留整体规律,又不被长短不一的语音难住。
  1. 帧级序列$\mathbf{h}_t$ 是第 $t$ 帧语音经过编码器得到的局部向量,总共 $T$ 帧,$T$ 随语音长度变化。
    t=1,2,…,T\displaystyle t=1,2,\dots,T
  2. 均值池化对所有帧向量求平均得到 $\boldsymbol\mu$,描述说话人最稳定的音色基调,类似“平均分”。
    μ=1T∑t=1Tht\displaystyle \boldsymbol\mu=\frac{1}{T}\sum_{t=1}^{T}\mathbf{h}_t
  3. 标准差池化计算每帧相对均值的波动得到 $\boldsymbol\sigma$,刻画说话习惯的动态变化,类似“起伏大不大”。
    σ=1T∑t=1T(ht−μ)2\displaystyle \boldsymbol\sigma=\sqrt{\frac{1}{T}\sum_{t=1}^{T}\left(\mathbf{h}_t-\boldsymbol\mu\right)^2}
  4. 拼接输出把 $\boldsymbol\mu$ 和 $\boldsymbol\sigma$ 拼接起来,再接一层线性映射,得到 128 或 192 维的最终嵌入向量。
    e=Concat(μ,σ)\displaystyle \mathbf{e}=\text{Concat}(\boldsymbol\mu,\boldsymbol\sigma)

注册库管理:维护声音点名册

声音点名册不是开学建一次就完事。有转学生来,要加一页;有人休学,要撕掉一页;还有双胞胎声音太像,得把两页钉在一起备注“容易混淆”,防止点名时认错人。这就是注册库管理的日常。

注册建档(enrollment)是第一步:新说话人录 5~10 条语音,逐条输入嵌入模型得到多个向量,再聚合成一条注册模板存进库中,同时记录姓名、注册时间等元信息。生产环境里,库是“活”的:每天都有新客户、新成员加入,系统不能为了加一个人就停机重训模型,所以需要增量注册——只向库中追加新向量,不动旧数据;当库大到几百万规模时,还用 FAISS 这类向量检索引擎把相似度检索从逐一遍历变成近似最近邻查找,把耗时从线性降到对数级别。

一条更稳的注册模板,来自对同一人多段语音取平均:

删除与封禁同样关键:用户注销,系统要立即移除模板并重建相关索引,防止旧数据被冒用。大规模库中还要定期做聚类去重——像“把双胞胎的两页档案合并”一样,用聚类算法对库内模板互相打分,相似度极高的档案视为重复注册,人工确认后合并。张老师经验再丰富,如果点名册字迹潦草、长期不更新,照样会点错人。

e=1K∑k=1Ke(k)\displaystyle \mathbf{e}=\frac{1}{K}\sum_{k=1}^{K}\mathbf{e}^{(k)}
公式含义:一个人录 $K$ 条,把 $K$ 个嵌入逐位求平均,单次录音的偶然因素(咳嗽、语气、环境差异)被抹平,得到更接近“标准音色”的档案。
  1. 多次采样同一个说话人录 $K$ 条语音,模型分别输出 $K$ 个嵌入向量 $\mathbf{e}^{(1)},\mathbf{e}^{(2)},\dots,\mathbf{e}^{(K)}$。
    e(k),k=1,…,K\displaystyle \mathbf{e}^{(k)}, \quad k=1,\dots,K
  2. 逐元素平均对 $K$ 个向量的每一位分别求和再除以 $K$,得到平均嵌入。
    1K∑k=1Ke(k)\displaystyle \frac{1}{K}\sum_{k=1}^{K}\mathbf{e}^{(k)}
  3. 存库使用$\mathbf{e}$ 作为该说话人唯一的注册模板存入库中,后续查询只与它比对。
    e∈Rd\displaystyle \mathbf{e}\in\mathbb{R}^{d}

部署实战难点:在嘈杂教室找声音

张老师在真实课堂点名,教室永远不是录音棚:窗外有施工声、同桌在嘀咕、麦克风离得远。部署说话人识别系统时,最普遍的挑战就是噪声鲁棒性。工程上常用信噪比(SNR)衡量语音里有效声音与背景噪声的功率比:

对抗噪声的手段分两端:训练端做多条件数据增强——给干净语音加各种噪声、混响、变速,让模型见过“菜市场里的张老师”;推理端部署前端降噪和 VAD,先定位人声片段再提取特征,相当于张老师“把手拢在耳朵边”。

除了噪声,部署还要跨过三道坎。一是跨域失配:模型用手机录音训练,却要识别座机、会议麦克风甚至网络压缩后的语音,采集信道变了会导致嵌入分布漂移,常用域自适应、信道归一化缓解;二是说话人重叠——会议室里两人同时说话,系统先要做说话人分离(把重叠的音频拆成单人轨道),再对每一条轨道做 SID;三是冷启动:新注册用户只有一句欢迎语音,注册向量不稳,识别很容易误判,工程上常用延迟入库、等收集到更多语料再建档。教室越真实,考验越大;能在大噪声下精准点名的张老师,才是真正靠谱的声纹系统。

SNR=10log⁡10PsPn\displaystyle \text{SNR}=10\log_{10}\frac{P_{\text{s}}}{P_{\text{n}}}
公式含义:信噪比越高,语音越干净;降到 0dB 以下时,信号功率比噪声还弱,再强的模型也难发挥。
  1. 信号功率$P_{\text{s}}$ 是有效人声的平均功率,代表“张老师要听的那句话”的能量。
    Ps\displaystyle P_{\text{s}}
  2. 噪声功率$P_{\text{n}}$ 是背景噪声的平均功率,代表“教室杂音”的能量。
    Pn\displaystyle P_{\text{n}}
  3. 对数比求功率比后取以 10 为底的对数再乘 10,把比值映射为分贝(dB),0dB 表示声音和噪声等强。
    10log⁡10PsPn\displaystyle 10\log_{10}\frac{P_{\text{s}}}{P_{\text{n}}}

评价与调优:张老师的期中考试

期中考试了,教务处要考察张老师点名本领。考核分两类错误:漏报(应到的人没被认出来,把人拒之门外)和误报(不是本班的人被当成自己人放进来)。漏报和误报是一对冤家:把接受阈值调严,谁都进不来,漏报率飙升;调松,外来者随意混入,误报率飙升。EER(等错误率,Equal Error Rate)就是寻找一个神奇阈值点,让两种错误恰好相等:

实际操作中,工程师会遍历所有可能的阈值,画出 DET 曲线(漏报率随误报率变化的曲线),曲线越靠近左下角系统越强,EER 正好是曲线与对角线的交点。除了 EER,还要看 Top-1 识别准确率——在库规模从 100 到 10000 不断增大时,准确率是否稳健地下降;最后做混淆分析:哪些说话人之间总被认错。答案往往是音色相近的几组人,这时就该给这些说话人补充注册语音,或换用能提取更细粒度音色信息的模型结构。张老师也会定期翻看点名记录:谁和谁容易混,就在点名册上多记几笔特征备注。

EER=PFA(τ∗)=PFR(τ∗)\displaystyle \text{EER}=P_{\text{FA}}(\tau^{*})=P_{\text{FR}}(\tau^{*})
公式含义:误报率曲线和漏报率曲线在某个阈值处相交,交点对应的错误率就叫 EER。EER 越低,说明系统“既不放走坏人、也不冤枉好人”的能力越强。
  1. 误报率$P_{\text{FA}}(\tau)$ 是阈值取 $\tau$ 时把冒名者错误接受的比例,阈值越宽松它越高。
    PFA(τ)\displaystyle P_{\text{FA}}(\tau)
  2. 漏报率$P_{\text{FR}}(\tau)$ 是把真正的说话人错误拒绝的比例,阈值越严格它越高。
    PFR(τ)\displaystyle P_{\text{FR}}(\tau)
  3. 相等点存在一个特殊阈值 $\tau^{*}$ 使两者相等,这个共同取值就是 EER。
    τ∗:PFA(τ∗)=PFR(τ∗)\displaystyle \tau^{*}: P_{\text{FA}}(\tau^{*})=P_{\text{FR}}(\tau^{*})

AI 应用场景

会议记录分人

阶段:语音预处理 + SID 推理

解决的问题:传统会议纪要只记录“说了什么”,不记录“谁说的”,整理时要人工反复听音频、对照人声猜测发言人,极其耗时。接入 SID 后,系统先把会议录音分段、分离重叠语音,再对每段语音做 1:N 辨识,自动打上“张总:本季度营收增长 15%”,让纪要直接按发言人归档。

具体案例:某在线会议软件上线“发言人标签”功能:会前参会人各自录 30 秒语音完成注册,开会时系统对每一句话实时辨识说话人,会后导出的纪要自动带颜色区分发言人。实测在 8 人会议、普通笔记本麦克风环境下,Top-1 准确率达到 93%。

智能客服 VIP 路由

阶段:注册库管理 + 阈值决策

解决的问题:VIP 客户打进客服热线,传统 IVR 靠输入会员号或验证身份证确认身份,步骤多、体验差且容易被冒用。利用 SID,系统在客户一开口的 3 秒内完成 1:N 辨识,命中且相似度超过高阈值就直接路由到专属坐席,并在屏幕上弹出客户档案。

具体案例:某银行信用卡客服在电话接通瞬间对客户语音做辨识,注册库里存有 500 万已签约客户的声纹模板。VIP 客户无需输密码,系统提示“王女士您好,已为您转接贵宾专线”,平均接通等待时间从 40 秒降到 8 秒。

多人通话分析

阶段:模型部署 + 鲁棒性优化

解决的问题:客服质检、刑侦分析等场景需要分清“哪句话是谁说的”,尤其在电话信道下存在压缩失真和环境噪声。系统先做信道归一化与降噪,再做说话人分割聚类,最后配合 SID 给出每个人在通话中的发言时长、说话顺序等结构化数据,大大降低人工质检成本。

具体案例:某保险公司的双人通话录音质检系统,用 SID 自动区分客户与坐席角色,并进一步识别出“金牌坐席”和“新手坐席”在沟通节奏上的差异,据此优化培训题库。

Python 演示

python68 行
import numpy as np  class SpeakerLibrary(object):    """说话人注册库: 保存每个说话人的声纹嵌入向量"""     def __init__(self, dim=64, threshold=0.72):        self.dim = dim        self.threshold = threshold        self.speakers = {}     def register(self, name, embedding):        norm = embedding / (np.linalg.norm(embedding) + 1e-8)        self.speakers[name] = norm     def delete(self, name):        if name in self.speakers:            del self.speakers[name]     @staticmethod    def _cosine(a, b):        return float(np.dot(a, b))     def identify(self, query):        q = query / (np.linalg.norm(query) + 1e-8)        best_name, best_score = None, -1.0        for name, emb in self.speakers.items():            score = self._cosine(q, emb)            if score > best_score:                best_score = score                best_name = name        accepted = best_score >= self.threshold        return best_name, best_score, accepted     def verify(self, claimed_name, query):        if claimed_name not in self.speakers:            return False, 0.0        q = query / (np.linalg.norm(query) + 1e-8)        score = self._cosine(q, self.speakers[claimed_name])        return score >= self.threshold, score  def main():    rng = np.random.default_rng(42)    centers = {        "alice": rng.normal(size=64),        "bob": rng.normal(size=64),        "carol": rng.normal(size=64),    }    lib = SpeakerLibrary()    for name, center in centers.items():        utterances = np.stack([center + 0.1 * rng.normal(size=64) for _ in range(3)])        lib.register(name, utterances.mean(axis=0))     alice_query = centers["alice"] + 0.05 * rng.normal(size=64)    who, score, ok = lib.identify(alice_query)    print("identify alice ->", who, "score=%.3f" % score, "accepted=", ok)     stranger = rng.normal(size=64)    who2, score2, ok2 = lib.identify(stranger)    print("identify stranger ->", who2, "score=%.3f" % score2, "accepted=", ok2)     ok3, score3 = lib.verify("bob", alice_query)    print("verify bob with alice voice ->", ok3, "score=%.3f" % score3)  if __name__ == "__main__":    main()
目的:用 64 维随机向量模拟声纹嵌入,演示 1:N 辨识(identify)与 1:1 验证(verify)的完整流程。
  1. utterances = np.stack([center + 0.1 * rng.normal(size=64) for _ in range(3)])模拟同一人录 3 条语音得到的嵌入,叠加小噪声代表每次录音的差异。
  2. lib.register(name, utterances.mean(axis=0))3 条语音取平均后入库,对应正文“多段注册平均”公式。
  3. norm = embedding / (np.linalg.norm(embedding) + 1e-8)归一化为单位向量,这样点积就等于余弦相似度,加 1e-8 防止除零。
  4. for name, emb in self.speakers.items():遍历注册库中每个说话人,这就是 1:N 的核心循环。
  5. accepted = best_score >= self.threshold最高分也要过阈值才接受,库外陌生人在这里被拦下,这是“开集辨识”的关键。
  6. ok3, score3 = lib.verify("bob", alice_query)1:1 验证只与声称的 Bob 比对,返回布尔结果和相似度。

常见误区

误区很多人第一次听到“说话人识别”,以为就是把语音转成文字,和“语音转写”是一回事。我当初也这么想——都是把声音交给模型,返回一个结果嘛。

正解两者目标完全不同。语音识别(ASR)回答“说了什么”,关心内容;说话人识别(SID)回答“谁在说”,关心音色和说话习惯。就像张老师既能听写出你朗读的课文,也能分辨这是你读的还是弟弟读的——前者靠文字内容,后者靠声音指纹,模型和特征都不同。

为何常见:两者都叫“语音 X 识别”,都处理音频,名字太像,初学者很容易把“识别内容”和“识别身份”混为一谈。

误区认为注册就是“按一下录音键说句话就行”,环境嘈杂、声音太小、只录了 2 秒也照样能建档案,反正模型很智能。

正解注册语音的质量直接决定识别上限。张老师建声音档案时,如果教室里吵吵闹闹、学生又只肯嘟囔半句,这页档案将来必然不准。工程上要求 5~10 条干净语音、每个说话人覆盖不同时间段(早中晚音色有细微差异),再用平均得到稳定模板。注册语音越脏,后面的相似度打分越不可信。

为何常见:体验过手机上的“声纹解锁”只录一遍就能用,误以为生产系统的注册流程也这么随意,其实消费级产品做了大量兜底和重试策略。

误区认为 SID 系统的核心就是模型,注册库只是“存向量”的数据库,加人、删人、查重都是次要的,随便写个列表就行。

正解库是系统的“点名册”,管理不善会让好模型白费。向量索引没更新,新注册的人永远查不到;重复注册让同一人占多页,辨识结果随机漂移;离职人员的旧模板不删,冒用风险极高。实际工程中,注册库的增量更新、聚类去重、索引重建往往比训练模型更耗时。张老师本领再强,翻一本顺序乱掉、多页重复的点名册也会点错人。

为何常见:教程和论文大多聚焦模型结构,注册库属于“工程琐事”,少被谈起,导致学习者低估了它。

误区系统上线后发现误报多,第一反应是“把阈值调高一点”,调完发现漏报又上来了,于是一会儿调高一会儿调低,凭感觉打补丁。

正解阈值只是决策层的旋钮,它调节的是“谨慎程度”,不是“模型能力”。如果 EER 本身很高,说明嵌入特征区分度不够,调阈值只是把错误从误报挪到漏报。正确做法是先看 DET 曲线和混淆分析:哪些人总被认错?是噪声、信道还是注册语音太少?针对性增强数据、补充注册、升级模型,才是治本。张老师如果点名总出错,该练的是“听力”,而不是把“及格线”从 60 分改成 90 分。

为何常见:阈值改一个数字立竿见影,最容易操作,容易让人误以为找到了根本解法。

误区既然两者都用声纹、都算相似度,那 SID 和 SV 应该只是同一个东西的两种叫法,简历上写哪个都行。

正解SID 是 1:N 的“找谁”问题,SV 是 1:1 的“是不是他”问题。前者输出身份标签,后者输出是/否;前者的难点在于候选多、库规模大、陌生人要拒绝,后者的难点在于阈值校准和防冒用。把验证系统改成辨识系统,要加注册库索引、1:N 打分排序、开集拒绝三个模块,绝不是改个函数名。张老师“认出这是李小明”和“判断这是不是李小明”是两种能力,考核方式也不同。

为何常见:两者的模型和数学基础高度重合,面试和项目里也常放一起讲,容易让人忽略任务层的关键差异。

面试题

Q1. 说话人识别 SID 的核心任务是什么?

单选题 · easy

  • A.判断两段语音是否同一人(1:1)
  • B.从说话人库中找出语音是谁(1:N)← 正确答案
  • C.识别语音说了什么文字内容
  • D.判断语音是否来自真实的人

答案:B。SID 是 1:N 的身份辨识,给定一段语音去注册库里找“是谁”;A 是 1:1 验证,C 是语音识别 ASR,D 是活体检测,都不属于 SID 的定义。

Q2. 1:1 说话人验证(SV)的输出是什么?

单选题 · easy

  • A.说话人的身份编号标签
  • B.按相似度排序的候选列表
  • C.是或否的匹配判定结果← 正确答案
  • D.语音内容的文字转写结果

答案:C。SV 只回答“这个人是不是他声称的那个人”,输出是布尔值“是/否”;输出身份编号和候选列表的是 1:N 辨识,输出文字的是 ASR。

Q3. SID 决策用 argmax 从注册库中选人,它的含义是?

单选题 · mid

  • A.随机挑一个注册库里的说话人
  • B.选相似度最高的注册说话人← 正确答案
  • C.选相似度最低的注册说话人
  • D.直接拒绝所有候选说话人

答案:B。argmax 表示“取分数最大的那个下标”,系统把查询语音与每个注册模板算相似度后,最高分对应的说话人就是答案;随机、选最低、全拒绝都与 argmax 语义相悖。

Q4. 余弦相似度的取值范围是多少?

单选题 · mid

  • A.数值在 0 和 1 之间
  • B.数值在负 1 和 1 之间← 正确答案
  • C.数值从负无穷到正无穷
  • D.数值总大于等于 0 之间

答案:B。两个向量夹角从 0° 到 180°,余弦值对应从 1 到 -1,所以区间是 [-1, 1];0 表示正交不相关,负值表示方向相反。其他范围均不符合余弦函数定义。

Q5. 池化层(Pooling)在声纹嵌入模型中的作用是?

单选题 · mid

  • A.变长语音帧聚合成固定向量← 正确答案
  • B.把语音帧数量变得更多些
  • C.将说话内容转写为文字
  • D.提高麦克风采样率参数

答案:A。语音时长不定,帧级编码器输出长度不固定,池化层对所有帧向量做均值、标准差等统计,汇总成固定维度的嵌入,方便后续存库和比对;B、C、D 都不是池化层的职责。

Q6. 关于 EER(等错误率)的说法,正确的是?

单选题 · hard

  • A.等错误率此时误报等于漏报← 正确答案
  • B.识别准确率能达到百分百
  • C.注册时的平均相似度得分
  • D.训练阶段的损失函数大小

答案:A。EER 是误报率与漏报率相等时的交点取值,反映系统把“该拒的”和“该收的”弄错的比例;它不表示 100% 准确,也不是注册平均分或训练 loss,而是评价阈值选取效果的指标。

Q7. 注册语音为什么要做多段平均?

单选题 · mid

  • A.让单次录音偶然因素被抹平← 正确答案
  • B.增加注册库的内存占用
  • C.让语音内容变成文字
  • D.把噪声放大方便校准

答案:A。同一人每次录音都有咳嗽、语气、环境等随机差异,多条嵌入平均后得到更稳定的“标准音色”,降低误识别;增加内存、转文字、放大噪声都不是平均的目的。

Q8. 哪些属于声音注册库的日常管理操作?

多选题 · mid

  • A.新说话人注册时建立档案← 正确答案
  • B.删除离职人员的声纹记录← 正确答案
  • C.对重复注册做聚类去重← 正确答案
  • D.调节麦克风增益和音量

答案:ABC。注册建档、删除封禁、聚类去重都是库管理任务,保证点名册“活而准确”;调节麦克风增益属于前端音频硬件调优,不属于注册库管理的操作。

Q9. 部署说话人辨识系统时,哪些属于常见难点?

多选题 · hard

  • A.背景噪声干扰特征提取← 正确答案
  • B.录音设备不同造成失配← 正确答案
  • C.多人重叠同时讲话难分← 正确答案
  • D.数据集被压缩成图片

答案:ABC。噪声鲁棒性、跨域失配、说话人重叠都是 SID 部署的真实挑战,分别对应信噪比过低、训练与测试信道分布漂移、多人同时发言难以分离;数据集被压缩成图片不是语音任务中的问题。

Q10. 关于开集 SID 与闭集 SID 的说法,正确的是?

多选题 · extreme

  • A.开集需拒绝库外陌生人← 正确答案
  • B.闭集需拒绝库外陌生人
  • C.两者在身份上无任何差别
  • D.开集只需做 1 对 1 验证

答案:A。闭集假设“说话人一定在库内”,直接取 argmax 即可;开集还要用阈值拒绝库外陌生人,避免把一个陌生人的声音硬认成某个注册者。开集辨识比闭集多一道“拒绝”环节,两者有本质差别。