想象你是一座城市的管理员:街道上挤满了建筑,有人住的宅子(人名)、地标广场(地名)、政府大院(机构名)。城市要对外发布地图,你必须先给这些“重要建筑”贴上分类门牌——这一步,在自然语言处理里就叫命名实体识别(NER)。 最早,你派出一队拿着手电筒的巡逻员,从左到右再从右到左扫视街道,照着“贴门牌手册”逐栋标注,这就是 BiLSTM-CRF 的朴素智慧。后来,档案馆请来一位阅遍全城史料的老先生,他只需看一眼街景就能判断建筑类别,这是 BERT 预训练带来的质变。最后,无人机升空全局俯瞰,无论大院套着小院,一次扫描全部框出,这是 GlobalPointer 对嵌套实体的终极解法。 这篇文章会沿着这条“门牌进化史”展开:从标注规则讲起,一路拆解三种方法的模型结构、关键公式与工程落地教训,帮你建立 NER 的完整认知地图。

岗位关联

掌握 NER 三大方法,等于拿到信息抽取与知识图谱构建的入场券——这是搜索、推荐、问答系统的地基能力,也是 NLP 算法工程师面试和实战的必考点。

目录
  1. 可视化演示
  2. 任务概述
  3. 标注体系
  4. BiLSTM编码
  5. CRF解码
  6. BERT预训练
  7. GlobalPointer
  8. 工程选型
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

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

BiLSTM-CRF架构 BiLSTM提取双向上下文特征 CRF建模标签转移约束 P = BiLSTM(x) + CRF transitions 经典NER架构

任务概述

城市管理局要绘制一张全市功能地图,第一步不是画路,而是给“值得标注的建筑”贴上门牌:住人的宅子、对外开放的广场、挂牌办公的大院。在自然语言处理里,这个“贴门牌”的动作就是命名实体识别(Named Entity Recognition,NER)——从一段自然语言中定位出具有特定意义的实体片段,并判断它的类别。

这套动作的价值贯穿整个 AI 应用链:知识图谱要靠 NER 从百科和公告中抽出头实体,搜索引擎要靠它高亮“人名/地名”提高点击率,客服系统要靠它识别用户话里的“产品名/订单号”才能做下一步意图处理。可以说,凡是需要从文本里“捞关键信息”的系统,第一站几乎都是 NER。

从技术脉络看,NER 的建模目标可以写成:在给定输入句子 X 的条件下,找到最合理的标签序列 Y。

所以“贴门牌”这件事要回答三个问题:哪些建筑值得贴(实体定义)、门牌怎么编码(标注体系)、用什么工具去贴(三大方法)。下面我们就从“门牌编码规则”说起。

Y^=arg⁡max⁡YP(Y∣X)\hat{Y} = \arg\max_Y P(Y \mid X)
这个公式的意思是:句子已经摆在那里,我们要在所有可能的“门牌标签组合”里,挑出概率最大的那一组。
  1. 输入句子 X把一句话切成一串词,X 就是这串词的集合。
    X=(x1,x2,…,xn)X = (x_1, x_2, \dots, x_n)
  2. 标签序列 Y每个词对应一个门牌标签,Y 就是这些标签组成的有序序列。
    Y=(y1,y2,…,yn)Y = (y_1, y_2, \dots, y_n)
  3. 取最大概率者\arg\max 表示在所有候选 Y 中选出条件概率最高的那个,作为最终标注结果。
    Y^=arg⁡max⁡YP(Y∣X)\hat{Y} = \arg\max_Y P(Y \mid X)

标注体系

门牌不能乱编,全市得有一套统一编码。最早的规则叫 BIO:B(Begin)代表一栋建筑的第一块门牌,I(Inside)代表建筑内部的延续门牌,O(Outside)代表路边普通路灯,不值得贴。比如“张三去北京大学读书”,切分成字后,标签可以是:张/B、三/I、去/O、北/B、京/I、大/I、学/I、读/O、书/O。

后来大家觉得还差点意思:单字实体(比如“京”单独指北京时)用 B 开头再直接接 O,边界感不够强。于是有了 BIOES 扩展:E(End)表示建筑最后一块门牌,S(Single)表示一整栋只有一块门牌的小屋。BIOES 对实体边界更敏感,在不少数据集上能小幅提升 F1。

