Nltk: 讨论:复兴 Ngram 模型

创建于 2016-03-25  ·  21评论  ·  资料来源: nltk/nltk

嗨伙计!

我正在努力确保 Ngram 模型模块可以重新添加到 NLTK 中,并想提出几个问题以供讨论。

第 1 期
这里@afourney表示,最好添加插值作为默认 Katz 退避的替代方法,以作为处理看不见的 ngram 的一种方式。 我一直在考虑这个,我可能知道这是如何工作的。 我想由所有感兴趣的人来运行它。

model模块的当前类结构如下:

  • model.api.ModelI -> 我猜这应该是抽象类或接口。
  • model.ngram.NgramModel -> 在类之上扩展,包含 ngram 模型的当前实现。

这是我的建议:

  • model.api.Model -> 老实说,我不确定我是否明白这一点,对于是保留还是放弃它很矛盾。
  • model.ngram.BasicNgramModel -> 这与NgramModel减去与退避有关的所有内容。 基本上,它无法处理训练中看不见的 ngram。 “为什么会有这个?” - 你可能会问。 我认为这将是对退避/插值需求的一个很好的演示。 学生可以简单地尝试一下,看看说服自己使用其他课程的效果如何。
  • model.ngram.BackoffNgramModel -> 从BasicNgramModel继承以产生NgramModel的当前实现,除了它对退避部分更明确。
  • model.ngram.InterpolatedNgramModel -> 也继承自BasicNgramModel ,但使用插值而不是退避。

这里的长期目标是:

a) 允许任何ProbDist类用作概率估计器,因为插值/退避(主要)与所使用的平滑算法无关。
b) 允许任何想要为自己的目的 _optimize_ NgramModel 的人能够轻松地从 NLTK 中的类继承一些有用的默认值。

第二期
不幸的是,概率模块有它自己的问题(例如#602 和(我的)Kneser-Ney 实现是不稳定的)。 所以现在我只用LidstoneProbDist测试正确性,因为它很容易手工计算。 我是否应该担心缺乏对更高级平滑方法的支持? 或者我们是否希望以这种方式进行以确保至少 Ngram 模型有效,然后_然后_分别处理有问题的概率类?

Python 3 super()
调用super() ,是否需要担心支持 python 2? 请参阅上下文。

corpus enhancement language-model nice idea tests

最有用的评论

我认为在 NLTK 中绝对值得拥有; 这是当我的核心部分
教授 NLP。

NLTK 现在是否支持深度 LM? 这个 API 与那个兼容吗?


乔丹·博伊德-格雷伯

语音:920.524.9464
[email protected]

http://boydgraber.org

2017 年 10 月 3 日星期二晚上 11:32,alvations [email protected]写道:

@Copper-Head https://github.com/copper-head @jacobheil
https://github.com/jacobheil和感兴趣的 NLTK 用户/开发者
N-gram 语言模型。

就像签入模型子模块的当前状态一样。

  • 你认为它已经准备好将它推入开发/主控了吗?
    分支?
  • 是否仍然是人们积极追求并希望看到的话题
    NLTK?


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/nltk/nltk/issues/1342#issuecomment-334041035或静音
线程
https://github.com/notifications/unsubscribe-auth/AAhoqh5oxzo2Y9mp88I8uwy4lmyNz9Amks5sovxngaJpZM4H4nGe
.

所有21条评论

在 NLTK 中有一个工作的 n-gram 库会很好。 SRILM 有一些用于推理的 Python 包装器,但它具有限制性许可。 KenLM 有一个用于推理的 Python 包装器,但它在编译中具有依赖性。 两者都不支持估计。 所以目前没有经过良好测试的 n-gram 工具可用于 Python NLP。

@anttttti感谢您的反馈,看到对该功能的所有这些需求,我感到非常有动力提交补丁:)

你碰巧对我发布的具体问题有什么想法吗?

一旦您了解高级平滑方法仅在折扣和插值的定义方式上有所不同,它们就很容易实现。 早期的论文和大部分教科书描述使模型看起来比它们更复杂,因为人们之前并没有很好地理解它们之间的联系。 不需要单独的模块,只需配置平滑即可。 那些没有正确归一化的较旧的退避模型现在不再使用,请参阅 Joshua Goodman 的“语言建模的一点进展”以获得一个很好的总结。 http://arxiv.org/pdf/1602.02332.pdf第 63 页总结了 unigram 情况下折扣和插值的一些选择,高阶模型递归地使用相同的方法。 Kneser-Ney 对修改后的退避有点棘手。

