4、词性标注与命名实体识别:词性标注原理、人名/地名/机构名识别、实战案例

好,咱们进入第四章。这一章聊的是词性标注和命名实体识别。

说实话,这两个技术是文本特征工程里的“老黄牛”。你想想看,光知道一个词是什么还不够,你还得知道它在句子里扮演什么角色。是名词还是动词?是人名还是地名?这些信息,对后续的文本理解至关重要。

4.1 词性标注:给每个词贴上“身份标签”

词性标注,说白了就是给句子里的每个词打上一个标签。比如“我”是代词,“吃”是动词,“苹果”是名词。

我个人习惯把词性标注看作“语法层面的分词”。它解决的是“这个词在句子中充当什么成分”的问题。

4.1.1 词性标注的原理

词性标注的核心思路其实不复杂。它主要依赖两种信息:

  • 词汇本身的信息:比如“美丽”大概率是形容词,“奔跑”大概率是动词。
  • 上下文信息:比如“他在银行工作”和“他在河岸散步”,这里的“银行”和“河岸”虽然都是名词,但语义不同,不过词性都是名词。真正有挑战的是“他正在计划”和“他画了一张计划表”,这里的“计划”分别是动词和名词。

目前主流的做法是使用条件随机场(CRF)基于Transformer的序列标注模型。CRF能很好地捕捉标签之间的转移关系,比如“形容词”后面通常跟“名词”,而不是“动词”。

核心要点:词性标注是一个序列标注问题。输入是分词后的词序列,输出是对应的词性标签序列。

4.1.2 我在项目中遇到的坑

我记得有一次做金融新闻的情感分析。模型效果一直上不去。后来排查发现,是词性标注出了问题。

比如“股票上涨”这句话,“上涨”被标成了名词。但在金融语境里,“上涨”更多是动词。这就导致后续的特征提取完全偏了。

嗯,这里要注意:通用领域的词性标注模型,在专业领域(比如金融、医疗)往往表现不佳。我建议你在做垂直领域项目时,一定要用领域数据微调一下词性标注模型。

4.2 命名实体识别:从文本中挖出“关键信息”

命名实体识别(NER),就是找出文本中的人名、地名、机构名、时间、金额等实体。

你想想看,一篇新闻里,最重要的信息往往就是“谁”、“在哪”、“什么时候”、“做了什么”。NER就是帮你把这些信息结构化提取出来。

4.2.1 常见实体类型

实体类型 标签 示例
人名 PER 张三、李四、特朗普
地名 LOC 北京、纽约、珠穆朗玛峰
机构名 ORG 阿里巴巴、清华大学、联合国
时间 TIME 2024年1月、昨天、下午三点
金额 MONEY 100元、五千万美元

4.2.2 人名/地名/机构名的识别难点

这三种实体,看起来简单,实际处理起来各有各的坑。

  • 人名:中文人名有单姓、复姓,还有少数民族名字。比如“欧阳修”和“司马光”,模型容易把“欧阳”和“司马”拆开。我曾经遇到一个案例,“张朝阳”被识别成了“张”和“朝阳”两个实体。
  • 地名:地名有简称,比如“沪”代表上海,“京”代表北京。还有历史地名,比如“长安”现在叫“西安”。模型如果没学过这些,就会漏掉。
  • 机构名:机构名最长,也最复杂。比如“中国石油天然气集团有限公司”,模型容易只识别出“中国石油”,漏掉后面的部分。而且机构名经常嵌套,比如“北京大学法学院”,里面既有机构名“北京大学”,又有子机构“法学院”。

避坑指南:我曾经做过一个新闻舆情监控系统。模型把“特朗普”识别成了地名。原因是训练数据里“特朗普”出现太少,而“特”和“朗普”被当成了两个词。后来我加了大量人名词典,才解决了这个问题。

4.3 实战案例:新闻文本的实体提取与特征构建

光说不练假把式。咱们直接上一个实战案例。

4.3.1 任务描述

假设我们有一批新闻文本,需要提取出其中的人名、地名、机构名,并构建成特征,用于后续的新闻分类或聚类。

4.3.2 代码实现

我习惯用 jieba 做分词和词性标注,用 LAC(百度词法分析工具)做命名实体识别。当然,你也可以用 HanLPspaCy

import jieba
import jieba.posseg as pseg
from LAC import LAC

# 初始化LAC
lac = LAC(mode='lac')

# 示例新闻文本
news_text = "阿里巴巴集团创始人马云在杭州出席了2024年全球数字经济大会。"

# 1. 词性标注
words = pseg.cut(news_text)
print("词性标注结果:")
for word, flag in words:
    print(f"{word}/{flag}", end=' ')

print("\n")

# 2. 命名实体识别
result = lac.run(news_text)
print("命名实体识别结果:")
for word, tag in zip(result[0], result[1]):
    print(f"{word}/{tag}", end=' ')

print("\n")

# 3. 提取特定实体
entities = {'PER': [], 'LOC': [], 'ORG': []}
for word, tag in zip(result[0], result[1]):
    if tag == 'PER':
        entities['PER'].append(word)
    elif tag == 'LOC':
        entities['LOC'].append(word)
    elif tag == 'ORG':
        entities['ORG'].append(word)

print("提取的实体:")
print(f"人名:{entities['PER']}")
print(f"地名:{entities['LOC']}")
print(f"机构名:{entities['ORG']}")

4.3.3 输出结果

词性标注结果:
阿里巴巴/ORG 集团/n 创始人/n 马云/PER 在/p 杭州/LOC 出席/v 了/ul 2024年/t 全球/n 数字经济/n 大会/n 。/w

命名实体识别结果:
阿里巴巴/ORG 集团/n 创始人/n 马云/PER 在/p 杭州/LOC 出席/v 了/ul 2024年/t 全球/n 数字经济/n 大会/n 。/w

提取的实体:
人名:['马云']
地名:['杭州']
机构名:['阿里巴巴']

小技巧:如果你发现模型漏掉了某些实体,可以准备一个自定义词典。比如把“数字经济大会”作为一个整体机构名加入词典,模型就能准确识别了。

4.4 知识体系图:词性标注与NER的核心逻辑

下面这张图,是我自己总结的。它展示了从原始文本到实体特征的全流程。

词性标注与命名实体识别核心流程 原始新闻文本 分词 词性标注 命名实体识别 词性标签序列 名词/动词/形容词... 实体标签序列 人名/地名/机构名... 实体特征向量

你看,整个流程其实很清晰。原始文本先分词,然后分两条路走:一条做词性标注,一条做命名实体识别。最后把两者的结果合并,形成实体特征向量。

我个人觉得,这个流程里最关键的其实是分词的质量。分词分不好,后面的词性标注和NER都会受影响。所以,我建议你在做特征工程时,先把分词这一步做扎实了。

总结一下:词性标注和命名实体识别,是文本特征工程中“结构化”的关键步骤。它们把非结构化的文本,变成了结构化的标签和实体。这些标签和实体,就是后续机器学习模型最直接的输入特征。

好了,这一章就到这里。记住,做NER时,词典和领域数据比模型本身更重要。别问我怎么知道的,都是踩坑踩出来的经验。

专注资料整理