有了编码规则,还得有“尺子”衡量贴得好不好。常用的尺子是精确率 P、召回率 R 和 F1。

规则和尺子都备齐了,接下来要看工具。第一代工具,是拿着手电筒的巡逻队——BiLSTM-CRF。

F1=2×P×RP+RF_1 = \frac{2 \times P \times R}{P + R}
F1 是精确率和召回率的调和平均:精确率怕“贴错”,召回率怕“漏贴”,F1 同时惩罚这两类错误,是 NER 最通行的总评分。
  1. 精确率 P在所有贴了门牌的建筑中,真正贴对的比例。
    P=贴对的实体数模型贴出的实体总数P = \frac{\text{贴对的实体数}}{\text{模型贴出的实体总数}}
  2. 召回率 R在真正值得贴的建筑中,被成功贴到的比例。
    R=贴对的实体数真实实体总数R = \frac{\text{贴对的实体数}}{\text{真实实体总数}}
  3. F1 调和平均当 P 和 R 都高时 F1 才高,避免模型“只贴少数稳的”或“乱贴一堆”。
    F1=2×P×RP+RF_1 = \frac{2 \times P \times R}{P + R}

BiLSTM编码

第一代巡逻队员的装备是一支“双向手电筒”。他从街头走到巷尾,记下每栋建筑左边的邻居;再从巷尾走回街头,记下右边的邻居。两条路线的记忆汇合在一起,就构成了这栋建筑最完整的“邻里画像”——这就是双向长短期记忆网络(BiLSTM)的直觉。

LSTM 之所以能“记住”,靠的是三扇门:遗忘门决定丢掉哪些旧记忆,输入门决定吸纳哪些新信息,输出门决定释放哪些记忆给下一个时刻。但单向 LSTM 有个天然缺陷:它只能看到左边的历史。于是人们把正向 LSTM 和反向 LSTM 的输出拼接起来,让每一个词的位置同时拥有左右两侧的上下文视野。

巡逻队记住了左右街景,但他贴门牌时有个毛病:可能前一栋贴“人名”,下一栋直接贴“地名内部”,闹出笑话。要让门牌贴得合规,巡逻队需要一本城管手册——CRF 层。

ht=[ h→t  ;  h←t ]h_t = [\, \overrightarrow{h}_t \; ; \; \overleftarrow{h}_t \,]
第 t 个词的最终表示,等于正向扫到它时的记忆向量和反向扫到它时的记忆向量,首尾相接拼在一起。
  1. 正向记忆从句子开头扫到第 t 个词时,LSTM 积累的“左侧上下文”。
    h→t=LSTM→(x1,…,xt)\overrightarrow{h}_t = \text{LSTM}_{\rightarrow}(x_1, \dots, x_t)
  2. 反向记忆从句子末尾扫到第 t 个词时,LSTM 积累的“右侧上下文”。
    h←t=LSTM←(xn,…,xt)\overleftarrow{h}_t = \text{LSTM}_{\leftarrow}(x_n, \dots, x_t)
  3. 向量拼接分号表示把两个向量首尾相接,得到同时携带左右信息的上下文向量 h_t。
    ht=[ h→t  ;  h←t ]h_t = [\, \overrightarrow{h}_t \; ; \; \overleftarrow{h}_t \,]

CRF解码

城管手册上写着一条铁律:门牌标签不能乱跳。“人名建筑”可以连排几间(B-PER 后跟 I-PER),但 B-PER 后面突然冒出 I-ORG(地名内部门牌)就是违规。这种“前一个标签到后一个标签是否合法”的规矩,就是条件随机场(CRF)的转移矩阵。

光有 BiLSTM 时,每个词的门牌是独立判断的——它会给“北”打一个高分给 B-ORG,给“京”打一个高分给 I-ORG,但完全不管两个标签连起来是否合理。CRF 出场后,把“发射分数”(BiLSTM 说该贴什么)和“转移分数”(城管手册说能不能这么接)加起来,构成整条路径的总分:

巡逻队加手册的组合,在中小规模任务上稳扎稳打。但手电筒的视野终究有限——它只能沿着街道一维地走,看不到建筑的“全貌气质”。于是城市请来了一位读过全城史料的老先生:BERT。