对于大多数用途来说,平滑并不是那么重要。 有了足够的数据,即使经过优化,Kneser-Ney 也不比 Stupid Backoff 好。 因此,在 Python 中使用具有任何基本平滑的高阶 n-gram 会很好。 每个订单的 Lidstone 或 Jelinek-Mercer 都应该可以正常工作。

问题 1)我认为非常有用的一件事是拥有一个用于构建词汇表和审查 OOV 标记的实用程序。 这将纠正许多使用户对旧版本感到沮丧的愚蠢错误。 我附上了一些这样做的代码(随意使用或复制)
文件.txt

问题 2a) 我认为拥有 Kneser-Ney 仍然很有用; 它通常被教授,并且有一个参考实现很有用。
问题 2b) 我担心耦合 ProbDist 会使这比它需要的复杂得多。 对于诸如 KN 之类的东西,将概率估计保留在语言模型中可能更简单。 对于其他模型,使用 ProbDist 可能没问题。

@anttttti “_高级平滑方法很容易实现,一旦您了解它们仅在折扣和插值的定义方式上有所不同_”

@ezubaric "_Issue 2b) 我担心耦合 ProbDist 会使这比它需要的复杂得多_"

虽然我有一段时间没有看过这段代码,但我的感觉是这两种说法都是正确的。

