当前位置:   article > 正文

BERT模型使用及心得_4、运用bert的调参心得

4、运用bert的调参心得

这几天学习使用了一下BERT模型

先简单介绍一下:

       BERT是基于Vaswani et al(2017)的论文"Attention is all you need"中提出的transformer模型构建的多层双向transformoer encoder。就是说BERT只是一个NLP方向的编码器。他能对单独句子进行表征,也可以对问答等进行表征。具体的可以看文章https://blog.csdn.net/sinat_33761963/article/details/83578498。

       很惭愧,我主要是简单的应用,将12层的BERT当成一个黑箱子,在后面简单的加上一个全连接得出分类结果。输入文本——>训练——>得出结果。下面就主要记录下,我如何使用的。

       BERT是个开源的项目,能在github上下载源代码。值得一提到是,由于预训练消耗大量时间和资源,google还很贴心的给出了预训练的权重(模型),让我们进行微调即可。比较可惜的是中文预训练模型就一个。中文预训练模型如下。

模型解压,模型文件包括:
bert_config.json
bert_model.ckpt.data-00000-of-00001
bert_model.ckpt.index
bert_model.ckpt.meta
vocab.txt(除了中文字符,还有很多看不懂的特殊符号等)

首先,使用BERT的条件是tensorflow大于等于1.11.0(我使用的是1.11.0)

第一步:修改run_classifier.py

因为我是做分类,所以只看了这个

1、制作特定格式data

  1. class InputExample(object):
  2. """A single training/test example for simple sequence classification."""
  3. def __init__(self, guid, text_a, text_b=None, label=None):
  4. """Constructs a InputExample.
  5. Args:
  6. guid: Unique id for the example.
  7. text_a: string. The untokenized text of the first sequence. For single
  8. sequence tasks, only this sequence must be specified.
  9. text_b: (Optional) string. The untokenized text of the second sequence.
  10. Only must be specified for sequence pair tasks.
  11. label: (Optional) string. The label of the example. This should be
  12. specified for train and dev examples, but not for test examples.
  13. """
  14. self.guid = guid
  15. self.text_a = text_a
  16. self.text_b = text_b
  17. self.label = label

 可以发现它要求的输入分别是guid, text_a, text_b, label,其中text_b和label为可选参数。我们要做的是单个句子的分类任务,那么就不需要输入text_b。对了,我们是中文的模型,只能输入512个字符(具有长度限制)。

所以我们的输入需要是 label  /t text 。下面是个例子。label AD ,然后是tab,然后是文本。

AD	啊,看到的东西都可以说啊。嗯。嗯还有呢?这里面有什么东西

2、重载DataProcessor类

每一个模型都有一个Processor,我们的预测也许要制作一个。

  1. class MyProcessor(DataProcessor):
  2. """Processor for my task-news classification """
  3. def __init__(self):
  4. self.labels = ['AD', 'CTRL']
  5. def get_train_examples(self, data_dir):
  6. return self._create_examples(
  7. self._read_tsv(os.path.join(data_dir, 'traintext.csv')), 'train')
  8. def get_dev_examples(self, data_dir):
  9. return self._create_examples(
  10. self._read_tsv(os.path.join(data_dir, 'vaildtext.csv')), 'val')
  11. def get_test_examples(self, data_dir):
  12. return self._create_examples(
  13. self._read_tsv(os.path.join(data_dir, 'testtext.csv')), 'test')
  14. def get_labels(self):
  15. return self.labels
  16. def _create_examples(self, lines, set_type):
  17. """create examples for the training and val sets"""
  18. examples = []
  19. for (i, line) in enumerate(lines):
  20. guid = '%s-%s' %(set_type, i)
  21. #print("line[0]:",line[0])
  22. #print("line[1]:",line[1])
  23. text_a = tokenization.convert_to_unicode(line[1])
  24. label = tokenization.convert_to_unicode(line[0])
  25. examples.append(InputExample(guid=guid, text_a=text_a, label=label))
  26. return examples

