Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Search 基于列表的搜索引擎命名实体识别:如何扩展?_Search_Memory_Solr_Nlp_Ner - Fatal编程技术网

Search 基于列表的搜索引擎命名实体识别:如何扩展?

Search 基于列表的搜索引擎命名实体识别:如何扩展?,search,memory,solr,nlp,ner,Search,Memory,Solr,Nlp,Ner,我正在开发一个搜索引擎,搜索存储在Solr中的文档 在用户查询中,我想检测命名实体个人、组织、城市 示例查询是: 巴拉克·奥巴马的妻子年龄 在这个问题中,我想发现巴拉克·奥巴马是一个人 因为查询不是真正的短语,所以对于经典的NER Spacy、Stanford NER。。。正常工作。 因此,我采取了这种方法: 在字典中存储文档中按长度递减排序的所有实体 循环字典,查看用户查询是否包含实体 def find_entities(query,entities_dict): entities=

我正在开发一个搜索引擎,搜索存储在Solr中的文档

在用户查询中,我想检测命名实体个人、组织、城市

示例查询是:

巴拉克·奥巴马的妻子年龄

在这个问题中,我想发现巴拉克·奥巴马是一个人

因为查询不是真正的短语,所以对于经典的NER Spacy、Stanford NER。。。正常工作。 因此,我采取了这种方法:

在字典中存储文档中按长度递减排序的所有实体 循环字典,查看用户查询是否包含实体

def find_entities(query,entities_dict):

    entities=[]
    new_query=query.lower()

    for entity in entities_dict:
        if find_substring(entity,new_query):
            entities.append({entity:entities_dict[entity]})
            new_query = re.sub(r'\b{}\b'.format(entity), '', new_query)
    return(new_query,entities)
目前,我的Solr索引中有大约20万个实体:创建字典需要几分钟;加载后,这种方法工作良好,速度快,占用内存少

在不久的将来,我将拥有5000-1亿个实体

我认为将这些实体存储在内存中是不可能的

我怎样才能改变我的方法?
我正在寻找有关算法、内存管理和数据结构的建议。

一个明显的暴力解决方案就是将搜索索引分散:创建100个节点,每个节点中包含100万个实体的字典,并行运行它们,然后合并结果

另一种可能是对分割索引的补充的解决方案是,不将实体保存在简单的列表中,而是保存在aka trie或索引图中。这些数据结构大大加快了子字符串搜索的速度,因为它们利用许多实体中有相同子字符串的事实,试图在一次过程中将所有实体与查询匹配

事实上,我曾经在简短的查询中查找过几百万个实体——电影、歌曲、演员等等,而且它的伸缩性似乎非常好。形式上,Aho Corasick的时间复杂度并不取决于实体的总数,而只取决于具体查询中匹配实体的数量。因此,如果搜索速度变慢(这是不太可能的),那么查看哪些实体生成大量假阳性匹配并将其从索引中删除是有意义的。在我的例子中,在删除非常常见的实体(例如它是电影名称)之后!,火柴手加快了速度

这里有一个例子。首先,我们让实体搜索15000个城市:

pip install pyahocorasick
wget https://simplemaps.com/static/data/world-cities/basic/simplemaps_worldcities_basicv1.6.zip
unzip simplemaps_worldcities_basicv1.6.zip
然后,我们创建可以匹配实体和城市的自动机:

import pandas as pd
import re
import ahocorasick
cities = pd.read_csv('worldcities.csv')

def preprocess(text):
    """
    Add underscores instead of non-alphanumeric characters 
    and on the word boundaries in order to tell words from word substrings.
    """
    return '_{}_'.format(re.sub('[^a-z0-9]', '_', text.lower()))

index = ahocorasick.Automaton()
for city in cities.city:
    index.add_word(preprocess(city), city)
index.make_automaton()
# this object can be pickled to disk and then loaded back
现在实际将此索引应用于文本中的查找实体:

def find_cities(text, searcher):
    result = dict()
    for end_index, city_name in searcher.iter(preprocess(text)):
        end = end_index - 1
        start = end - len(city_name)
        result[(start, end)] = city_name
    return result

