NLP学习记录(六)最大熵模型MaxEnt_顺序潜在最大熵强化学习(maxent rl)-程序员宅基地

技术标签: NLP自然语言处理理论篇  NLP  

原理

在叧掌握关于未知分布的部分信息的情况下,符合已知知识的概率分布可能有夗个,但使熵值最大的概率分布最真实地反映了事件的的分布情况,因为熵定义了随机变量的不确定性,弼熵值最大时,随机变量最不确定,最难预测其行为。


最大熵模型介绍

我们通过一个简单的例子来介绍最大熵概念。假设我们模拟一个翻译专家的决策过程,关于英文单词in到法语单词的翻译。我们的翻译决策模型p给每一个单词或短语分配一个估计值p(f),即专家选择f作为翻译的概率。为了帮助我们开发模型p,我们收集大量的专家翻译的样本。我们的目标有两个,一是从样本中抽取一组决策过程的事实(规则),二是基于这些事实构建这一翻译过程的模型。

我们能从样本中得到的一个明显的线索是允许的翻译候选列表。例如,我们可能发现翻译专家总是选择下面这5个法语词汇:{dans, en, à, au cours de, pendant}。一旦有了这些信息,我们可以给模型p施加第一个约束条件:

p(dans)+p(en)+ p(à)+p(au cours de)+p(pendant) = 1

这个等式代表了这一翻译过程的第一个统计信息,我们现在可以进行寻找满足这一条件的模型了。显然,有无数满足这个条件的模型可供选择。其中一个模型是p(dans)=1,换句话说这个模型总是预测dans。另外一个满足这一约束的模型是p(pendant)=1/2 and p(à)=1/2。 这两个模型都有违常理:只知道翻译专家总是选择这5个法语词汇,我们哪知道哪个概率分布是对的。两个模型每个都在没有经验支持的情况下,做了大胆的假设。最符合直觉的模型是:

p(dans) = 1/5

p(en) = 1/5

p(à) = 1/5

p(au cours de) = 1/5

p(pendant) = 1/5

这个模型将概率均匀分配给5个可能的词汇,是与我们已有知识最一致的模型。我们可能希望从样本中收集更多的关于翻译决策的线索。假设我们发现到有30%时间in被翻译成dans 或者en. 我们可以运用这些知识更新我们的模型,让其满足两个约束条件:

p(dans) + p(en) = 3/10

p(dans)+p(en)+ p(à)+p(au cours de)+p(pendant) = 1

同样,还是有很多概率分布满足这两个约束。在没有其他知识的情况下,最合理的模型p是最均匀的模型,也就是在满足约束的条件下,将概率尽可能均匀的分配。

p(dans) = 3/20

p(en) = 3/20

p(à) = 7/30

p(au cours de) = 7/30

p(pendant) = 7/30

假设我们又一次检查数据,这次发现了另外一个有趣的事实:有一般的情况,专家会选择翻译成dans 或 à.我们可以将这一信息列为第三个约束:

p(dans) + p(en) = 3/10

p(dans)+p(en)+ p(à)+p(au cours de)+p(pendant) = 1

p(dans)+ p(à)=1/2

我们可以再一次寻找满足这些约束的最均匀分配的模型p,但这一次的结果没有那么明显。由于我们增加了问题的复杂度,我们碰到了两个问题:首先,”uniform(均匀)”究竟是什么意思?我们如何度量一个模型的均匀度(uniformity)?第二,有了这些问题答案之后,我们如何找到满足一组约束且最均匀的模型?就像前面我们看到的模型。

最大熵的方法回答了这两个问题。直观上讲,很简单,即:对已知的知识建模,对未知的不过任何假设(model all that is known and assume nothing about that which is unknown)。换句话说,在给定一组事实(features+output)的条件下,选择符合所有事实,且在其他方面近可能均匀的模型,这恰恰是我们在上面例子每一步选择模型p所采取的方法。

  • Maxent Modeling

我们考虑一个随机过程,它产生一个输出y,y属于一个有穷集合。对于刚才讨论的翻译的例子,该过程输出单词in的翻译,输出值y可以是集合{dans, en, à, au cours de, pendant}中任何一个单词。在输出y时,该过程可能会被上下文信息x影响,x属于有穷的集合X。在目前的例子中,这信息可能包括英文句子中in周围的单词。

我们的任务是构造一个统计模型,该模型能够准确表示随机过程的行为。该模型任务是预测在给定上下文x的情况下,输出y的概率:p(y|x).
Training Data

