Solr - 返回单词NGrams,即使是混合字序

时间:2013-12-29 10:23:07

标签: n-gram

我无法找到一种资源来解释一种方法,通过该资源我可以返回最常用的单词NGrams,它不依赖于单词顺序,并且具有灵活的单词位置边界。我认为这个概念类似于在结果中使用slop,而不是在查询中使用slop。

例如,我了解一个典型的BiGram或CommonGram可能允许索引以下文字:“快速棕色狐狸...”
这些术语:“快速”“快速棕色”“棕色狐狸” ... ...从那里,如果我只想要一个请求处理程序或facet将返回最常出现的单词BiGrams的前100个(或左右),这应该不是问题。

但是有两个案例与我有关:
1)如果在我的语料库中,我看到“快速褐色”和“棕色快速”的出现 - 它们将被单独计算。就我的目的而言,这些可能是相关的,所以我希望它们被算作一个 2)如果在我的语料库中,我看到“快速狐狸”和“快速棕狐”的出现 - 它们将被单独计算。就我的目的而言,我希望在这种情况下看到“快速狐狸”重复计算。实际上,这种情况是一种简化 - 术语“快速”和“狐狸”可以用几个词分开。 (这可能是显而易见的,但是,我不能简单地对这两个术语进行slop查询并返回匹配的文档,因为我不知道这些术语是什么。)

详细说明(Jan的问题)如果文件中出现“快狐,快狐”,我最好将单词对“quick fox”/“fox quick”计为:
  - 如果用0个单词分隔,则出现三次(“快速狐狸”x2,“狐狸,快速”x1)   - 如果用1个单词分隔出现五次(上面加上“快......,狐狸”和“狐狸......快”)   - 如果用2个单词分隔出现六次(上面加上“快......,......狐狸”)

另外,对于文字:“快速狐狸狐狸”,我最好将单词对“快速狐狸”/“狐狸快”视为:
  - 如果用0个单词分开,则出现一次(“快速狐狸”)
  - 如果用1个单词分隔出现三次(上面加上“快速...狐狸”x2)
  - 如果用2个单词分隔出现五次(上面加上“快......狐狸”)

(虽然我的例子显示的是两个单词,但我的问题比两个单词组合更广泛。但如果我只有两个单词组合,我会对此感到高兴。)< / p>

“我为什么关心”的原因是我在合并技术和服务/支持的(非常不精确的)行业工作。我有一个与Solr的现有应用程序,我想添加一个新功能 - 此功能将允许用户挖掘可能通过某种灵活定义的邻近度相关的文本数据术语。详细说明 - 用户已经有几个查询,按顺序运行,结果在图表上绘制。然后用户:
a)开始手动阅读与每个查询匹配的文档 b)尝试识别常见的术语或短语 c)细分和细化他们的查询 d)重新绘制查询结果 e)重复,从a)开始 我想向他们提供这些“草率的单词NGrams”,几乎就像一个文字云,因此用户可以在开发过程中获得即时反馈细分和优化查询,而无需打开和阅读文档。

我理解TermVectorComponent将允许我取回我所关注的各个词的所有位置和频率信息,从那里我可以做任何我想做的事 - 但我宁愿不必如果我不需要那样做。

理想情况下,我希望无论如何都要尊重停用词。 (也就是说,在上面的例子中,如果“the”是一个禁用词,根本就不要索引:“快速”。)

最后,我并不精通文档摘要,搜索建议或其他一些我认为“先进”的概念,因为我对此有多了解。如果我刚才描述的内容可以通过其中一个功能提供,请告诉我,我会更多地阅读它们。

1 个答案:

答案 0 :(得分:0)

好的,我想我得到了你想要达到的目标。这并不难,但难以表现。

我只会勾画我的想法,因为我躺在床上,没有我的IDE就不会提供Java代码:-)

基本原则是你创建自己的Tokenizer(事实上你自己的过滤器,但因为它会创建很多额外的令牌,感觉更像是一个标记器),你链接在你最喜欢的Tokenizer-Filter-Chain之后(小写,停用词)过滤器,同义词,变音过滤)

我假设你的N-gram中的N有一个最大值(否则你需要将整个场加载到内存中)而且我进一步假设,两个最外面的令牌中有一个最大距离M。带有M>=N

的N-gram
  1. 使用来自tokenizer链的第一个M令牌加载大小为M的FiFo-Queue。
    1. 现在用第一个标记构建所有Bi到N-gram(N-1个双子座,......,1个N-gram)
    2. 按字母顺序排序并将每个单个n-gram作为标记返回
    3. 弹出第一个令牌
  2. while(将下一个令牌从tokenizer推送到队列或队列不为空)
  3. 出于性能原因,将Fifo实现为Ringbuffer阵列 这将为您提供一个包含所有n-gram的索引,您只需计算它们即可。

    稍后需要偏移量时,将其存储为有效负载或使用它来设置令牌的权重。

    我们举个例子:

    input="quick brown fox jumps quick fox"
    N=3
    M=4
    

    首先使用令牌“text”填充缓冲区:position:weight

    buffer = ["quick":1:1,"brown":2:1,"fox":3:1,"jumps":4:1]
    

    将创建以下二元标记(我使用权重来存储两个最外面的原始标记之间的倒数距离,使得重量1表示没有中间标记)

    "brown quick":1:1,"fox quick":1:0.5,"jumps quick":1:0,333
    

    和3克:

    "brown fox quick":1:1,"brown jumps quick":1:0.5,"fox jumps quick":1:0.5
    

    弹出第一个缓冲区元素并填充下一个

    buffer = ["brown":2:1,"fox":3:1,"jumps":4:1,"quick":5:1]
    

    做N-gram

    "brown fox":2:1,"jumps brown":2:0.5,"brown quick":2:0,333
    "brown fox jumps":2:1,"brown fox quick":2:0,5,"brown jumps quick":2:0.5
    

    如果现在看一下索引,我们已经可以看到,多次出现了几个N-gram:

    "brown quick"↦:1:1,:2:0,333
    …
    "brown jumps quick"↦:1:0.5,:2:0.5
    …
    

    继续

    buffer = ["fox":3:1,"jumps":4:1,"quick":5:1,"fox":6:1]
    

    我认为,你只对n-gram的不同单词感兴趣,所以我用N-gram过滤重复:

    "fox jumps":3:1,"fox quick":3:0,5
    "fox jumps quick":3:1
    

    现在到达输入的末尾我们只是减少缓冲区

    buffer = ["jumps":4:1,"quick":5:1,"fox":6:1]
    "jumps quick":4:1,"fox jumps":4:0,5
    "fox jumps quick":4:1
    
    buffer = ["quick":5:1,"fox":6:1]
    "fox quick":5:1