print(find_cities( 'Tver’ is somewhere between Moscow and Saint Petersburg', index))
# {(0, 5): 'Tver’', (27, 33): 'Moscow', (38, 54): 'Saint Petersburg', (44, 54): 'Petersburg'} 
# the search takes about 0.1 ms
Naive search会给出相同的结果,但大约需要10毫秒:

for city in cities.city:
    idx = text.find(city)
    if idx >=0:
        print(idx, city)

下面是我的代码。

一个明显的暴力解决方案就是让搜索索引分布:例如,创建100个节点,每个节点中包含100万个实体的字典,并行运行它们,然后合并结果

另一种可能是对分割索引的补充的解决方案是,不将实体保存在简单的列表中,而是保存在aka trie或索引图中。这些数据结构大大加快了子字符串搜索的速度,因为它们利用许多实体中有相同子字符串的事实,试图在一次过程中将所有实体与查询匹配

事实上,我曾经在简短的查询中查找过几百万个实体——电影、歌曲、演员等等,而且它的伸缩性似乎非常好。形式上,Aho Corasick的时间复杂度并不取决于实体的总数,而只取决于具体查询中匹配实体的数量。因此,如果搜索速度变慢(这是不太可能的),那么查看哪些实体生成大量假阳性匹配并将其从索引中删除是有意义的。在我的例子中,在删除非常常见的实体(例如它是电影名称)之后!,火柴手加快了速度

这里有一个例子。首先,我们让实体搜索15000个城市:

pip install pyahocorasick
wget https://simplemaps.com/static/data/world-cities/basic/simplemaps_worldcities_basicv1.6.zip
unzip simplemaps_worldcities_basicv1.6.zip
然后,我们创建可以匹配实体和城市的自动机:

import pandas as pd
import re
import ahocorasick
cities = pd.read_csv('worldcities.csv')

def preprocess(text):
    """
    Add underscores instead of non-alphanumeric characters 
    and on the word boundaries in order to tell words from word substrings.
    """
    return '_{}_'.format(re.sub('[^a-z0-9]', '_', text.lower()))

index = ahocorasick.Automaton()
for city in cities.city:
    index.add_word(preprocess(city), city)
index.make_automaton()
# this object can be pickled to disk and then loaded back
现在实际将此索引应用于文本中的查找实体:

def find_cities(text, searcher):
    result = dict()
    for end_index, city_name in searcher.iter(preprocess(text)):
        end = end_index - 1
        start = end - len(city_name)
        result[(start, end)] = city_name
    return result

print(find_cities( 'Tver’ is somewhere between Moscow and Saint Petersburg', index))
# {(0, 5): 'Tver’', (27, 33): 'Moscow', (38, 54): 'Saint Petersburg', (44, 54): 'Petersburg'} 
# the search takes about 0.1 ms
Naive search会给出相同的结果,但大约需要10毫秒:

for city in cities.city:
    idx = text.find(city)
    if idx >=0:
        print(idx, city)

这是我的代码。

您可以对包含实体的单独集合运行查询,然后对查询运行返回的实体,因为您知道哪些实体存在?我可能可以,但我认为Solr中的这种双重查询会减慢用户搜索速度。谢谢你的主意。如果您有任何其他建议,请分享。您是否可以对包含实体的单独集合运行查询,然后对查询运行返回的实体,因为您知道哪些实体存在?可能我可以,但我认为Solr中的这种双重查询会减慢用户搜索速度。谢谢你的主意。如果你还有其他建议,请分享。谢谢。如何保存和加载要使用pyahocorasick搜索的实体?请解释一下……谢谢。最后一个问题:对不同类型的实体使用单一索引,如何存储和使用有关实体类型的信息?是p吗
是否可能保留此方法并集成此信息?在方法add_word中,第一个参数是要搜索的字符串,第二个参数是与此字符串关联的任意对象,例如带有任何键的dict。因此,您可以在此对象中保留有关实体类型的信息。谢谢。如何保存和加载要使用pyahocorasick搜索的实体?请解释一下……谢谢。最后一个问题:对不同类型的实体使用单一索引,如何存储和使用有关实体类型的信息?是否可以保留此方法并集成此信息?在方法add_word中,第一个参数是要搜索的字符串,第二个参数是与此字符串关联的任意对象,例如带有任何键的dict。因此,可以在该对象中保留有关实体类型的信息。