为了研究这一过程,我们观察一段时间随机过程的行为,收集大量的样本:这里写图片描述。在我们讨论的例子中,每一个样本由包含in周围单词的词汇x,和in的翻译y组成。现在,我们可以假设这些训练样本已经由一个专家搞定了,我们提供大量包含in的随机的短语要求她选择一个合适的翻译。

我们可以通过它的经验分布来总结训练样本的特性:

这里写图片描述

通常,对于一个特定的pair (x, y),它要么不出现在样本中,要么最多出现几次。

  • Features and constraints

我们的目标是构造一个产生训练样本这一随机过程的统计模型。组成这个模型的模块将是一组训练样本的统计值。在目前的例子中,我们已经采用了几个统计数据:(1)in被翻译成dans 或者en的频率是3/10;(2) in被翻译成dans 或 à的概率是1/2 ;…等。这些统计数据是上下文独立的,但我们也可以考虑依赖上下文信息x的统计数据。例如,我们可能注意到,在训练样本中,如果 April 是一个出现在in之后,那么in翻译成en的频率有9/10.

为了表示这个事件(event),即当Aprial出现在in之后,in被翻译成en,我们引入了指示函数:

这里写图片描述

特征f 关于经验分布的期望值,正是我们感兴趣的统计数据。我们将这个期望值表示为:

这里写图片描述 (1)

我们可以将任何样本的统计表示成一个适当的二值指示函数的期望值,我们把这个函数叫做特征函数(feature function)或简称特征(feature)。

当我们发现一个统计量,我们觉得有用时,我们让模型去符合它(拟合),来利用这一重要性。拟合过程通过约束模型p分配给相应特征函数的期望值来实现。特征f关于模型p(y|x)的期望值是:

这里写图片描述 (2)

这里,是x在训练样本中的经验分布。我们约束这一期望值和训练样本中f的期望值相同。那就要求:

这里写图片描述 (3)

组合(1),(2) 和(3),我们得到等式:

这里写图片描述

我们称(3)为约束等式(constraint equation)或者简称约束(constraint)。我们只关注那么满足(3)的模型这里写图片描述,不再考虑那些和训练样本中特征f频率不一致的模型。

目前总结来看,我们现在有办法表示样本数据中内在的统计现象(叫做这里写图片描述),也有办法使我们的模型继承这一现象(叫做这里写图片描述)。

最后,仍我关于特征和约束再罗嗦两句:单词 feature'' andconstraint”在讨论最大熵时经常被混用,我们希望读者注意区分这两者的概念:特征(feature)是(x,y)的二值函数;约束是一个等式:即模型的特征函数期望值等于训练样本中特征函数的期望值。

  • The maxent prinple

假设给我们n个特征函数fi,它们的期望值决定了在建模过程中重要的统计数据。我们想要我们的模型符合这些统计,就是说,我们想要模型p属于的子集C。

这里写图片描述

图1是这一限制的几何解释。这里,P是三点上所有可能的概率分布空间。如果我们不施加任何约束(图a),所有概率模型都是允许的。施加一个线性约束C1后,模型被限制在C1定义的区域,如图b示。如果两个约束是可满足的, 施加第二个线性约束后可以准确确定p,如图c所示。另一种情形是,第二个线性约束与第一个不一致,例如,第一个约束可能需要第一个点的概率是1/3,第二个约束需要第三个点的概率是3/4,图d所示。在目前的设置中,线性约束是从训练数据集中抽取的,不可能手工构造,因此不可能不一致。进一步来说,在我们应用中的线性约束甚至不会接近唯一确定的p,就象图c那样。相反,集合C=C1∩C2∩C3∩…∩Cn中的模型是无穷的。

这里写图片描述

属于集合C的所有模型p中,最大熵的理念决定我们选择最均匀的分布。但现在,我们面临一个前面遗留的问题:什么是”uniform(均匀)”?

数学上,条件分布p(y|x)的均匀度就是条件熵定义:
这里写图片描述

熵的下界是0, 这时模型没有任何不确定性;熵的上界是log|Y|,即在所有可能(|Y|个)的y上均匀分布。有了这个定义,我们准备提出最大熵原则。

当从允许的概率分布集合C中选择一个模型时,选择模型这里写图片描述,使得熵H(p)最大。

这里写图片描述

可以证明这里写图片描述是well-defined的,就是说,在任何的约束集合C中,总是存在唯一的模型这里写图片描述取得最大熵。

  • Exponential form

