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(百度词法分析工具)做命名实体识别。当然,你也可以用 HanLP 或 spaCy。
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时,词典和领域数据比模型本身更重要。别问我怎么知道的,都是踩坑踩出来的经验。