class_docstr: nlp 里为了保证输出的句长 = 输入的句长，一般使用奇数 kernel_size，如 [3, 5, 7, 9]
  当然也可以不等长输出，keep_length 设为 False
  此时，padding = k // 2
  stride 一般为 1
docstr: in_channels      : 一般就是 word embedding 的维度，或者 hidden size 的维度
  out_channels     : int
  kernel_sizes     : list 为了保证输出长度=输入长度，必须为奇数: 3, 5, 7...
  activation       : [relu, lrelu, prelu, selu, celu, gelu, sigmoid, tanh]
  pooling_strategy : [max, avg, cls]
  dropout:         : float
code: def __init__(self, config):
      """
      in_channels      : 一般就是 word embedding 的维度，或者 hidden size 的维度
      out_channels     : int
      kernel_sizes     : list 为了保证输出长度=输入长度，必须为奇数: 3, 5, 7...
      activation       : [relu, lrelu, prelu, selu, celu, gelu, sigmoid, tanh]
      pooling_strategy : [max, avg, cls]
      dropout:         : float
      """
      super(CNN, self).__init__()
  
      # self.xxx = config.xxx
      self.in_channels = config.in_channels
      self.out_channels = config.out_channels
      self.kernel_sizes = config.kernel_sizes
      self.activation = config.activation
      self.pooling_strategy = config.pooling_strategy
      self.dropout = config.dropout
      self.keep_length = config.keep_length
      for kernel_size in self.kernel_sizes:
          assert (
              kernel_size % 2 == 1
          ), "kernel size has to be odd numbers."
  
      # convolution
      self.convs = nn.ModuleList(
          [
              nn.Conv1d(
                  in_channels=self.in_channels,
                  out_channels=self.out_channels,
                  kernel_size=k,
                  stride=1,
                  padding=k // 2 if self.keep_length else 0,
                  dilation=1,
                  groups=1,
                  bias=False,
              )
              for k in self.kernel_sizes
          ]
      )
  
      # activation function
      assert self.activation in [
          "relu",
          "lrelu",
          "prelu",
          "selu",
          "celu",
          "gelu",
          "sigmoid",
          "tanh",
      ], "activation function must choose from [relu, lrelu, prelu, selu, celu, gelu, sigmoid, tanh]"
      self.activations = nn.ModuleDict(
          [
              ["relu", nn.ReLU()],
              ["lrelu", nn.LeakyReLU()],
              ["prelu", nn.PReLU()],
              ["selu", nn.SELU()],
              ["celu", nn.CELU()],
              ["gelu", GELU()],
              ["sigmoid", nn.Sigmoid()],
              ["tanh", nn.Tanh()],
          ]
      )
  
      # pooling
      assert self.pooling_strategy in [
          "max",
          "avg",
          "cls",
      ], "pooling strategy must choose from [max, avg, cls]"
  
      self.dropout = nn.Dropout(self.dropout)
  
file_path: DeepKE/src/deepke/attribution_extraction/standard/module/CNN.py
imports: import math
  import torch
  import torch.nn
  import torch.nn.functional
label_desc: Use image node_id 1 to create a new CNN object from inherited base classes: nn with example: obj = CNN(config)