最大熵原理呈现给我们的是一个约束优化问题:find the 这里写图片描述 which maximizes H(p)。简单的情况,我们可以分析求出问题的解。如翻译模型中我们施加前两个约束时,容易求得p的分布。不幸的是,通常最大熵模型的解无法明显得出,我们需要一个相对间接的方法。

为了解决这个问题,我们采用约束优化理论中Lagrange multipliers的方法。这里仅概述相关步骤,请参考进一步阅读以更深入了解约束优化理论如何应用到最大熵模型中的。

我们的约束优化问题是:
这里写图片描述

我们将这个称为原始问题(primal)。简单的讲,我们目标是在满足以下约束的情况下,最大化H(p)。

这里写图片描述

为了解决这个优化问题,引入Lagrangian 乘子。

这里写图片描述

实值参数这里写图片描述这里写图片描述对应施加在解上的n+1个约束。

下面的策略可以求出p的最优解(这里写图片描述),但我们不打算证明它。

首先,将这里写图片描述这里写图片描述看成常量,寻找p最大化公式(8)。这会产生以这里写图片描述这里写图片描述为参数的表示式p,(参数没有解决)。接着,将该表达式代回(8)中,这次求这里写图片描述这里写图片描述的最优解( 这里写图片描述and这里写图片描述 ,respectively)。

按照这一方式,我们保证这里写图片描述这里写图片描述不变,计算在所有这里写图片描述空间下,计算这里写图片描述的无约束的最大值。

这里写图片描述

令该式等于0, 求解 p(y|x):

这里写图片描述

可以看出公式(10)的第二个因子对应第二个约束:

这里写图片描述

将上式带入公式(10)得到:

这里写图片描述

将公式(11)带入(10),我们得到:
这里写图片描述

因此,

这里写图片描述

Z(x)是正则化因子。

现在我们要求解最优值这里写图片描述,这里写图片描述 。显然,我们已经知道了这里写图片描述 ,还不知道这里写图片描述

为此,我们介绍新的符号,定义对偶函数这里写图片描述

这里写图片描述

对偶优化问题是:
这里写图片描述

因为p*和这里写图片描述是固定的,公式(15)的右边只有自由变量这里写图片描述

参数值等于这里写图片描述的p*就是一开始约束优化问题的最优解。这办法不明显看出为什么,但这的确是Lagrange multipliers理论的基本原理,通常叫做Kuhn-Tucker theorem(KTT)。详细的解释已经超出本文讨论的范围。我们简单地陈述最后结论:

满足约束C最大熵模型具有(13)参数化形式,最优参数这里写图片描述可以通过最小化对偶函数这里写图片描述求得。

补充说明:

这里写图片描述究竟是什么样呢? (记住我们要求这里写图片描述的最小值, 这是Lagrange multipliers理论的基本原理)

这里写图片描述

  • Maximum likelihood

最大似然率:找出与样本的分布最接近的概率分布模型。

比如:10次抛硬币的结果是:

画画字画画画字字画画

假设p是每次抛硬币结果为”画”的概率。

得到这样试验结果的概率是:

P = pp(1-p)ppp(1-p)(1-p)pp=p7(1-p)3

最大化似然率的方法就是:
这里写图片描述

最优解是:p=0.7

似然率的一般定义为:这里写图片描述

p(x)是模型估计的概率分布,这里写图片描述是结果样本的概率分布。

在我们的问题里,要估计的是p(y|x),最大似然率为:

这里写图片描述

因此,有:

这里写图片描述

这里的p具有公式(13)的形式,我们的结果进一步可以表述为:

最大熵模型这里写图片描述是具有公式(13)形式,且最大化样本似然率的模型。最大熵模型与最大似然率模型一致。

  • Computing the Parameters

要算λ,解析解肯定是行不通的。对于最大熵模型对应的最优化问题,GIS,lbfgs,sgd等等最优化算法都能解。相比之下,GIS大概是最好实现的。这里只介绍GIS算法。

具体步骤如下:

(1)set这里写图片描述 等于任意值, 比如等于0.

这里写图片描述

(2) 重复直到收敛:
这里写图片描述

这里,(t)是迭代下标,常数C定义为:
这里写图片描述, 实践中C是训练样本里最大的特征个数。尽管C再大些也没关系,但是它决定了收敛速度,还是取最小的好。

