构建基于计数的分布模型时,长度为 5 的 ngram 的数据结构选择

Posted

技术标签:

【中文标题】构建基于计数的分布模型时,长度为 5 的 ngram 的数据结构选择【英文标题】:Data structure choice for ngrams upto length 5, when building count-based distributional model 【发布时间】:2016-04-07 22:31:02 【问题描述】:

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

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

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

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

有什么建议吗?使用数据库有什么价值吗?他们可以在没有内存的情况下做到这一点吗?

【问题讨论】:

我想这就是他们所说的“大数据”。 【参考方案1】:

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

也许您也可以尝试二进制前缀树。首先,您创建一个单独的字符字符串,例如通过将单词的字母交织成一个字符串(我想您也可以将它们连接起来,用空格分隔)。然后可以将这个长字符串存储在二进制树中。示例见CritBit1D。

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

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

【讨论】:

以上是关于构建基于计数的分布模型时,长度为 5 的 ngram 的数据结构选择的主要内容,如果未能解决你的问题,请参考以下文章

5分钟实现SpringBoot整合Dubbo构建分布式服务

北大微软提出NGra:高效大规模图神经网络计算

Oracle/SQL - 基于参数的动态列

构建之法阅读笔记

计数排序

中文分词