Pytorch Bi-LSTM + CRF 代码详解

久闻LSTM + CRF的效果强大,最近在看Pytorch官网文档的时候,看到了这段代码,前前后后查了很多资料,终于把代码弄懂了。我希望在后来人看这段代码的时候,直接就看我的博客就能完全弄懂这段代码。
看这个博客之前,我首先建议看看
Pytorch 关于Bi-LSTM + CRF的解释
看完再看看这位的博客
Bi-LSTM-CRF for Sequence Labeling PENG
这两部分内容都看完了之后,我就接着上面这位的博客继续讲,他讲的很好了,只是没有讲的更细致。

首先我们来看看Score的定义:
这里写图片描述
这部分博主的解释很详细了,这里我想多提醒一下的是,我们的每一个Score都是对应于一个完整的路径,举例说
【我 爱 中国人民】对应标签【N V N】那这个标签就是一个完整的路径,也就对应一个Score值。

接下来我想讲的是这个公式

这里写图片描述

这个公式成立是很显然的,动笔算一算就知道了,代码里其实就是用了这个公式的原理,但是这位博主并没有详细解释代码是怎么实现这个公式的,所以我就写下这篇博客来完成这位博主没有做完的工作。
先上代码

def _forward_alg(self, feats):
    # Do the forward algorithm to compute the partition function
    init_alphas = torch.Tensor(1, self.tagset_size).fill_(-10000.)
    # START_TAG has all of the score.
    init_alphas[0][self.tag_to_ix[START_TAG]] = 0.

    # Wrap in a variable so that we will get automatic backprop
    forward_var = autograd.Variable(init_alphas)

    # Iterate through the sentence
    for feat in feats:
        alphas_t = []  # The forward variables at this timestep
        for next_tag in range(self.tagset_size):
            # broadcast the emission score: it is the same regardless of
            # the previous tag
            emit_score = feat[next_tag].view(
                1, -1).expand(1, self.tagset_size)
            # the ith entry of trans_score is the score of transitioning to
            # next_tag from i
            trans_score = self.transitions[next_tag].view(1, -1)
            # The ith entry of next_tag_var is the value for the
            # edge (i -> next_tag) before we do log-sum-exp
            next_tag_var = forward_var + trans_score + emit_score
            # The forward variable for this tag is log-sum-exp of all the
            # scores.
            alphas_t.append(log_sum_exp(next_tag_var))
        forward_var = torch.cat(alphas_t).view(1, -1)
    terminal_var = forward_var + self.transitions[self.tag_to_ix[STOP_TAG]]
    alpha = log_sum_exp(terminal_var)
    return alpha

我们看到有这么一段代码
next_tag_var = forward_var + trans_score + emit_score
我们主要就是来讲讲他。
首先这个算法的思想是:假设我们要做一个词性标注的任务,对句子【我 爱 中华人民】,我们要对这个句子做 这里写图片描述
意思就是 对这个句子所有可能的标注,都算出来他们的Score,然后按照指数次幂加起来,再取对数。一般来说取所有可能的标注情况比较复杂,我们这里举例是长度为三,但是实际过程中,可能比这个要大得多,所以我们需要有一个简单高效得算法。也就是我们程序中得用得算法, 他是这么算得。
先算出【我, 爱】可能标注得所有情况,取 log_sum_exp 然后加上 转换到【中国人民】得特征值 再加上【中国人民】对应得某个标签得特征值。其等价于【我,爱,中国人民】所有可能特征值指数次幂相加,然后取对数

接下来我们来验证一下是不是这样

首先我们假设词性一共只有两种 名词N 和 动词 V
那么【我,爱】得词性组合一共有四种 N + N,N + V, V + N, V + V
那么【爱】标注为N时得log_sum_exp 为
l o g ( e s c o r e ( N , N ) + s c o r e ( V , N ) ) log(e^{score(N,N)+score(V,N)}) log(escore(NN)+score(VN))
【爱】 标注为 V时的 log_sum_exp为
l o g ( e s c o r e ( N , V ) + s c o r e ( V , V ) ) log(e^{score(N,V)+score(V,V)}) log(e

  • 43
    点赞
  • 224
    收藏
    觉得还不错? 一键收藏
  • 33
    评论
评论 33
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值