如果我没记错的话,ConditionalProbDist(以及更普遍的 ProbDist)过早标准化,无法用于平滑的 ngram 模型。 例如,虽然我们知道一个词在给定上下文中的可能性有多大,但我们很难对上下文本身进行推理(我相信较早的补丁试图纠正这个问题——尽管尽了最大努力,但还是有点笨拙 [https: //github.com/nltk/nltk/pull/800])。

恕我直言,整个事情有点过度设计。

@afourney

恕我直言,整个事情有点过度设计。

但愿如此! 我现在一直在努力使这项工作永远有效(我提交了 #800,是的,它根本不优雅)而且我也开始认为有太多的活动部分以至于它不合理。

@ezubaric非常感谢那个文件,我完全借用了它的精神进行重构。

基于所有这些反馈,这是我对模块结构的新看法。 我们只有一个类: model.ngram.NgramModelCounter

这基本上是几个FreqDist计数器组合在一个清晰的界面中。 _Training_ 仅包括递归计算 ngram 的数量以及跟踪词汇大小(可能“最终确定”其中一些计数以防止在训练完成后进行更新)。 @alvations我知道你想要一个 trie 实现,但我认为我们现在可以从一个低效的递归计数器开始,稍后重构后端,因为它不应该对接口产生太大影响。

最重要的是,这个类处理在所有的概率。 这应该会使事情变得更加简单,同时更加灵活。 任何人添加概率所需要做的就是使用他们最喜欢的 OOP 方法(例如继承或组合)编写一个类,该类使用 NgramModel 的属性来构造它自己的prob()方法。

如果我有时间,我将提交一个(或两个!)示例,说明向 NgramModelCounter 添加概率如何工作。

你们怎么想?

@Copper-Head 尽可能与 KenLM 具有相似的界面,这对未来的集成有好处: https :

我认为在 NLTK 的NgramModel稳定版本发布后,我可以尝试重构kenlm包装器以使用与 NLTK 类似的接口,就像我们为scikit-learn所做的那样。

此功能也有助于填充: https :

我认为@Copper-Head 建议的是一个以协调的方式计算 unigrams、bigrams、trigrams 等的类,方便下游语言模型使用。 在这种情况下,我认为 kenlm API 还不适用。 (我可能是错的,但从发布的示例来看,kenlm API 看起来不像处理原始频率计数)

我认为考虑使用这些 ngram 计数的最小语言模型 API 也是值得的。 正如@Copper-Head 所暗示的那样,这将是一个子类,或者更好的是,一个完全独立的接口(允许完全不同的实现,如 https://www.projectoxford.ai/weblm)。 在这里,我认为采用 kenlm API 可能是合理的,但认为 _any_ ngram LM 接口应该足够简单,可以轻松编写适配器。

我认为最小的 ngram API 实际上只需要方法来 (1) 计算给定上下文或序列的标记的条件概率,以及 (2) 报告已知词汇表的大小和组成。 大多数其他东西都可以通过辅助方法计算,包括联合概率的计算,以及语言生成。 这些助手可能是也可能不是界面的一部分。

嗯,有趣的一点。 我想知道跟踪 GT 的这些计数是否可能会减慢训练速度,并且对于不想使用特定平滑的人来说是不必要的。 我认为在基本的NgramCounter类中做最少的事情可能更有意义,然后在专门用于 Good-Turing 的子类中简单地扩展它的训练(或__init__ )方法,甚至在一个面向计算 Good-Turing 概率的 ngram API 的实现。
但我只是坐下来写一些这些东西,所以也许它最终不会成为一个问题。

抱歉,我好像不小心删除了一个帖子。 为未来的读者填补缺失的上下文:我认为在设计 NgramModelCounter API 时考虑常见的平滑技术会很好。 例如,允许用户查询一次、两次或 N 次观察到的 _species_ 数量对于 Good-Turing 平滑(以及 Witten-Bell 平滑等)很重要。

编辑:看起来 FreqDist 类已经有一些这样的(参见:FreqDist.hapaxes 和 FreqDist.r_Nr)我想知道它是否可以重新利用? 或者如果 FreqDist 应该是起点。

我喜欢只拥有一个计数对象的想法,然后可以使用实现特定平滑方法的子类来查询该对象。

我唯一担心的是,如果我们没有及早修复词汇的能力,训练就会出现问题:它与标准的 LM 训练过程不一致,并且跟踪所有词汇会导致记忆力爆炸(这是一个旧的 LM 也有很大的问题)。

著名的。 我有如何解决这个问题的想法。 我将在今天晚些时候发布 PR。

PR #1351 上线了!! 提出问题/挑剔:)

@Copper-Head——我们离能够将它合并回主分支还有多远?

看看我的待办事项清单,我会说我需要 2-3 天的专注工作。
考虑到我在放学和日常工作的空闲时间重新开始处理这个问题,我会在 2 周到一个月之间的任何时间完成所有_我_未决问题。 这自然没有考虑到当时可能引起我注意的随机内容。

@Copper-Head @jacobheil和对 N-gram 语言模型感兴趣的 NLTK 用户/开发者。

就像签入model子模块的当前状态一样。

  • 你认为它已经准备好将它推送到开发/主分支了吗?
  • NLTK 上还是人们积极追求和想看到的话题吗?

我认为在 NLTK 中绝对值得拥有; 这是当我的核心部分
教授 NLP。

NLTK 现在是否支持深度 LM? 这个 API 与那个兼容吗?


乔丹·博伊德-格雷伯

语音:920.524.9464
[email protected]

http://boydgraber.org

2017 年 10 月 3 日星期二晚上 11:32,alvations [email protected]写道:

@Copper-Head https://github.com/copper-head @jacobheil
https://github.com/jacobheil和感兴趣的 NLTK 用户/开发者
N-gram 语言模型。

就像签入模型子模块的当前状态一样。

  • 你认为它已经准备好将它推入开发/主控了吗?
    分支?
  • 是否仍然是人们积极追求并希望看到的话题
    NLTK?


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/nltk/nltk/issues/1342#issuecomment-334041035或静音
线程
https://github.com/notifications/unsubscribe-auth/AAhoqh5oxzo2Y9mp88I8uwy4lmyNz9Amks5sovxngaJpZM4H4nGe
.

嗨 - 我想在 NLTK 中使用语言模型的“旧”功能。 仍然具有预训练语言模型(英语)的最新版本是什么?

对于那些找到这个线程的人,我已经把一个包含旧模型代码的子模块组合在一起。

https://github.com/sleepyfoxen/nltk_model

@stevenbird我想我们终于可以关闭了 :)

对于现有实现的具体反馈,人们可以打开单独的问题。

@Copper-Head 是的,我同意。 恭喜! :)

此页面是否有帮助?
0 / 5 - 0 等级