【问题标题】:Suitable data structure for fast search on sets. imput: tags, output: sentence适合快速搜索集合的数据结构。输入:标签,输出:句子
【发布时间】:2019-02-07 23:45:51
【问题描述】:

我有以下问题。

我得到1-10个标签,与一张图片相关,每个标签都有一个存在于图片中的概率。

输入:海滩、女人、狗、树……

我想从数据库中检索与标签最相关的已经组成的句子。

例如:

beach -> “在 beach 玩得开心” / “在 beach 放松一下” ....

beach, woman -> “woman at the beach

海滩,女人,狗 - > 没有找到!

取最接近的存在但考虑概率 可以说:女人 0.95,海滩 0.85,狗 0.7 所以如果存在取女人+海滩(0.95,0.85)然后女人+狗和最后一个海滩+狗,顺序是越高越好,但我们不求和。

我曾想过使用 python sets,但我不确定如何使用。

另一个选项将是 defaultdict:

db['beach']['woman']['dog'],但我也想从以下位置获得相同的结果: db['woman']['beeach']['dog']

我想得到一个很好的解决方案。 谢谢。

编辑:工作解决方案

from collections import OrderedDict
list_of_keys = []
sentences = OrderedDict()
sentences[('dogs',)] = ['I like dogs','dogs are man best friends!']
sentences[('dogs', 'beach')] = ['the dog is at the beach']
sentences[('woman', 'cafe')] = ['The woman sat at the cafe.']
sentences[('woman', 'beach')] = ['The woman was at the beach']
sentences[('dress',)] = ['hi nice dress', 'what a nice dress !']


def keys_to_list_of_sets(dict_):
    list_of_keys = []
    for key in dict_:
        list_of_keys.append(set(key))

    return list_of_keys

def match_best_sentence(image_tags):
    for i, tags in enumerate(list_of_keys):
        if (tags & image_tags) == tags:
            print(list(sentences.keys())[i])

list_of_keys = keys_to_list_of_sets(sentences)
tags = set(['beach', 'dogs', 'woman'])
match_best_sentence(tags)

结果:

('dogs',)
('dogs', 'beach')
('woman', 'beach')

此解决方案运行有序字典的所有键, o(n),我希望看到任何性能改进。

【问题讨论】:

  • 据我了解您的问题,您不知道选择什么数据结构来存储标签对?
  • 数据库有多大?它包含多少个句子和关键词?它是静态的还是动态变化的添加和删除新句子?
  • 静态,不变。
  • 1000 句,还在不断增加中……
  • @SamperMan 我真的不知道我不知道什么。我没有适合存储和检索的解决方案。

标签: python database search set


【解决方案1】:

主要取决于数据库的大小和关键字之间的组合数量。此外,这还取决于您最常做的操作。
如果它很小并且您需要快速的find 操作,则可以使用带有frozensets 作为键的字典,其中包含标签和所有相关句子的值。

例如,

d=defaultdict(list)
# preprocessing
d[frozenset(["bob","car","red"])].append("Bob owns a red car")

# searching
d[frozenset(["bob","car","red"])]  #['Bob owns a red car']
d[frozenset(["red","car","bob"])]  #['Bob owns a red car']

对于“bob”、“car”等词的组合,根据关键字的数量和更重要的因素,您有不同的可能性。例如

  • 您可以为每个组合添加额外的条目
  • 您可以遍历键并检查同时包含 carbob 的键

【讨论】:

  • 如果你想要 ["bob", "car"] 作为查找呢?
  • 这取决于,如果空间不是问题(即少量关键字),您可以有所有组合的附加条目,否则迭代键并检查同时包含 car 和鲍勃。
【解决方案2】:

在不使用数据库的情况下,似乎最简单的方法是为每个单词保留集合并取交集。

更明确地说:

如果一个句子包含“女人”这个词,那么你把它放到“女人”集合中。每个句子的狗和海滩等也是如此。这意味着您的空间复杂度为 O(sentences*average_tags),因为每个句子在数据结构中都是重复的。

你可能有:

>>> dogs = set(["I like dogs", "the dog is at the beach"])
>>> woman = set(["The woman sat at the cafe.", "The woman was at the beach"])
>>> beach = set(["the dog is at the beach", "The woman was at the beach", "I do not like the beach"])
>>> dogs.intersection(beach)
{'the dog is at the beach'}

您可以将其构建到 defaultdict 之上的对象中,以便您可以获取标签列表,并且只能与这些列表相交并返回结果。

粗略的实现思路:

from collections import defaultdict
class myObj(object): #python2
    def __init__(self):
        self.sets = defaultdict(lambda: set()) 

    def add_sentence(self, sentence, tags):
         #how you process tags is up to you, they could also be parsed from
         #the input string. 
         for t in tags:
             self.sets[tag].add(sentence)

    def get_match(self, tags):
         result = self.sets(tags[0]) #this is a hack 
         for t in tags[1:]:
             result = result.intersection(self.sets[t])

         return result #this function can stand to be improved but the idea is there

也许这会让默认的 dict 和 sets 最终如何在对象中查找更清楚。

>>> a = defaultdict(lambda: set())
>>> a['woman']
set([])
>>> a['woman'].add(1)
>>> str(a)
"defaultdict(<function <lambda> at 0x7fcb3bbf4b90>, {'woman': set([1])})"
>>> a['beach'].update([1,2,3,4])
>>> a['woman'].intersection(a['beach'])
set([1])
>>> str(a)
"defaultdict(<function <lambda> at 0x7fcb3bbf4b90>, {'woman': set([1]), 'beach': set([1, 2, 3, 4])})"

【讨论】:

  • 我发现这个选项是一个很好的解决方案,但我会改变一件事:我将放置数字而不是句子,每个数字代表一个列表中的句子,即 my_list[1] = '海滩上的狗”,这样我可以节省内存。
  • 我们确实错过了概率部分
  • 我忘了提到这个解决方案没有解决这个问题,因为我不明白你的意图。数字会加快速度,您也可以在每个字符串周围包裹一个对象,这取决于您的问题,这可能好也可能不好。
  • 我将根据您的答案发布解决方案,并实现概率。
  • 我确实遇到了一个句子必须有 beach 和 woman 但对 beach\woman 本身无效的情况。
猜你喜欢
  • 1970-01-01
  • 2014-06-18
  • 1970-01-01
  • 2015-11-10
  • 1970-01-01
  • 2011-04-26
  • 2015-05-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多