实际上,GIS算法用第N次迭代的模型来估算每个特征在训练数据中的分布。如果超过了实际的,就把相应参数这里写图片描述变小。否则,将它们变大。当训练样本的特征分布和模型的特征分布相同时,就求得了最优参数。

  • 最大熵实现

下面是GIS训练算法的python实现,代码不到100行。

from collections import defaultdict

import math


class MaxEnt(object):

    def __init__(self):

        self.feats = defaultdict(int)

        self.trainset = []

        self.labels = set()  



    def load_data(self,file):

        for line in open(file):

            fields = line.strip().split()

            # at least two columns

            if len(fields) < 2: continue

            # the first column is label

            label = fields[0]

            self.labels.add(label)

            for f in set(fields[1:]):

                # (label,f) tuple is feature 

                self.feats[(label,f)] += 1

            self.trainset.append(fields)



    def _initparams(self):

        self.size = len(self.trainset)

        # M param for GIS training algorithm

        self.M = max([len(record)-1 for record in self.trainset])

        self.ep_ = [0.0]*len(self.feats)

        for i,f in enumerate(self.feats):

            # calculate feature expectation on empirical distribution

            self.ep_[i] = float(self.feats[f])/float(self.size)

            # each feature function correspond to id

            self.feats[f] = i

        # init weight for each feature

        self.w = [0.0]*len(self.feats)

        self.lastw = self.w



    def probwgt(self,features,label):

        wgt = 0.0

        for f in features:

            if (label,f) in self.feats:

                wgt += self.w[self.feats[(label,f)]]

        return math.exp(wgt)



    """

    calculate feature expectation on model distribution

    """        

    def Ep(self):

        ep = [0.0]*len(self.feats)

        for record in self.trainset:

            features = record[1:]

            # calculate p(y|x)

            prob = self.calprob(features)

            for f in features:

                for w,l in prob:

                    # only focus on features from training data.

                    if (l,f) in self.feats:

                        # get feature id

                        idx = self.feats[(l,f)]

                        # sum(1/N * f(y,x)*p(y|x)), p(x) = 1/N

                        ep[idx] += w * (1.0/self.size)

        return ep



    def _convergence(self,lastw,w):

        for w1,w2 in zip(lastw,w):

            if abs(w1-w2) >= 0.01:

                return False

        return True



    def train(self, max_iter =1000):

        self._initparams()

        for i in range(max_iter):

            print 'iter %d ...'%(i+1)

            # calculate feature expectation on model distribution

            self.ep = self.Ep()           

            self.lastw = self.w[:]  

            for i,win enumerate(self.w):

                delta = 1.0/self.M * math.log(self.ep_[i]/self.ep[i])

                # update w

                self.w[i] += delta

            print self.w

            # test if the algorithm is convergence

            if self._convergence(self.lastw,self.w):

                break



    def calprob(self,features):

        wgts = [(self.probwgt(features, l),l) for l in self.labels]

        Z = sum([ w for w,l in wgts])

        prob = [ (w/Z,l) for w,l in wgts]

        return prob 



    def predict(self,input):

        features = input.strip().split()

        prob = self.calprob(features)

        prob.sort(reverse=True)

        return prob   

原文参考
https://blog.csdn.net/erli11/article/details/24718655

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u014258362/article/details/80816368

智能推荐

linux devkmem 源码,linux dev/mem dev/kmem实现访问物理/虚拟内存-程序员宅基地

文章浏览阅读451次。dev/mem: 物理内存的全镜像。可以用来访问物理内存。/dev/kmem: kernel看到的虚拟内存的全镜像。可以用来访问kernel的内容。调试嵌入式Linux内核时,可能需要查看某个内核变量的值。/dev/kmem正好提供了访问内核虚拟内存的途径。现在的内核大都默认禁用了/dev/kmem,打开的方法是在 make menuconfig中选中 device drivers --> ..._dev/mem 源码实现

vxe-table 小众但功能齐全的vue表格组件-程序员宅基地

文章浏览阅读7.1k次,点赞2次,收藏19次。vxe-table,一个小众但功能齐全并支持excel操作的vue表格组件_vxe-table

(开发)bable - es6转码-程序员宅基地

文章浏览阅读62次。参考:http://www.ruanyifeng.com/blog/2016/01/babel.htmlBabelBabel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行// 转码前input.map(item => item + 1);// 转码后input.map(function (item) { return item..._让开发环境支持bable

FPGA 视频处理 FIFO 的典型应用_fpga 频分复用 视频-程序员宅基地

