docstr: finetune with the specified dataset.
  
  Args:
      train_path(str): the train dataset path.
      dev_path(str): the dev dataset path.
      save_dir(str): the model params and dev dataset predict result save path.
      init_ckpt_path(str): incremental training load path.
      use_gpu(bool): use gpu or not.
      max_steps(int): max training steps.
      batch_size(int): the batch size.
      max_encode_len(int): the max encode length.
      max_decode_len(int): the max decode length.
      learning_rate(float): the learning rate.
      warmup_proportion(float): the warmup proportion.
      weight_decay(float): the weight decay magnitude.
      noise_prob(float): the nosie probability. see the ernie gen paper for details.
      label_smooth(float): the label smooth magnitude.
      beam_width(int): the beam size during evaluating the dev dataset.
      length_penalty(float): the length penalty during evaluating the dev dataset.
      log_interval(int): the log interval.
      save_interval(int): the save interval. dev set will be evaluated after saving.
  
  Return:
      result(dict): A Dictionary of shape::
          {
              last_save_path(str): last model save path.
              last_ppl(float): last model ppl.
          }
docstr_tok: ["finetune","with","the","specified","dataset",".","Args",":","train_path","(","str",")",":","the","train","dataset","path",".","dev_path","(","str",")",":","the","dev","dataset","path",".","save_dir","(","str",")",":","the","model","params","and","dev","dataset","predict","result","save","path",".","init_ckpt_path","(","str",")",":","incremental","training","load","path",".","use_gpu","(","bool",")",":","use","gpu","or","not",".","max_steps","(","int",")",":","max","training","steps",".","batch_size","(","int",")",":","the","batch","size",".","max_encode_len","(","int",")",":","the","max","encode","length",".","max_decode_len","(","int",")",":","the","max","decode","length",".","learning_rate","(","float",")",":","the","learning","rate",".","warmup_proportion","(","float",")",":","the","warmup","proportion",".","weight_decay","(","float",")",":","the","weight","decay","magnitude",".","noise_prob","(","float",")",":","the","nosie","probability",".","see","the","ernie","gen","paper","for","details",".","label_smooth","(","float",")",":","the","label","smooth","magnitude",".","beam_width","(","int",")",":","the","beam","size","during","evaluating","the","dev","dataset",".","length_penalty","(","float",")",":","the","length","penalty","during","evaluating","the","dev","dataset",".","log_interval","(","int",")",":","the","log","interval",".","save_interval","(","int",")",":","the","save","interval",".","dev","set","will","be","evaluated","after","saving",".","Return",":","result","(","dict",")",":","A","Dictionary","of","shape",":",":","{","last_save_path","(","str",")",":","last","model","save","path",".","last_ppl","(","float",")",":","last","model","ppl.","}"]
code: def finetune(
      self,
      train_path,
      dev_path=None,
      save_dir="ernie_gen_result",
      init_ckpt_path=None,
      use_gpu=True,
      max_steps=500,
      batch_size=8,
      max_encode_len=50,
      max_decode_len=50,
      learning_rate=5e-5,
      warmup_proportion=0.1,
      weight_decay=0.1,
      noise_prob=0,
      label_smooth=0,
      beam_width=5,
      length_penalty=1.0,
      log_interval=100,
      save_interval=200,
  ):
      """
      finetune with the specified dataset.
  
      Args:
          train_path(str): the train dataset path.
          dev_path(str): the dev dataset path.
          save_dir(str): the model params and dev dataset predict result save path.
          init_ckpt_path(str): incremental training load path.
          use_gpu(bool): use gpu or not.
          max_steps(int): max training steps.
          batch_size(int): the batch size.
          max_encode_len(int): the max encode length.
          max_decode_len(int): the max decode length.
          learning_rate(float): the learning rate.
          warmup_proportion(float): the warmup proportion.
          weight_decay(float): the weight decay magnitude.
          noise_prob(float): the nosie probability. see the ernie gen paper for details.
          label_smooth(float): the label smooth magnitude.
          beam_width(int): the beam size during evaluating the dev dataset.
          length_penalty(float): the length penalty during evaluating the dev dataset.
          log_interval(int): the log interval.
          save_interval(int): the save interval. dev set will be evaluated after saving.
  
      Return:
          result(dict): A Dictionary of shape::
              {
                  last_save_path(str): last model save path.
                  last_ppl(float): last model ppl.
              }
      """
      paddle.disable_static()
      paddle.set_device("gpu") if use_gpu else paddle.set_device("cpu")
  
      if init_ckpt_path is not None:
          logger.info("loading checkpoint from %s" % init_ckpt_path)
          sd = paddle.load(init_ckpt_path)
          self.model.set_state_dict(sd)
  
      train_dataset = self._load_dataset(train_path)
      attn_id = self.tokenizer.vocab["[MASK]"]
      trans_func = convert_example(
          tokenizer=self.tokenizer,
          attn_id=attn_id,
          tgt_type_id=1,
          max_encode_len=max_encode_len,
          max_decode_len=max_decode_len,
          noise_prob=noise_prob,
      )
  
      train_dataset = train_dataset.map(trans_func)
      train_batch_sampler = paddle.io.BatchSampler(
          train_dataset, batch_size=batch_size, shuffle=True
      )
      batchify_fn = lambda samples, fn=Tuple(
          Pad(axis=0, pad_val=self.tokenizer.pad_token_id),  # src_ids
          Pad(axis=0, pad_val=self.tokenizer.pad_token_id),  # src_pids
          Pad(
              axis=0, pad_val=self.tokenizer.pad_token_type_id
          ),  # src_tids
          Pad(axis=0, pad_val=self.tokenizer.pad_token_id),  # tgt_ids
          Pad(axis=0, pad_val=self.tokenizer.pad_token_id),  # tgt_pids
          Pad(
              axis=0, pad_val=self.tokenizer.pad_token_type_id
          ),  # tgt_tids
          Pad(axis=0, pad_val=self.tokenizer.pad_token_id),  # attn_ids
          Pad(
              axis=0, pad_val=self.tokenizer.pad_token_id
          ),  # tgt_labels
      ): after_padding(fn(samples))
      train_data_loader = DataLoader(
          dataset=train_dataset,
          batch_sampler=train_batch_sampler,
          collate_fn=batchify_fn,
          num_workers=0,
          return_list=True,
      )
  
      if dev_path:
          dev_dataset = self._load_dataset(dev_path)
          dev_dataset = dev_dataset.map(trans_func)
          dev_data_loader = DataLoader(
              dataset=dev_dataset,
              batch_size=batch_size,
              collate_fn=batchify_fn,
              num_workers=0,
              return_list=True,
          )
  
      label_num = self.model.word_emb.weight.shape[0]
      train_model = StackModel(self.model)
      lr_scheduler = LinearDecayWithWarmup(
          learning_rate, max_steps, warmup_proportion
      )
      # Generate parameter names needed to perform weight decay.
      # All bias and LayerNorm parameters are excluded.
      decay_params = [
          p.name
          for n, p in self.model.named_parameters()
          if not any(nd in n for nd in ["bias", "norm"])
      ]
      optimizer = paddle.optimizer.AdamW(
          learning_rate=lr_scheduler,
          parameters=self.model.parameters(),
          weight_decay=weight_decay,
          grad_clip=nn.ClipGradByGlobalNorm(1.0),
          apply_decay_param_fun=lambda x: x in decay_params,
      )
  
      rouge1 = Rouge1()
      rouge2 = Rouge2()
      global_step = 1
      if save_dir and not os.path.exists(save_dir):
          os.makedirs(save_dir)
      while True:
          for batch in train_data_loader:
              (
                  src_ids,
                  src_tids,
                  src_pids,
                  tgt_ids,
                  tgt_tids,
                  tgt_pids,
                  attn_ids,
                  mask_src_2_src,
                  mask_tgt_2_srctgt,
                  mask_attn_2_srctgtattn,
                  tgt_labels,
                  _,
              ) = batch
              if label_smooth > 0.0:
                  tgt_labels = nn.functional.label_smooth(
                      nn.functional.one_hot(tgt_labels, label_num),
                      epsilon=label_smooth,
                  )
  
              tgt_pos = paddle.nonzero(attn_ids == attn_id)
              loss = train_model(
                  src_ids,
                  src_tids,
                  src_pids,
                  tgt_ids,
                  tgt_tids,
                  tgt_pids,
                  attn_ids,
                  mask_src_2_src,
                  mask_tgt_2_srctgt,
                  mask_attn_2_srctgtattn,
                  tgt_labels,
                  tgt_pos,
              )
  
              loss.backward()
              optimizer.step()
              lr_scheduler.step()
              optimizer.clear_grad()
  
              if (
                  global_step % log_interval == 0
                  and paddle.distributed.get_rank() == 0
              ):
                  loss_np = loss.numpy()
                  ppl = np.exp(loss_np)
                  logger.info(
                      "[step %d / %d]train loss %.5f, ppl %.5f, elr %.3e"
                      % (
                          global_step,
                          max_steps,
                          loss_np,
                          ppl,
                          lr_scheduler.get_lr(),
                      )
                  )
              if (
                  save_dir
                  and global_step % save_interval == 0
                  and global_step > 0
              ):
                  loss_np = loss.numpy()
                  ppl = np.exp(loss_np)
                  save_name = "step_%s_ppl_%.5f.params" % (
                      global_step,
                      ppl,
                  )
                  save_path = os.path.join(save_dir, save_name)
                  logger.info("save the model in %s" % save_path)
                  paddle.save(self.model.state_dict(), save_path)
  
                  if dev_path:
                      self._evaluate(
                          self.model,
                          dev_data_loader,
                          self.tokenizer,
                          rouge1,
                          rouge2,
                          attn_id,
                          max_decode_len,
                          max_encode_len,
                          beam_width,
                          length_penalty,
                      )
  
              if global_step >= max_steps:
                  break
              global_step += 1
  
          if global_step >= max_steps:
              break
  
      if global_step % save_interval != 0:
          loss_np = loss.numpy()
          ppl = np.exp(loss_np)
          logger.info(
              "[final step %d]train loss %.5f, ppl %.5f, elr %.3e"
              % (global_step, loss_np, ppl, lr_scheduler.get_lr())
          )
          if save_dir:
              save_name = "step_%s_ppl_%.5f.pdparams" % (
                  global_step,
                  ppl,
              )
              save_path = os.path.join(save_dir, save_name)
              logger.info("save the model in %s" % save_path)
              paddle.save(self.model.state_dict(), save_path)
  
              if dev_path:
                  self._evaluate(
                      self.model,
                      dev_data_loader,
                      self.tokenizer,
                      rouge1,
                      rouge2,
                      attn_id,
                      max_decode_len,
                      max_encode_len,
                      beam_width,
                      length_penalty,
                  )
  
      result = {
          "last_save_path": "%s" % save_path,
          "last_ppl": ppl[0],
      }
  
      return result
  
imports: import os
  import sys
  import shutil
  from copy import deepcopy
  import numpy
  import paddle
  import paddle.nn
  from paddle.io import DataLoader
  import paddlehub
  from paddlehub.common.logger import logger
  from paddlehub.module.module import moduleinfo
  from paddlenlp.datasets import MapDataset
  from paddlenlp.data import Stack, Tuple, Pad
  from paddlenlp.metrics import Rouge1, Rouge2
  from paddlenlp.transformers import ErnieTokenizer, ErnieForGeneration, LinearDecayWithWarmup
  from .encode import convert_example, after_padding
  from .decode import post_process, beam_search_infilling
  from .model import StackModel
label_desc: Use image node_id 3 for calling the ErnieGen obj's underlying member method code with example usage: obj.finetune(train_path, dev_path, save_dir, init_ckpt_path, use_gpu, max_steps, batch_size, max_encode_len, max_decode_len, learning_rate, warmup_proportion, weight_decay, noise_prob, label_smooth, beam_width, length_penalty, log_interval, save_interval) and returns: result