score(Y∣X)=∑t=1nEt,yt+∑t=1n−1Tyt,yt+1\mathrm{score}(Y \mid X) = \sum_{t=1}^{n} E_{t, y_t} + \sum_{t=1}^{n-1} T_{y_t, y_{t+1}}
整条标签路径的得分 = 每个词自身的贴牌分数之和 + 相邻两个标签的转移分数之和。得分最高的一条路径,就是最终答案。
  1. 发射分数E 是 BiLSTM 输出矩阵中的元素,表示第 t 个词贴上标签 y_t 的“底分”。
    Et,yt=BiLSTM 输出的第 t 行第 yt 列E_{t, y_t} = \text{BiLSTM 输出的第 t 行第 } y_t \text{ 列}
  2. 转移分数T 是 CRF 学到的转移矩阵,表示从标签 y_t 跳到 y_{t+1} 的合法程度,非法跳转会被训练成很大的负数。
    Tyt,yt+1=转移矩阵第 yt 行第 yt+1 列T_{y_t, y_{t+1}} = \text{转移矩阵第 } y_t \text{ 行第 } y_{t+1} \text{ 列}
  3. 累加与寻优把发射和转移逐项相加得到路径总分,再用维特比算法一次性动态规划出全局最优路径。
    Y∗=arg⁡max⁡Y(∑t=1nEt,yt+∑t=1n−1Tyt,yt+1)Y^* = \arg\max_Y \left( \sum_{t=1}^{n} E_{t, y_t} + \sum_{t=1}^{n-1} T_{y_t, y_{t+1}} \right)

BERT预训练

老先生年轻时通读过全城所有街区的档案:青砖的烧制年代、牌坊的雕刻风格、门墩的形状……他只需要扫一眼街景,就能判断这栋建筑是什么类别。这种“见识”,来自日复一日的海量阅读——对应到技术里,就是预训练。

BERT 的做法分两步。第一步是预训练:在 GB 级的无标注文本上,随机遮住 15% 的词,让模型根据上下文猜被遮住的词是什么。这个任务叫掩码语言模型(Masked Language Model,MLM)。第二步是微调:把预训练好的参数作为起点,在 NER 的标注数据上再训几个 epoch,输出层换成标签分类头。于是模型从“通用语言理解专家”变成了“贴门牌专家”。

老先生见多识广,但遇到“大院套小屋”的嵌套建筑(“北京大学”里藏着“北京”),老先生也得顺着门牌一行行找,费时费力。于是新一代工具登场:无人机全局扫描——GlobalPointer。

P(wi∣w1,…,wi−1,wi+1,…,wn)P(w_i \mid w_1, \dots, w_{i-1}, w_{i+1}, \dots, w_n)
这是掩码语言模型的核心目标:当第 i 个词被遮住时,模型要根据句子中所有其他词来预测它的真实身份。
  1. 被遮住的词w_i 是被随机掩码的目标词,模型看不到它。
    wi=被 [MASK] 替换的词w_i = \text{被 } [\text{MASK}] \text{ 替换的词}
  2. 上下文条件除了 w_i 之外的整句其余词,都作为预测的依据。
    {w1,…,wi−1,wi+1,…,wn}\{ w_1, \dots, w_{i-1}, w_{i+1}, \dots, w_n \}
  3. 条件概率模型输出每个候选词的概率,训练目标就是让正确词的概率最高。
    P(wi∣其余所有词)→max⁡P(w_i \mid \text{其余所有词}) \rightarrow \max

GlobalPointer

无人机升到高空,俯瞰整片街区。它不再沿着街道一栋栋走,而是直接问:任意两个点 i 和 j 围出来的那片区域,会不会是一座院子?如果是,就整体框出来。这种“任意区间直接配对”的思路,就是全局指针(GlobalPointer)的核心。

传统序列标注给每个词分配一个标签,天然只能表达“连续的一段”,遇到嵌套实体就手足无措:同一个“北”字,既属于地名“北京”,又属于机构名“北京大学”,一个标签根本装不下。GlobalPointer 换了个建模空间:对每一类实体,构造一个 n×n 的打分矩阵,矩阵中 (i, j) 位置的值,代表“从第 i 个词到第 j 个词构成该类实体的置信度”。

无人机能同时圈出大院子和小院子,嵌套实体不再是难题。但它的代价也很明显:要比较 n² 个区间,计算和显存压力都不小。于是我们来到最后一关——怎么给真实业务选工具。

