Bert是一种更合理的语言模型,基于bert预训练模型fine-tune可以完成文本分类、问答匹配等任务。本文主要记录使用bert预训练语言模型做二分类文本分类的实验过程。
源码下载:https://github.com/google-research/bert
预训练模型版本:(1)chinese_L-12_H-768_A-12对应BERT-Base, Chinese: Chinese Simplified and Traditional, 12-layer, 768-hidden, 12-heads, 110M parameters;(2)chinese_wwm_ext_L-12_H-768_A-12对应BERT-Large, Cased (Whole Word Masking): 24-layer, 1024-hidden, 16-heads, 340M parameters。
源码主要代码文件:(1)tokenization.py分词器(2)optimization.py优化器(3)modeling.py 模型原理(4)run_classifier.py基于前3个文件训练文本分类任务(5)extract_features.py基于前3个文件抽取词向量编码
实验流程
实验数据放在文件test_data文件夹下,依次是train.tsv、dev.tsv、test.tsv,数据格式:
label \t 无需提前分词的文本
针对个人数据需要在run_classifier.py文件,加入数据解析类,并在main()函数处加入相应调用key-value对应:
class TestProcessor(DataProcessor):
"""Processor for the MRPC data set (GLUE version)."""
def get_train_examples(self, data_dir):
"""See base class."""
return self._create_examples(
self._read_tsv(os.path.join(data_dir, "train.tsv")), "train")
def get_dev_examples(self, data_dir):
"""See base class."""
return self._create_examples(
self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev")
def get_test_examples(self, data_dir):
"""See base class."""
return self._create_examples(
self._read_tsv(os.path.join(data_dir, "test.tsv")), "test")
def get_labels(self):
"""See base class."""
return ["__label__neg", "__label__pos"]
def _create_examples(self, lines, set_type):
"""Creates examples for the training and dev sets."""
examples = []
for (i, line) in enumerate(lines):
guid = "%s-%s" % (set_type, i)
text_a = tokenization.convert_to_unicode(line[1])
if set_type == "test":
label = "__label__common"
else:
label = tokenization.convert_to_unicode(line[0])
examples.append(
InputExample(guid=guid, text_a=text_a, text_b=None, label=label))
return examples
def main(_):
...
processors = {
"cola": ColaProcessor,
"mnli": MnliProcessor,
"mrpc": MrpcProcessor,
"xnli": XnliProcessor,
"Test": TestProcessor, #
}
自己补入train.sh:
BERT_BASE_DIR=/home/yy/bert-master/chinese_wwm_ext_L-12_H-768_A-12
localdir=/home/yy/bert-master
inputdata=$localdir/test_data
echo $inputdata
outputmodel=$localdir/test_output
echo $outputmodel
python run_classifier.py \
--task_name=Test \
--do_train=true \
--do_eval=true \
--data_dir=$inputdata \
--vocab_file=$BERT_BASE_DIR/vocab.txt \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
--max_seq_length=40 \
--train_batch_size=128 \
--learning_rate=2e-5 \
--num_train_epochs=3.0 \
--output_dir=$outputmodel
自己补入test.sh:
BERT_BASE_DIR=/home/yy/bert-master/chinese_wwm_ext_L-12_H-768_A-12
localdir=/home/yy/bert-master
inputdata=$localdir/test_data
outputmodel=$localdir/test_output
python run_classifier.py \
--task_name=Test \
--do_predict=true \
--data_dir=$inputdata \
--vocab_file=$BERT_BASE_DIR/vocab.txt \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$outputmodel \
--max_seq_length=15 \
--predict_batch_size=256 \
--output_dir=$outputmodel
Tesla K80的GPU卡,40W样本,训练接近6h,是真的慢啊~
1.bert的tokenization.py分词器,逻辑上是按字切分的;
2.如果想替换成按词切分的,最好对应替换词表和预训练模型,不然效果不好。
nvidia-smi
# 设置选卡
if __name__ == "__main__":
os.environ["CUDA_VISIBLE_DEVICES"]="1"