Algorithm 语料库中的高效搜索

Algorithm 语料库中的高效搜索,algorithm,search,data-structures,hadoop,mapreduce,Algorithm,Search,Data Structures,Hadoop,Mapreduce,我有几百万个单词,我想在十亿个单词的语料库中搜索。这样做的有效方法是什么 我正在考虑trie,但是有没有trie的开源实现 多谢各位 --更新-- 让我再补充一些关于具体要求的细节 我们有一个系统,在这个系统中,我们对新闻来源进行爬网,并根据单词的频率获取流行单词。可能有一百万个字 我们的数据看起来像这样 单词1频率1 字2频率2 (以制表符分隔) 我们还从另一个来源获得了最流行的单词(10亿),其中也包含上述格式的数据 以下是我希望得到的输出 两个来源的共同词语 单词只出现在我们的源代码中,

我有几百万个单词,我想在十亿个单词的语料库中搜索。这样做的有效方法是什么

我正在考虑trie,但是有没有trie的开源实现

多谢各位

--更新--

让我再补充一些关于具体要求的细节

我们有一个系统,在这个系统中,我们对新闻来源进行爬网,并根据单词的频率获取流行单词。可能有一百万个字

我们的数据看起来像这样

单词1频率1 字2频率2 (以制表符分隔)

我们还从另一个来源获得了最流行的单词(10亿),其中也包含上述格式的数据

以下是我希望得到的输出

  • 两个来源的共同词语
  • 单词只出现在我们的源代码中,而不出现在参考源代码中
  • 单词只出现在参考源中,而不出现在我们的源中
我能够使用comm(bash命令)来处理上面的信息,只针对单词。我不知道如何使用comm只对一列而不是两列进行比较

该系统应该是可扩展的,我们希望每天都执行此操作并比较结果。我还想得到大致的匹配

所以,我正在考虑写一份地图缩减工作。我计划写地图和减少功能如下,但我有几个问题

Map
For each word
output key = word and value = structure{ filename,frequency}
done

Reduce
For each key
Iterate through all the values and check if both file1 and file2 are contained.
If yes, then write it to appropriate file.
If only in file1, write it to file1only file
If only in file2, write it to file2only file.
Done.
我有两个问题。 在MapReduce中,我可以输入一个包含两个文件的目录。我不知道如何获取读取单词的文件名。如何获取这些信息? 如何写入不同的输出文件,因为reduce phase只自动写入名为part-xxxxx的默认文件。如何写入不同的输出文件


感谢您阅读此文。

如果我用Java进行此操作,我会使用HashMap。这表明trie在某些情况下稍微好一些,但我不确定您是否会看到很大的不同。

这看起来像是字符串搜索算法的设计目标。我从来没有自己编写过代码,但谷歌搜索一下应该会发现一些代码


也可能有效,但我不知道当多个模式的长度不都相同时,它是如何工作的。注意:维基百科文章中的多模式伪代码似乎是错误的。但是应该给你一个起点。

本着快速和肮脏的精神:

fgrep --mmap -f query-file corpus-file

文本搜索引擎中使用的数据结构称为。正如人们所说的,非常好的开源搜索引擎是。

使用MapReduce,您不应该尝试在一步或一项工作中完成所有事情。看起来你应该把这个问题分成多个步骤。由于您正在生成存储在HDFS上的数据,并且您需要知道数据源,因此您可能应该选择以下格式:

{SOURCE}、{WORD}、{FREQUENCY}

请记住,您谈论的是分布式文件系统,因此将输入称为file1和file2在技术上是不正确的。您的参考数据和源数据都将分布在整个集群中,每个节点上都有各自的数据片段

接下来,从伪代码示例开始,您将需要创建一个将单词与源及其频率关联起来的作业。您的映射器工作正常,但是reduce需要将单词链接到源代码。您需要创建自己的可写对象,其中包含Map。这将作为后续过滤器作业可以使用的中间数据输出到HDFS

然后,可以使用此步骤的输出作为3个不同MapReduce作业的输入。其中每个都在寻找不同的源组合。这些工作将非常简单,因为映射器将只传递相同的数据,但是reducer将检查源的不同组合的每个值