s(i,j)=(Wqhi)⊤(Wkhj)ds(i, j) = \frac{(W_q h_i)^\top (W_k h_j)}{\sqrt{d}}
这个公式衡量的是:第 i 个词作为“起点”与第 j 个词作为“终点”之间的匹配程度。匹配分高,就框成一个实体区间。
  1. 编码向量h_i 和 h_j 是经过编码器(如 BERT)得到的第 i 词、第 j 词表示。
    hi,hj∈Rdh_i, h_j \in \mathbb{R}^{d}
  2. 投影变换W_q 把起点向量转成“查询”,W_k 把终点向量转成“键”,学习该从什么角度匹配头尾。
    qi=Wqhi,kj=Wkhjq_i = W_q h_i, \quad k_j = W_k h_j
  3. 点积打分内积越大,说明这两个位置越像一对合法的“头尾”;对每个实体类别各做一套打分。
    s(i,j)=qi⊤kjs(i, j) = q_i^\top k_j
  4. 缩放稳定除以 \sqrt{d} 防止维度高导致点积过大,让打分分布更平稳。
    qi⊤kjd\frac{q_i^\top k_j}{\sqrt{d}}

工程选型

不是每个城市都值得出动无人机。小镇街区派巡逻队加手册就够用,大城市才请老先生和无人机。选型不是“越新越好”,而是数据量、算力、时延、嵌套需求四者的权衡。

工程经验大致可以这样划:标注数据只有几千句、用 CPU 部署、要求毫秒级响应,BiLSTM-CRF 是最务实的选择——它轻量、稳定、易调试;如果数据量充足、有 GPU、追求榜单效果,BERT 或 BERT+CRF 是主流;如果业务文本里嵌套实体密集(地址解析、生物医学命名、法律条款),GlobalPointer 的优势就体现出来了。三种方法的计算复杂度对比很能说明问题:

回到我们的城市:巡逻队稳、老先生博学、无人机全知,但没有谁绝对最优。先看清自家街区的规模、预算和“建筑分布”,再决定出动哪支队伍。这,就是 NER 三大方法演进留给我们的最朴素心法。

TBiLSTM-CRF=O(n),TGlobalPointer=O(n2)T_{\text{BiLSTM-CRF}} = O(n), \qquad T_{\text{GlobalPointer}} = O(n^2)
n 是句子长度。BiLSTM-CRF 大致沿着句子扫一遍,GlobalPointer 要检查所有起止组合,所以句子越长,两者的开销差距越明显。
  1. 句子长度 n输入序列包含的词数,是复杂度分析的规模变量。
    n=序列长度n = \text{序列长度}
  2. 线性复杂度BiLSTM-CRF 对每个词只做常数次计算,整体随 n 线性增长。
    TBiLSTM-CRF=O(n)T_{\text{BiLSTM-CRF}} = O(n)
  3. 平方复杂度GlobalPointer 要打分所有 (i, j) 区间对,共约 n²/2 个候选,随 n 平方增长。
    TGlobalPointer=O(n2)T_{\text{GlobalPointer}} = O(n^2)

AI 应用场景

知识图谱构建中的实体抽取

阶段:数据准备与信息抽取

解决的问题:知识图谱的上游需要从海量百科、研报、公告中抽出“实体-关系-属性”,人工标注成本极高。传统规则模板只能覆盖固定措辞,换个说法就失效。用 BERT+CRF 微调后,模型能理解上下文语义,在长句和复杂表达中准确抽取出人名、机构名、地名,把非结构化文本转成结构化三元组的原料。

具体案例:某金融知识图谱项目,从 10 万份上市公司公告中抽取“公司名、股东名、高管名”。初期用规则命中率仅 65%,改用 BERT+CRF 微调后 F1 提升到 88%,新公告直接进入推理管线自动入库。

地址解析与嵌套实体识别

阶段:模型选型与推理上线

解决的问题:中文地址天然嵌套严重:“北京市海淀区中关村大街”中,“北京市”“海淀区”“中关村大街”层层嵌套。用传统序列标注只能抽出一段最外层,“海淀区”会丢失。GlobalPointer 用全局区间打分,一次性框出每层地址要素,再配合层级规则组装成标准行政区划。

具体案例:某电商物流系统每天处理 50 万条用户填写的不规范地址,使用 GlobalPointer 后嵌套地址要素召回率从 71% 提升至 93%,“省市区街”四级拆分准确率显著改善,送错率下降。

