Python实现命名实体识别方式(非AI)

发布时间:2023年12月22日

最近在做知识图谱智能问答应用(KBQA),卡在Text2Cypher,构造Cypher查询语句前提是做一个命名实体识别,上网看其他大佬KBQA项目,得出一个取巧的办法,就是在节点入库时把各分类节点名存到一个列表中,然后通过一些字符串匹配算法识别自然语言中的实体。

一、基于Aho-Corasick算法

使用Aho-Corasick算法进行字符串匹配通常涉及以下步骤:

  1. 构建Aho-Corasick自动机:首先,需要将要匹配的模式(关键词)构建成Aho-Corasick自动机的数据结构。这个数据结构可以通过构建Trie树并应用Aho-Corasick算法转化而来。
  2. 初始化自动机:初始化Aho-Corasick自动机,使之处于匹配状态。
  3. 匹配:将待匹配的文本输入到Aho-Corasick自动机中,自动机会根据输入的文本进行状态转移,最终输出匹配的结果,即模式在文本中的出现位置。

在Python中,您可以使用第三方库ahocorasick来实现Aho-Corasick算法的字符串匹配。您可以按照以下步骤使用该库:

安装ahocorasick库(如果尚未安装):

pip3 install pyahocorasick -i https://pypi.tuna.tsinghua.edu.cn/simple/

使用示例代码进行字符串匹配:

import ahocorasick

# 定义不同类型的命名实体词典
entity_dict = {
    '地点': ["北京", "上海", "广州"],
    '人名': ["张三", "李四", "王五"],
    '大学': ["清华大学", "北京大学", "复旦大学"]
}

# 构建Aho-Corasick自动机
automata = {entity_type: ahocorasick.Automaton() for entity_type in entity_dict}

# 将命名实体词典添加到各自的自动机中
for entity_type, words in entity_dict.items():
    for word in words:
        automata[entity_type].add_word(word, (entity_type, word))

# 完成模式添加后,需要调用make_automaton()来构建自动机
for ac in automata.values():
    ac.make_automaton()

# 待匹配的文本
text = "张三来自北京,就读于清华大学。"

# 匹配
matches = {entity_type: set() for entity_type in entity_dict}
for entity_type, ac in automata.items():
    for end_index, (keyword_type, keyword) in ac.iter(text):
        start_index = end_index - len(keyword) + 1
        matches[entity_type].add((start_index, end_index, keyword))

# 输出匹配结果
for entity_type, entity_matches in matches.items():
    print(f"匹配到的{entity_type}:")
    for start, end, word in entity_matches:
        print(f"  发现命名实体 '{word}',位置:{start}-{end}")

二、基于相似度算法

一种常见的字符串相似度算法是Levenshtein距离,它衡量了两个字符串之间的编辑距离,即需要进行多少次插入、删除或替换操作才能将一个字符串转换为另一个字符串。
安装Levenshtein库(如果尚未安装):

pip install python-Levenshtein

以下是一个简单的示例代码,演示了如何使用Levenshtein距离来进行命名实体识别:

import Levenshtein

# 定义多个命名实体词典
entity_dicts = {
    '地点': ["北京", "上海", "广州"],
    '人名': ["张三", "李四", "王五"],
    '大学': ["清华大学", "北京大学", "复旦大学"]
}

# 待匹配的文本
text = "张三来自北京,就读于清华大学。"

# 初始化最高相似度字典
max_similarity = {entity_type: 0 for entity_type in entity_dicts}

# 进行多粒度命名实体识别
for entity_type, entity_list in entity_dicts.items():
    for entity in entity_list:
        similarity = Levenshtein.ratio(text, entity)
        if similarity > max_similarity[entity_type]:
            max_similarity[entity_type] = similarity

# 输出匹配结果
matched_entities = {entity_type: "" for entity_type in entity_dicts}
for entity_type, entity_list in entity_dicts.items():
    for entity in entity_list:
        similarity = Levenshtein.ratio(text, entity)
        if similarity == max_similarity[entity_type] and similarity > threshold:
            matched_entities[entity_type] = entity

# 输出匹配结果
print("找到以下相似的命名实体:")
for entity_type, entity in matched_entities.items():
    if entity:
        print(f"  类型:{entity_type},匹配到 '{entity}',相似度:{max_similarity[entity_type]}")
    else:
        print(f"  未找到 {entity_type} 类型的相似命名实体。")
文章来源:https://blog.csdn.net/qq_39071593/article/details/135132042
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。