因此,如果采用这种方法,您将需要4个MapReduce作业。您不需要手动运行每个作业,您可以有一个作业按顺序运行每个作业。或者,由于最后3个作业将使用相同的输入数据,因此可以在第一个作业完成后同时启动这三个作业。这可能取决于集群能够管理的数据量和中间数据量,以及每个作业需要的映射器/还原器的数量


希望这个建议能有所帮助。

我不确定它的性能,但Python的设计就是为了做这类事情:标记大型文本语料库并允许您对它们进行比较。《使用Python进行自然语言处理》一书使用了该工具包,并提供了许多示例。它是免费提供的。

编译为A.out的tokenizer.c可以对语料库进行标记,然后使用systemclose shell脚本实现高效性能

 ./a.out <
/live/memory/var/cache/man/whatis  | sort | awk {'print $1'} | uniq -c
| sort -rn > file.txt
/a.out<
/live/memory/var/cache/man/whatis | sort | awk{'print$1'}uniq-c
|sort-rn>file.txt

台式电脑可以做到这一点。更小的数据集可以放在内存中,这就是您所需要的

在Python中:

# Load the words from the small file into one big hash set
small_set = set(line.split()[0] for line in open("small.txt", "r"))

# Open 3 output files.
f1 = open("common.txt", "w")
f2 = open("large_only.txt", "w")
f3 = open("small_only.txt", "w")

# Find all words in the large set that aren't in the small set.
for line in open("large.txt", "r"):
    word = line.split()[0]
    if word in small_set:
        f1.write(line)  # word is in both sets
        small_set.remove(word)
    else:
        f2.write(line)  # word is in large but not small

# Everything left over in small_set wasn't in the large_set.
for word in small_set:
    f3.write(word + "\n")

集群可以更快地完成这项工作。但是你可以在家里试试。

因为你可以使用
comm
,我想你一定已经对输入文件进行了排序

这是一个类似于
comm
的程序,它只查看第一列,但生成包含整行输入的输出。它只有在输入被排序时才起作用

这是一个完整的程序。你所要做的就是把它放在一个文本文件中,然后从命令行运行它

#!/usr/bin/env python
#
# comm.py - Compare 2 sorted files line by line, based on the first column.
# Usage:   python compare.py FILE1 FILE2 OUTFILE1 OUTFILE2 OUTFILE12
# OUTFILE1 receives all entries that are only in FILE1, etc.

import sys

def compare(f1, f2, out1, out2, out12):
    def get(f):
        line = f.readline()
        if line == '':
            return None
        first, rest = line.rstrip('\n').split('\t', 1)
        return first, rest, line

    e1 = get(f1)
    e2 = get(f2)
    while e1 and e2:
        if e1[0] == e2[0]:   # common entry
            out12.write(e1[0] + "\t" + e1[1] + "\t" + e2[1] + "\n")
            e1 = get(f1)
            e2 = get(f2)
        elif e1[0] < e2[0]:  # e1 is not in f2
            out1.write(e1[2])
            e1 = get(f1)
        else:                # e2 is not in f1
            out2.write(e2[2])
            e2 = get(f2)
    if e1:
        buf = e1[2]
        while buf:
            out1.write(buf)
            buf = f1.read(8192)
    if e2:
        buf = e2[2]
        while buf:
            out2.write(buf)
            buf = f2.read(8192)

compare(open(sys.argv[1], "r"),
        open(sys.argv[2], "r"),
        open(sys.argv[3], "w"),
        open(sys.argv[4], "w"),
        open(sys.argv[5], "w"))
#/usr/bin/env python
#
#comm.py-基于第一列,逐行比较2个已排序的文件。
#用法:python compare.py FILE1 FILE2 OUTFILE1 OUTFILE2 OUTFILE12
#OUTFILE1接收仅在文件1中的所有条目,以此类推。
导入系统
def比较(f1、f2、out1、out2、out12):
def get(f):
line=f.readline()
如果行=='':
一无所获
首先,rest=line.rstrip('\n').split('\t',1)
R