现在大模型十分火热,但资源或价格考虑下来,也不是所有环境都适合用。今天就是考古使用spaCy进行中文命名实体识别,这个模型的特点就是快。
有一个问题,spaCy的中文模型对英文实体的识别效果不佳,同样英文模型对中文的识别也不好。
因此,我们可以尝试先进行语言检测,然后根据语言选择不同的模型。但是,spaCy的模型通常只针对一种语言训练,所以我们可以分别加载中英文模型,然后根据文本的语言选择模型。
然而,spaCy的模型不支持在同一流程中动态切换,所以我们需要先检测语言,然后选择对应的模型进行处理。
但是,请注意,spaCy的英文模型(en_core_web_sm)对中文无效,中文模型(zh_core_web_sm)对英文也无效。所以,如果我们有一段中英文混合的文本,我们可能需要更复杂的处理,例如分段处理。
然而,由于时间关系,我们这里只做一个简单的演示:分别用中英文模型处理中英文文本。对于混合文本,我们可以尝试用以下策略:
-
将文本按句子分割,然后对每个句子进行语言检测,然后选择对应的模型。
-
或者,如果文本中主要是一种语言,则用该语言的模型处理,另一种语言的实体可能识别不出来。
由于spaCy的模型不支持混合语言,考虑复杂度,我们这里只做简单的单语言处理。对于混合文本,默认用中文模型,因为我们应用场景以中文为主。
但是,我们也可以同时运行两个模型,然后合并结果。但是这样可能会重复识别,而且位置可能会重叠,需二次去重。
什么是命名实体识别?
科普,命名实体识别(Named Entity Recognition, NER)是自然语言处理中的基础任务,旨在识别文本中具有特定意义的实体,主要包括人名、地名、机构名、时间、日期、货币等。
传统方法 vs 现代方法:
-
传统方法:基于规则和词典
-
现代方法:基于机器学习特别是深度学习
spaCy 用预训练模型,准确率很高,用起来还简单。
环境安装三步走
# 1. 安装 spaCy,最好自己先创建一个python虚拟环境
pip install spacy
# 2. 下载中文模型
python -m spacy download zh_core_web_sm
# 3. 下载英文模型
python -m spacy download en_core_web_sm
国内用户如果下载慢,用这个:
# 用国内镜像,速度飞起
pip install zh_core_web_sm -i https://mirrors.aliyun.com/pypi/simple/
核心代码:智能识别系统
先来个语言检测
import re
def detect_language(text):
"""判断文本主要是中文还是英文"""
# 去掉标点数字,只看文字
clean_text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z]', '', text)
if not clean_text:
return 'en' # 默认英文
# 数中文字符和英文字母
chinese_count = len(re.findall(r'[\u4e00-\u9fa5]', clean_text))
english_count = len(re.findall(r'[a-zA-Z]', clean_text))
total = chinese_count + english_count
# 中文超过30%就算中文
if chinese_count / total > 0.3:
return 'zh'
else:
return 'en'
这个函数很聪明(简单粗暴~),能判断文本主要是中文还是英文。
主程序来了
import spacy
class SmartNER:
def __init__(self):
"""初始化,加载两个模型"""
try:
self.nlp_zh = spacy.load("zh_core_web_sm") # 中文模型
self.nlp_en = spacy.load("en_core_web_sm") # 英文模型
print("✓ 模型加载成功!")
except:
print("× 模型没找到,先安装模型吧")
exit(1)
def extract_entities(self, text):
"""提取实体,自动选模型"""
# 先检测语言
lang = detect_language(text)
print(f"原文: {text}")
print(f"检测到: {'中文' if lang == 'zh' else '英文'}")
print("-" * 40)
# 选择合适的模型
if lang == 'zh':
doc = self.nlp_zh(text)
else:
doc = self.nlp_en(text)
# 提取实体信息
entities = []
for ent in doc.ents:
entities.append({
"text": ent.text,
"type": ent.label_,
"type_cn": self._get_chinese_label(ent.label_),
"start": ent.start_char,
"end": ent.end_char
})
return entities
def _get_chinese_label(self, label):
"""把英文标签转成中文,看着舒服"""
label_map = {
# 中文标签映射
"PERSON": "人名", "ORG": "组织机构", "GPE": "地理实体",
"LOC": "地点", "DATE": "日期", "TIME": "时间",
"MONEY": "货币", "PERCENT": "百分比", "CARDINAL": "数字",
# 英文标签映射
"PERSON": "人名", "ORG": "组织", "GPE": "地理位置",
"LOC": "地点", "DATE": "日期", "TIME": "时间",
"MONEY": "金额", "PERCENT": "百分比", "CARDINAL": "数字"
}
return label_map.get(label, label)
def show_results(self, entities):
"""漂亮地显示结果"""
if not entities:
print("没识别到实体")
return
print("识别到的实体:")
for i, ent in enumerate(entities, 1):
print(f" {i}. {ent['text']} → {ent['type_cn']}")
def main():
"""主函数,测试效果"""
print("=" * 50)
print("spaCy 智能中英文实体识别")
print("=" * 50)
# 创建识别器
ner = SmartNER()
# 测试文本
test_texts = [
"马云在杭州阿里巴巴总部会见了苹果公司的Tim Cook",
"Apple CEO Tim Cook visited Beijing yesterday",
"2024年北京大学的李华教授获得了50万美元经费",
"iPhone 15 sales in China reached $1 billion last quarter",
"今天的会议在上海市浦东新区举行,Tim会参加"
]
# 逐个测试
for i, text in enumerate(test_texts, 1):
print(f"\n测试 {i}:")
entities = ner.extract_entities(text)
ner.show_results(entities)
if __name__ == "__main__":
main()
运行效果:看看它能干啥
实际截图:

运行上面的代码,你会看到:
==================================================
spaCy 智能中英文实体识别
==================================================
测试 1:
原文: 马云在杭州阿里巴巴总部会见了苹果公司的Tim Cook
检测到: 中文
识别到的实体:
1. 马云 → 人名
2. 杭州 → 地理实体
3. 阿里巴巴总部 → 组织机构
4. Tim Cook → 人名
测试 2:
原文: Apple CEO Tim Cook visited Beijing yesterday
检测到: 英文
识别到的实体:
1. Apple → 组织
2. Tim Cook → 人名
3. Beijing → 地理位置
4. yesterday → 日期
测试 3:
原文: 2024年北京大学的李华教授获得了50万美元经费
检测到: 中文
识别到的实体:
1. 2024年 → 日期
2. 北京大学 → 组织机构
3. 李华 → 人名
4. 50万美元 → 货币
核心要点回顾
1. 语言检测是关键
def detect_language(text):
# 数中文字符和英文字母的比例
# 中文多就用中文模型,英文多就用英文模型
为什么要检测语言?因为:
- 中文模型对英文实体识别不好
- 英文模型对中文实体识别不好
- 选对模型,准确率翻倍
2. 实体标签映射
def _get_chinese_label(self, label):
# 把 PERSON 变成 "人名"
# 把 ORG 变成 "组织机构"
这样显示结果更友好,一看就懂,可以进一步处理。
3. 统一处理接口
def extract_entities(self, text):
# 自动检测语言
# 自动选择模型
# 统一返回格式
使用者不用关心底层细节,只管调用就行。
实际应用场景
这个技术可以用在:
- 智能客服:自动提取用户问题里的关键信息
- 文档分析:快速找出合同里的人物、公司、金额
- 新闻聚合:自动分类新闻涉及的人物和地点
- 社交媒体监控:发现热门话题的关键实体
可能遇到的问题
问题 1:模型下载失败?
解决:用国内镜像,或者手动下载 whl 文件安装就行
问题 2:速度几何?慢吗?
解决:对比使用大模型可以说是极速了,六七十字的一句话识别平均只需要 10 ms。
问题 3:识别不准,没办法了
解决:spaCy 主要是通用模型,专业领域可以自己训练,试了公司自己的人名,确实无法检测到。
赶紧试试吧!遇到问题欢迎交流。



187

被折叠的 条评论
为什么被折叠?