def __init__(self):函数中self.labels = ['AD', 'CTRL']定义自己的分类标签。data三个文件,分别是训练集,验证集和测试集(或者是需要预测的目标)。可以看到_create_examples函数对于data的读取过程。如果改数据比较麻烦,也可以修改这个函数和这个类。

建立好了需要在main函数中的processors中增加自己的模型

  1. processors = {
  2. "cola": ColaProcessor,
  3. "mnli": MnliProcessor,
  4. "mrpc": MrpcProcessor,
  5. "xnli": XnliProcessor,
  6. "my": MyProcessor,
  7. }

3、修改loss输出

原生的是全部epochs训练好之后再验证,验证输出一个acc和loss。修改训练的部分,让他n个iter输出一次loss

  1. if FLAGS.do_train:
  2. train_file = os.path.join(FLAGS.output_dir, "train.tf_record")
  3. file_based_convert_examples_to_features(
  4. train_examples, label_list, FLAGS.max_seq_length, tokenizer, train_file)
  5. tf.logging.info("***** Running training *****")
  6. tf.logging.info(" Num examples = %d", len(train_examples))
  7. tf.logging.info(" Batch size = %d", FLAGS.train_batch_size)
  8. tf.logging.info(" Num steps = %d", num_train_steps)
  9. train_input_fn = file_based_input_fn_builder(
  10. input_file=train_file,
  11. seq_length=FLAGS.max_seq_length,
  12. is_training=True,
  13. drop_remainder=True)
  14. tensors_to_log={'train loss':'loss/Mean:0'} #修改
  15. logging_hook = tf.train.LoggingTensorHook(tensors=tensors_to_log,every_n_iter=20)#修改
  16. estimator.train(input_fn=train_input_fn, hooks=[logging_hook],max_steps=num_train_steps) #修改

第二步:训练

建立一个train.sh来存储训练的命令

  1. export BERT_BASE_DIR=./chinese_L-12_H-768_A-12#这里是存放中文模型的路径
  2. export DATA_DIR=. #这里是存放数据的路径
  3. python3 run_classifier.py \
  4. --task_name=my \ #这里是processor的名字
  5. --do_train=true \ #是否训练
  6. --do_eval=true \ #是否验证
  7. --do_predict=false \ #是否预测(对应test)
  8. --data_dir=$DATA_DIR \
  9. --vocab_file=$BERT_BASE_DIR/vocab.txt \
  10. --bert_config_file=$BERT_BASE_DIR/bert_config.json \
  11. --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
  12. --max_seq_length=512 \#最大文本程度,最大512
  13. --train_batch_size=4 \
  14. --learning_rate=2e-5 \
  15. --num_train_epochs=15 \
  16. --output_dir=./mymodel #输出目录

第三步:预测(测试)

  1. export BERT_BASE_DIR=./chinese_L-12_H-768_A-12
  2. export DATA_DIR=./mymodel
  3. # TRAINED_CLASSIFIER为刚刚训练的输出目录,无需在进一步指定模型模型名称,否则分类结果会不对
  4. export ./mymodel
  5. python3 run_classifier.py \
  6. --task_name=chi \
  7. --do_predict=true \
  8. --data_dir=$DATA_DIR \
  9. --vocab_file=$BERT_BASE_DIR/vocab.txt \
  10. --bert_config_file=$BERT_BASE_DIR/bert_config.json \
  11. --init_checkpoint=$TRAINED_CLASSIFIER \
  12. --max_seq_length=512 \
  13. --output_dir=./mymodel

其实简单点,把训练的do_predict=false改成true就行。在输出路径中会有一个test_results。打开是各个类的概率(二分类就有两列)。

 

注意点:

1、test数据文件也要有标签(可以随便弄一个)

2、tenserflow版本问题

3、输入只有512个字(包括标点,实际不到,分割时会添加字符)

 

参考文献

1、BERT简介及中文分类

2、【NLP】彻底搞懂BERT

3、BERT模型实战之多文本分类(附源码)

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/200419?site
推荐阅读
相关标签
  

闽ICP备14008679号