轻量级客服系统的实体识别

阶段:端侧推理与在线服务

解决的问题:在线客服机器人需要实时从用户消息中识别“产品名、订单号、业务类型”,但并发高、响应时间苛刻,且 GPU 资源有限。BiLSTM-CRF 在 CPU 上单条推理只需几毫秒,参数规模小,适合嵌入实时流水线。

具体案例:某银行智能客服将 BiLSTM-CRF 部署在 CPU 集群上,识别“转账/挂失/查余额”等意图下的关键实体,平均耗时 3ms,支撑日均百万次请求,成为高并发场景的轻量基座。

Python 演示

python92 行
# -*- coding: utf-8 -*-"""从零演示 NER 三大方法核心: BIO 标注, CRF 维特比解码, GlobalPointer 区间打分""" SENTENCE = "张三去北京大学读书"WORDS = list(SENTENCE)  # 简化: 按字切分TAGS = ["B", "I", "O"]  # BIO 标注体系  def build_entities(tags):    """把 BIO 标签序列还原成实体片段"""    entities = []    i = 0    while i < len(tags):        if tags[i] == "B":            j = i            while j + 1 < len(tags) and tags[j + 1] == "I":                j += 1            entities.append((i, j, "".join(WORDS[i:j + 1])))            i = j + 1        else:            i += 1    return entities  # 模拟 BiLSTM 输出的发射分数: 每行是 [B, I, O] 的得分EMIT = [    [0.9, 0.6, 0.1],  # 张    [0.7, 0.9, 0.2],  # 三    [0.1, 0.2, 0.9],  # 去    [0.9, 0.5, 0.1],  # 北    [0.5, 0.9, 0.2],  # 京    [0.2, 0.9, 0.3],  # 大    [0.1, 0.8, 0.3],  # 学    [0.1, 0.2, 0.9],  # 读    [0.2, 0.1, 0.9],  # 书] # CRF 转移矩阵: TRANS[prev][cur], 用大负数惩罚非法转移TRANS = [    # prev = B, cur: B / I / O    [-10.0, 1.0, 0.5],    # prev = I, cur: B / I / O    [-10.0, 1.0, 0.5],    # prev = O, cur: B / I / O    [1.0, -10.0, 0.5],]  def viterbi(emit, trans):    """维特比解码: 动态规划寻找全局最优标签路径"""    n = len(emit)    m = len(emit[0])    dp = [[-1e9] * m for _ in range(n)]    back = [[-1] * m for _ in range(n)]    for j in range(m):        dp[0][j] = emit[0][j]    for i in range(1, n):        for j in range(m):            for k in range(m):                score = dp[i - 1][k] + trans[k][j] + emit[i][j]                if score > dp[i][j]:                    dp[i][j] = score                    back[i][j] = k    tags = [0] * n    tags[-1] = max(range(m), key=lambda j: dp[-1][j])    for i in range(n - 1, 0, -1):        tags[i - 1] = back[i][tags[i]]    return tags  def global_pointer(emit, threshold=1.3):    """GlobalPointer 简化演示: 任意 (i, j) 区间打分, 支持嵌套"""    n = len(emit)    candidates = {}    for i in range(n):        for j in range(i, n):            score = emit[i][0] + emit[j][1]  # 头部取 B 分, 尾部取 I 分            if score > threshold:                candidates[(i, j)] = score    return candidates  if __name__ == "__main__":    tags = viterbi(EMIT, TRANS)    tag_names = [TAGS[t] for t in tags]    print("维特比标签:", tag_names)    print("抽取实体:", build_entities(tag_names))     print("\nGlobalPointer 候选区间:")    cands = global_pointer(EMIT)    for (i, j), s in sorted(cands.items(), key=lambda x: -x[1]):        print("  ", (i, j), "".join(WORDS[i:j + 1]), "得分", round(s, 2))
目的:用纯 Python 实现 BIO 标注、CRF 维特比解码和 GlobalPointer 区间打分,串起三大方法的核心逻辑。
  1. WORDS = list(SENTENCE)简化任务,按字切分句子,字符序列就是模型要标注的最小单元。
  2. build_entities(tags)把 B/I/O 标签流还原成连续的实体片段,对应“贴门牌后汇总建筑清单”。
  3. EMIT手工构造的发射分数矩阵,模拟 BiLSTM 对每个字的标签打分。
  4. TRANS转移矩阵用 -10.0 惩罚非法转移,比如 B 后面不能再跟 B。
  5. dp[i - 1][k] + trans[k][j] + emit[i][j]维特比的核心递推式:上一位置最优分 + 转移分 + 当下发射分。
  6. tags[-1] = max(range(m), key=lambda j: dp[-1][j])从最后一个位置选总分配最大的标签,作为回溯起点。
  7. for (i, j), s in sorted(cands.items(), key=lambda x: -x[1])按区间得分从高到低输出 GlobalPointer 捕捉到的所有候选实体,包括嵌套的“北京”与“北京大学”。