文章浏览阅读2.8k次,点赞6次,收藏29次。摘要:FPGA视频处理FIFO的典型应用,视频输入FIFO的作用,视频输出FIFO的作用,视频数据跨时钟域FIFO,视频缩放FIFO的作用_fpga 频分复用 视频

R语言:设置工作路径为当前文件存储路径_r语言设置工作目录到目标文件夹-程序员宅基地

文章浏览阅读575次。【代码】R语言:设置工作路径为当前文件存储路径。_r语言设置工作目录到目标文件夹

background 线性渐变-程序员宅基地

文章浏览阅读452次。格式:background: linear-gradient(direction, color-stop1, color-stop2, ...);<linear-gradient> = linear-gradient([ [ <angle> | to <side-or-corner>] ,]? &l..._background线性渐变

随便推点

【蓝桥杯省赛真题39】python输出最大的数 中小学青少年组蓝桥杯比赛 算法思维python编程省赛真题解析-程序员宅基地

文章浏览阅读1k次,点赞26次,收藏8次。第十三届蓝桥杯青少年组python编程省赛真题一、题目要求(注:input()输入函数的括号中不允许添加任何信息)1、编程实现给定一个正整数N,输出正整数N中各数位最大的那个数字。例如:N=132,则输出3。2、输入输出输入描述:只有一行,输入一个正整数N输出描述:只有一行,输出正整数N中各数位最大的那个数字输入样例:

网络协议的三要素-程序员宅基地

文章浏览阅读2.2k次。一个网络协议主要由以下三个要素组成:1.语法数据与控制信息的结构或格式,包括数据的组织方式、编码方式、信号电平的表示方式等。2.语义即需要发出何种控制信息,完成何种动作,以及做出何种应答,以实现数据交换的协调和差错处理。3.时序即事件实现顺序的详细说明,以实现速率匹配和排序。不完整理解:语法表示长什么样,语义表示能干什么,时序表示排序。转载于:https://blog.51cto.com/98..._网络协议三要素csdn

The Log: What every software engineer should know about real-time data's unifying abstraction-程序员宅基地

文章浏览阅读153次。主要的思想,将所有的系统都可以看作两部分,真正的数据log系统和各种各样的query engine所有的一致性由log系统来保证,其他各种query engine不需要考虑一致性,安全性,只需要不停的从log系统来同步数据,如果数据丢失或crash可以从log系统replay来恢复可以看出kafka系统在linkedin中的重要地位,不光是d..._the log: what every software engineer should know about real-time data's uni

《伟大是熬出来的》冯仑与年轻人闲话人生之一-程序员宅基地

文章浏览阅读746次。伟大是熬出来的  目录  前言  引言 时间熬成伟大:领导者要像狼一样坚忍   第一章 内圣外王——领导者的心态修炼  1. 天纵英才的自信心  2. 上天揽月的企图心  3. 誓不回头的决心  4. 宠辱不惊的平常心  5. 换位思考的同理心  6. 激情四射的热心  第二章 日清日高——领导者的高效能修炼  7. 积极主动,想到做到  8. 合理掌控自己的时间和生命  9. 制定目标,马..._当狼拖着受伤的右腿逃生时,右腿会成为前进的阻碍,它会毫不犹豫撕咬断自己的腿, 以

有源光缆AOC知识百科汇总-程序员宅基地

文章浏览阅读285次。在当今的大数据时代,人们对高速度和高带宽的需求越来越大,迫切希望有一种新型产品来作为高性能计算和数据中心的主要传输媒质,所以有源光缆(AOC)在这种环境下诞生了。有源光缆究竟是什么呢?应用在哪些领域,有什么优势呢?易天将为您解答!有源光缆(Active Optical Cables,简称AOC)是两端装有光收发器件的光纤线缆,主要构成部件分为光路和电路两部分。作为一种高性能计..._aoc 光缆

浏览器代理服务器自动配置脚本设置方法-程序员宅基地

文章浏览阅读2.2k次。在“桌面”上按快捷键“Ctrl+R”,调出“运行”窗口。接着,在“打开”后的输入框中输入“Gpedit.msc”。并按“确定”按钮。如下图 找到“用户配置”下的“Windows设置”下的“Internet Explorer 维护”的“连接”,双击选择“自动浏览器配置”。如下图 选择“自动启动配置”,并在下面的“自动代理URL”中填写相应的PAC文件地址。如下..._設置proxy腳本