• 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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    我们看到有这么一段代码
    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 为
    log(escore(N,N)+score(V,N))
    log(escore(N,N)+score(V,N))

    【爱】 标注为 V时的 log_sum_exp为
    log(escore(N,V)+score(V,V))
    log(escore(N,V)+score(V,V))

    我们的forward列表里就是存在着这两个值,即:
    [
    log(escore(N,N)+score(V,N))
    log(escore(N,N)+score(V,N))

    log(escore(N,N)+score(V,N))
    log(escore(N,N)+score(V,N))
    ]
    在这里我在提醒一下score(N,V)的定义,前面有写哈,可以翻前面取看看。
    假设【中华人民】得词性为N,我们按照代码来写一下公式,在forward列表对应位置相加就是这样
    [
    log(escore(N+N)+score(V+N)+N+N−>N)
    log(escore(N+N)+score(V+N)+N+N−>N)
    ,
    log(escore(N,V)+score(V,V))+N+V−>N
    log(escore(N,V)+score(V,V))+N+V−>N

    ]
    我们的N+N->N可以写成 log(eN+N−>N)log(eN+N−>N),这样的话,我们的列表就变成
    [
    log(escore(N,N)+score(V,N)+N+N−>N)log(escore(N,N)+score(V,N)+N+N−>N),
    log(escore(N,V)+score(V,V)+N+V−>N)log(escore(N,V)+score(V,V)+N+V−>N),
    ]
    再次回想一下score的定义,我们就能知道这个式子其实也就是等于
    [
    log(escore(∗,N,N))log(escore(∗,N,N)),log(escore(∗,V,N)log(escore(∗,V,N)
    ]
    我们对这个式子 long_sum_exp就变成了log∑(escore(∗,∗,N))log∑(escore(∗,∗,N))
    他的直观意义就是【中华人民】的词性为N的时候,整个score值的long_sum_exp
    以上是我们把【中华人民】作为N的举例,如果我们再举V的情况,计算过程同上,最后我们要把 中华人民两种情况的再做一次log_sum_exp,这样我们就完成了【我,爱,中华人民】所有情况的score值的log_sum_exp
    以上就是对LSTM+crf 的所有讲解,有问题,请留言
    ---------------------
    作者:Johnny_Cuii
    来源:CSDN
    原文:https://blog.csdn.net/cuihuijun1hao/article/details/79405740
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    Uncaught (in promise) Error: Redirected when going from "/login" to "/home" via a navigation guard.
    开始写实际业务代码之前的一些准备工作
    vue 路由的基本配置
    Vue + Vue-router + Element-ui 搭建一个非常简单的dashboard demo
    vue报错 ModuleBuildError: Module build failed: Error: `sass-loader` requires `node-sass` >=4. Please i(Cannot find module ‘node-sass‘ 解决办法)
    vuex-mutations
    vuex及axios的get方法获取数据
    如何实现提交笔记-Markedown
    如何将线上项目下载至本地或者借鉴代码
    Sublime text3 vue代码格式化插件
  • 原文地址:https://www.cnblogs.com/jfdwd/p/11185769.html
Copyright © 2020-2023  润新知