• NER中BiLSTM-CRF解读Forward_algorithm


    Forward_algorithm

    如果你对下面的内容有疑惑,可能需要看一下我前一篇写的对BiLSTM-CRF的讲解
    CRF+BiLSTM代码分步骤解读

    讲解

    之前也讲过forward_algorithm的是用来求解所有路径得分之和的函数,下面将用一个具体的例子来讲解一下这个函数实现的流程。

    先随机初始化一个发射矩阵e_score (batch_size, seq_len, tags_size)

    再随机初始化一个发射矩阵t_score (tags_size, tags_size)

    创建一个init_matrix,然后再复制一份给pre_matrix,这里为了方便理解将模型竖起来 (batch_size, 1, tags_size)

    这里仅展示当时刻为0,状态为’B’时的计算过程

    下面都是在log_sum_exp中的临时变量

    代码

    def forward_algorithm(self, e_matrix):
    
      # matrix 是在当前状态下总路径之和
      init_matrix = torch.full((BATCH_SIZE, 1, tags_size), -10000.0)
      init_matrix[:, 0, self.s2i[START_TAG]] = 0.
    
      # 前一步的最优值
      pre_matrix = init_matrix
    
      # 循环时间
      for i in range(SEQ_LEN):
        # 保存当前时间步的的路径值
        matrix_value = []
        # 循环状态
        for s in range(tags_size):
          # 计算发射分数, (BATCH_SIZE, 1, tags_size)
          e_score = e_matrix[:, i, s].view(BATCH_SIZE, 1, -1).expand(BATCH_SIZE, 1, tags_size)
          # 计算转移分数 (1,tags_size)
          t_score = self.t_score[s, :].view(1, -1)
          # 下一步的得分 (BATCH_SIZE, 1, tags_size)
          next_matrix = pre_matrix + e_score + t_score
          # self.log_sum_exp(next_matrix) (BATCH_SIZE, 1)
          matrix_value.append(self.log_sum_exp(next_matrix))
          # 在把其记录到pre_matrix变量中
      	pre_matrix = torch.cat(matrix_value, dim=-1).view(BATCH_SIZE, 1, -1)
    
      # 最终的变量:之前的得分+转移到终点的得分 (BATCH_SIZE, 1, tags_size)
      terminal_var = pre_matrix + self.t_score[self.s2i[STOP_TAG], :]
      alpha = self.log_sum_exp(terminal_var)
      # (BATCH_SIZE,1)
      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
    • 31

    可看到这里也不太明白为什么这样做可以得到所有路径之和,其实,这样做无非是为了简化运算,但这样计算的不足在于使用了很多遍logsumexp,这就和原先的值其实有一些差距。

    理想值
    s c o r e i d e a l = l o g ( e S 1 + e S 2 + . . . + e S N ) (1) score_{ideal} = log(e^{S_1}+e^{S_2}+...+e^{S_N})\tag1 scoreideal=log(eS1+eS2+...+eSN)(1)
    现实值

    s c o r e r e a l i t y = l o g ( ∑ e p r e + t ) = l o g ( ∑ e l o g ( ∑ e p r e + t + e s ) + t ) = . . . (2)

    scorereality=log(epre+t)=log(elog(epre+t+es)+t)=...
    \tag2 scorereality=log(epre+t)=log(elog(epre+t+es)+t)=...(2)
    t->t_score
    es->e_score
    pre->pre_matrix

    如上图所示,🟣球处已经计算了从<START>到"我",前一步所有状态到B的全部路径得分S1,求logsumexp(S1)记录到🟣球处,同理🔵球处则是前两步所有路径到达"爱",并且所有状态转移至B的全部路径得分S2,求logsumexp(S2)记录到🔵球处。

    至此,你学废了吗?

  • 相关阅读:
    HTML 实现仿 Windows 桌面主题特效
    指针难点——数组指针、指针数组、函数指针、指针函数详解
    芯片设计后端遇到的各种文件类型和文件后缀
    【车间调度】基于matlab混合蛙跳算法 (SFLA) 求解简单调度问题【含Matlab源码 2247期】
    MySQL比较两个表数据的差异
    基于JavaWeb+SpringBoot+Vue摩托车商城微信小程序系统的设计和实现
    四旋翼电调驱动程序(STM32F1)
    每日LeetCode——Java版(一)
    Redis-Mysql八股总结
    Java多线程之 理解重排序
  • 原文地址:https://blog.csdn.net/qq_44833392/article/details/125488754