常见误区

误区刚接触 BiLSTM-CRF 时,以为 CRF 是某个深度网络,甚至觉得 NER 的语义理解全靠 CRF 完成,BiLSTM 只是配角。

正解CRF 是概率图模型,本质是一张“标签转移表”。它负责的是标签之间的合法性约束,不负责理解句子。真正的语义特征提取是 BiLSTM 的功劳:双向手电筒把上下文记忆扫出来,CRF 只是最后把关“门牌不能乱接”的城管手册。

为何常见:模型名字里 CRF 写在最后,作为输出层,新手容易把“最终输出者”误当成“主要贡献者”。

误区觉得预训练模型无所不能,BERT 微调后每个词独立过 Softmax 就能拿到完美标签,不需要 CRF 或任何规则。

正解BERT 输出层的 softmax 是逐词独立的,依然可能产出 B-PER 后面直接跟 I-ORG 这种非法标签。工程上常见的做法是 BERT 后接 CRF,或至少做解码约束。预训练提升的是“语义理解”,不是“标签合规”。

为何常见:把预训练的强大语义能力误当成端到端的全部,忽略了序列标注固有的结构性问题。

误区遇到“北京大学”和“北京”同时出现,第一反应是先抽外层机构,再在内部抽地名,觉得嵌套只能靠两遍模型。

正解GlobalPointer 把建模空间从“词到标签”换成“任意区间到实体类别”,每个 (i, j) 组合独立打分,大区间和小区间可以同时命中,天然支持嵌套,不需要分层。传统序列标注才是受限于一维结构的那个。

为何常见:因为大多数人接触 NER 都是从 BIO 序列标注入手的,思维被“一个词一个标签”的框架锁住了。

误区看到 GlobalPointer 能解嵌套、BERT 效果好,就认为 BiLSTM-CRF 是过时产物,任何项目都该上最新模型。

正解工程选型看的是约束条件:标注数据只有几千条、CPU 部署、延迟敏感时,BiLSTM-CRF 以极小代价稳定运行;大模型和全局区间打分带来的显存与耗时开销可能远超收益。没有普适最优,只有场景匹配。

为何常见:技术社区的“新模型屠榜”叙事容易让人忽略资源成本和业务约束。

误区以为预训练模型自带 NER 能力,给十几条例子微调一下就能上线,甚至尝试零样本直接抽实体。

正解预训练学的是通用语言知识,但“哪些词是实体、实体边界在哪、类别怎么划分”是任务特有的。领域差距越大(比如法律、生物、方言),需要的标注数据越多。微调的本质是把通用知识“校准”到贴门牌任务上,校准总得有样本。

为何常见:“预训练”这个词太有迷惑性,让人误以为模型已经做过了 NER 训练。

面试题

Q1. NER 的任务本质是什么?

单选题 · easy

  • A.对文本做情感倾向打分
  • B.识别实体并对其分类标注← 正确答案
  • C.自动生成文章内容摘要
  • D.把一种语言翻译成另一种

答案:B。NER 的目标是从文本中定位实体片段并判断类别,对应“给重要建筑贴分类门牌”。A 是情感分析,C 是文本摘要,D 是机器翻译,三者都是 NLP 的不同任务。

Q2. BIO 标注中 I 标签的含义是什么?

单选题 · easy

  • A.实体外部区域的标记
  • B.实体内部延续的标记← 正确答案
  • C.实体开始位置的标记
  • D.标点符号类别的标记

答案:B。I 是 Inside,表示实体内部的延续门牌,比如“张三”里的“三”贴 I-PER。A 描述的是 O,C 描述的是 B,D 与实体标注无关。

Q3. BiLSTM 为什么能捕捉“上下文信息”?

