class_docstr: 条件随机场。提供 :meth:`forward` 以及 :meth:`viterbi_decode` 两个方法，分别用于 **训练** 与 **inference** 。
  
  :param num_tags: 标签的数量
  :param include_start_end_trans: 是否考虑各个 tag 作为开始以及结尾的分数。
  :param allowed_transitions: 内部的 ``Tuple[from_tag_id(int), to_tag_id(int)]`` 视为允许发生的跃迁，其他没
      有包含的跃迁认为是禁止跃迁，可以通过 :func:`allowed_transitions` 函数得到；如果为 ``None`` ，则所有跃迁均为合法。
class_docstr_tok: ["\u6761\u4ef6\u968f\u673a\u573a\u3002\u63d0\u4f9b",":","meth",":","`","forward","`","\u4ee5\u53ca",":","meth",":","`","viterbi_decode","`","\u4e24\u4e2a\u65b9\u6cd5\uff0c\u5206\u522b\u7528\u4e8e","*","*","\u8bad\u7ec3","*","*","\u4e0e","*","*","inference","*","*","\u3002",":","param","num_tags",":","\u6807\u7b7e\u7684\u6570\u91cf",":","param","include_start_end_trans",":","\u662f\u5426\u8003\u8651\u5404\u4e2a","tag","\u4f5c\u4e3a\u5f00\u59cb\u4ee5\u53ca\u7ed3\u5c3e\u7684\u5206\u6570\u3002",":","param","allowed_transitions",":","\u5185\u90e8\u7684","``","Tuple","[","from_tag_id","(","int",")",",","to_tag_id","(","int",")","]","``","\u89c6\u4e3a\u5141\u8bb8\u53d1\u751f\u7684\u8dc3\u8fc1\uff0c\u5176\u4ed6\u6ca1","\u6709\u5305\u542b\u7684\u8dc3\u8fc1\u8ba4\u4e3a\u662f\u7981\u6b62\u8dc3\u8fc1\uff0c\u53ef\u4ee5\u901a\u8fc7",":","func",":","`","allowed_transitions","`","\u51fd\u6570\u5f97\u5230\uff1b\u5982\u679c\u4e3a","``","None","``","\uff0c\u5219\u6240\u6709\u8dc3\u8fc1\u5747\u4e3a\u5408\u6cd5\u3002"]
code: def __init__(
      self,
      num_tags: int,
      include_start_end_trans: bool = False,
      allowed_transitions: List = None,
  ):
      super(ConditionalRandomField, self).__init__()
  
      self.include_start_end_trans = include_start_end_trans
      self.num_tags = num_tags
  
      # the meaning of entry in this matrix is (from_tag_id, to_tag_id) score
      self.trans_m = nn.Parameter(torch.randn(num_tags, num_tags))
      if self.include_start_end_trans:
          self.start_scores = nn.Parameter(torch.randn(num_tags))
          self.end_scores = nn.Parameter(torch.randn(num_tags))
  
      if allowed_transitions is None:
          constrain = torch.zeros(num_tags + 2, num_tags + 2)
      else:
          constrain = torch.full(
              (num_tags + 2, num_tags + 2),
              fill_value=-10000.0,
              dtype=torch.float,
          )
          has_start = False
          has_end = False
          for from_tag_id, to_tag_id in allowed_transitions:
              constrain[from_tag_id, to_tag_id] = 0
              if from_tag_id == num_tags:
                  has_start = True
              if to_tag_id == num_tags + 1:
                  has_end = True
          if not has_start:
              constrain[num_tags, :].fill_(0)
          if not has_end:
              constrain[:, num_tags + 1].fill_(0)
      self._constrain = nn.Parameter(constrain, requires_grad=False)
  
file_path: fastNLP/fastNLP/modules/torch/decoder/crf.py
imports: from typing import Union, List, Tuple
  import torch
  from torch import nn
  from ....core.metrics.span_f1_pre_rec_metric import _get_encoding_type_from_tag_vocab, _check_tag_vocab_and_encoding_type
  from ....core.vocabulary import Vocabulary
label_desc: Use image node_id 1 to create a new ConditionalRandomField object from inherited base classes: nn with example: obj = ConditionalRandomField(num_tags, include_start_end_trans, allowed_transitions)