构建基于计数的分布模型

时间:2016-04-07 22:31:02

标签: java data-structures information-retrieval bigdata

我正在从文本构建分布式模型(基于计数)。基本上对于每个ngram(一系列单词),我必须存储一个计数。我需要合理快速地访问计数。对于n = 5,技术上所有可能的5克都是(10 ^ 4)^ 5,即使我假设保守估计10k字,这太高了。但是这些n-gram的许多组合在文本中不存在,因此不考虑5d数组的结构。

我构建了一个trie,其中每个单词都是一个节点。所以这个特里会很宽,最大深度为5.这给了我相当大的记忆。但是我训练了足够多的文件后,仍然会耗尽内存(64GB)。公平地说,我没有在这里使用任何超高效的Java实践。每个节点都有一个count,word的索引为int。然后我有一个HashMap来存储孩子。我最初是从列表开始的。每次我添加一个孩子时都试图对它进行排序,但是我在那里失去了很多时间,所以转移到了HashMap。即使有一个列表,我会在读完更多文件后耗尽内存。

所以我想我需要将我的任务分成几部分,将每个部分存储到磁盘上。但最终,在访问时我需要合并这些数据结构。所以我认为前进的方向是一个基于磁盘的解决方案,我知道哪个文件可以访问ngrams,这些文件以某种东西开头(某种排序)。正如我所看到的,trie的问题是当我去合并它时效率不高。我需要将两个部分加载到内存中进行合并。那不会真的有用。

您会推荐什么方法?我研究了一种基于HashMap编码的语言模型结构(就像berkeleylm使用的那样)。但在他们的用例中,他们不需要重建ngram,所以他们只是哈希它并将哈希值存储为上下文。我需要以后能够访问上下文。

有什么建议吗?使用数据库有什么价值吗?他们可以在没有记忆的情况下做到吗?

1 个答案:

答案 0 :(得分:1)

我不会使用HashMap,它的内存非常密集,一个简单的排序数组应该更好,然后就可以使用二进制搜索了。

也许你也可以尝试二进制前缀-trie。首先,您创建一个字符串,例如通过将单词的字母交错为单个字符串(我想您也可以将它们连接起来,用空格分隔)。然后可以将这个长字符串存储在二进制trie中。有关示例,请参阅CritBit1D

您还可以使用多维树。许多树仅限于64位数字,但你冷却将每个单词的八个前导ASCII字符转换为64位整数,然后将其存储为5D密钥。这应该比5D阵列更有效。多暗度索引是:kd-trees,R-trees或quadtree。 5-gram-count和完整的5-gram(包括剩余字符)可以单独存储在可与每个5D-KEY关联的VALUE中。

如果您使用的是Java,可以尝试我自己的tree。它是前缀共享的按位四叉树。它非常节省内存,非常适合较大的数据集(1M条目向上),并且本身使用'整数'而不是'浮点数'。它也有非常好的最近邻搜索。