语言模型:使用NLTK训练

语言模型:使用NLTK训练并计算困惑度和文本熵

Author: Sixing Yan

这一部分主要记录我在阅读NLTK的两种语言模型源码时,一些遇到的问题和理解。

1. NLTK中训练语言模型MLE和Lidstone有什么不同

NLTK 中两种准备ngram语言模型的方式:最大似然估计MLE和平滑Lidstone。两者的实现方式都是基于统计信息,而没有进行又梯度更新的估计。

(1)使用语言模型计算困惑度或文本熵

使用NLTK构建了一个语言模型后,一般用于计算给定输入的困惑度 perplexity 或者文本熵 entropy 。这两个打分函数都调用了它们(MLELidstone)父类(LanguageModel)的score函数。

外部调用score的时候,其实是通过各自的unmasked_score函数计算的,MLELid有不同的unmasked_score函数

    def score(self, word, context=None):
        """Masks out of vocab (OOV) words and computes their model score.

        For model-specific logic of calculating scores, see the `unmasked_score`
        method.
        """
        return self.unmasked_score(
            self.vocab.lookup(word), self.vocab.lookup(context) if context else None
        )

(2)lm.MLE vs. lm.Lidstone的区别和联系

最大似然估计的核心方法

class MLE(LanguageModel):
    """Class for providing MLE ngram model scores.

    Inherits initialization from BaseNgramModel.
    """

    def unmasked_score(self, word, context=None):
        """Returns the MLE score for a word given a context.

        Args:
        - word is expcected to be a string
        - context is expected to be something reasonably convertible to a tuple
        """
        return self.context_counts(context).freq(word)

k平滑的核心方法

    def unmasked_score(self, word, context=None):
        """Add-one smoothing: Lidstone or Laplace.

        To see what kind, look at `gamma` attribute on the class.

        """
        counts = self.context_counts(context)
        word_count = counts[word]
        norm_count = counts.N()
        return (word_count + self.gamma) / (norm_count + len(self.vocab) * self.gamma)

这两个模型都是用了LanguageModel.context_counts()函数。

(3)现在探究一下两者unmasked_score函数都调用的context_counts函数。

    def context_counts(self, context):
        """Helper method for retrieving counts for a given context.

        Assumes context has been checked and oov words in it masked.
        :type context: tuple(str) or None

        """
        return (
            self.counts[len(context) + 1][context] if context else self.counts.unigrams
        )

如果没指定上下文的时候,这个函数返回的是self.counts.unigrams对象

那么再看self.counts是什么:默认情况下,是一个NgramCounter()对象

self.counts = NgramCounter() if counter is None else counter

(4)所以我希望知道self.counts.unigrams.freq(word)计算的是什么

self._counts[1] = self.unigrams = FreqDist() 可知,FreqDist().freq(word)对应是word的频率

word_count = counts[word] 的作用也是调取word的频率,所以和FreqDist().freq(word)的作用一样。

(5)结论

lm.MLE 是没加平滑的 lm.Lidstone方法

2. 另一个问题:如何使用context这个功能呢

context_counts()可知有context的时候会返回 self.counts[len(context) + 1][context]

然后看self.counts = NgramCounter()[len(context) + 1][context] 调用,它会使用self._counts 这个成员:

    def __getitem__(self, item):
        """User-friendly access to ngram counts."""
        if isinstance(item, int):
            return self._counts[item]
        elif isinstance(item, string_types):
            return self._counts.__getitem__(1)[item]
        elif isinstance(item, Sequence):
            return self._counts.__getitem__(len(item) + 1)[tuple(item)]

self._counts = defaultdict(ConditionalFreqDist)由此初始化,由第7行[len(word)][word]取到同长度下的该word的频数。

而从counts = self.context_counts(context);word_count = counts[word] 这部分看,它返回一个Key-value型的数据类型,类似于如果context=(word1, word2);len(content)=2,那么应该返回trigrams的类实例(这里用了len(item)+1做索引)。于是乎就是考虑了前面两个词,然后计量(word1, word2, word)这个组合。

(1)结论

使用context不用改变原有类的初始化,直接使用即可。

NgramCounter会根据输入的List[Tuple]tuple长度len(tuple)来设置ngram_order的值(具体可看update()函数)。所以如果fit( )的时候用的是ngrams(2)的列表,那么context输入的长度就必须是1。

问题是,self.context_counts(context)返回int值,它是怎么可以使用word_count = counts[word]这种调用呢?因为在计算 entropy 的时候,它会放入context内容。

具体实现细节,参考
http://www.nltk.org/_modules/nltk/lm/models.html#Lidstone
http://www.nltk.org/_modules/nltk/lm/api.html#LanguageModel
http://www.nltk.org/_modules/nltk/lm/counter.html#NgramCounter
http://www.nltk.org/_modules/nltk/probability.html#FreqDist.freq

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • 已经养成了习惯,出差的时候行李箱中一定要放一双跑鞋。只要时间允许,就一定要在去的那个城市里晨跑。 跑步对我来说,没...
    东里西门行走阅读 825评论 1 7
  • 每天在工作生活中忙碌穿梭,倍感亚历山大,但我们都知道三角形是最稳定的结构,所以不妨把三角形的家居家饰用品带回家,分...
    窗爸爸家居阅读 276评论 0 0
  • 此别墅设计案例: A484号别墅设计图纸及效果图介绍: 占地规格:门面14.3米X深度12.6米 一层面积:119...
    妮妮别墅阅读 826评论 0 0
  • 我和小李是发小,从穿开裆裤就每天黏在一起。生活在农村的我们,并没有因为物质条件的差异而影响我们的关系,我们一直...
    荣草阅读 202评论 0 0