单选题 · mid

  • A.它把句子随机打乱顺序输入
  • B.它同时从正反两个方向扫描句子← 正确答案
  • C.它只根据当前词自身判断标签
  • D.它把整个句子压缩成一个向量

答案:B。BiLSTM 由正向和反向两个 LSTM 组成,分别从左到右、从右到左扫描,再把两个方向的记忆拼接起来。因此每个词同时携带“左边邻居”和“右边邻居”的信息,这就是双向上下文。

Q4. 在 BiLSTM-CRF 中,CRF 层的主要作用是什么?

单选题 · mid

  • A.提取句子的深层语义特征
  • B.约束标签间转移的合法性← 正确答案
  • C.减少模型总体的参数量
  • D.加快模型收敛的迭代速度

答案:B。CRF 通过转移矩阵约束相邻标签的组合,比如 B-PER 后不能直接接 I-ORG。深层语义特征由 BiLSTM 负责;CRF 既不减少参数量,也不加速收敛,它管的是“门牌接得合不合规”。

Q5. BERT 做 NER 的核心优势是什么?

单选题 · mid

  • A.模型整体的参数量最少
  • B.预训练带来双向上下文语义← 正确答案
  • C.任务不需要任何标注数据
  • D.推理速度比 LSTM 快很多

答案:B。BERT 在海量文本上做掩码语言模型预训练,学到深厚的双向上下文理解,微调后对实体边界的判断更准。它参数量并不少,依然需要标注数据微调,推理也远慢于 LSTM。

Q6. GlobalPointer 建模的核心空间是什么?

单选题 · hard

  • A.词到标签的单步映射空间
  • B.所有头尾位置的配对空间← 正确答案
  • C.相邻标签的转移概率空间
  • D.句法树结构的递归嵌套空间

答案:B。GlobalPointer 对任意起点 i 和终点 j 组合打分,把候选实体表示为“区间”,生活在 (i, j) 的二维配对空间里。A 是序列标注,C 是 CRF 的转移矩阵,D 是句法分析,均不符合。

Q7. 在 BiLSTM-CRF 的维特比解码中,back 数组记录的是什么?

单选题 · extreme

  • A.每个词的所有候选标签得分
  • B.每个位置最优路径的前驱标签← 正确答案
  • C.BiLSTM 的隐藏状态向量序列
  • D.转移矩阵的合法转移集合

答案:B。维特比算法在动态规划时,每到一个位置都要记下“当前最优分是从上一个位置的哪个标签转移来的”,这个回溯指针就是 back 数组。解码最后一步从末尾往前倒推,靠它拼出整条全局最优标签路径。

Q8. 关于 BIO 标注,下列说法正确的是?

多选题 · mid

  • A.B 表示一个实体的开始位置← 正确答案
  • B.I 只能出现在 B 或 I 之后← 正确答案
  • C.O 表示实体内部的一个词
  • D.B 后面可以直接接 O 收尾← 正确答案

答案:ABD。B 标记实体起点,I 表示实体延续,因此 I 前面只可能是 B 或 I;单字实体用 B 开头后直接接 O 收尾也是合法的。O 表示实体外部,不是实体内部,所以 C 错误。

Q9. BERT 微调做 NER 时,哪些做法是合理的?

多选题 · mid

  • A.全量参数参与下游任务微调← 正确答案
  • B.输出层外接 CRF 加强约束← 正确答案
  • C.冻结全部参数不进行任何更新
  • D.用掩码语言模型替代标注输出

答案:AB。全量微调让预训练参数适配 NER 任务,是主流做法;外接 CRF 能约束标签转移,在工程中很常见。完全冻结参数则无法有效适配任务;掩码语言模型是预训练任务,不是 NER 的输出形式,不能直接替代标注。

Q10. GlobalPointer 相比传统 BiLSTM-CRF 的特点有哪些?

多选题 · hard

  • A.一次建模所有实体区间← 正确答案
  • B.天然支持嵌套结构实体← 正确答案
  • C.区间计算复杂度为线性级别
  • D.不需要使用预训练编码器

答案:AB。GlobalPointer 对任意 (i, j) 区间打分,所有候选一次建模,因此大区间套小区间的嵌套实体能同时命中。但它要对约 n² 个区间打分,复杂度是平方级而非线性;它同样依赖 BERT 等编码器提供词向量,所以 C、D 错误。