文章目录

  • BERT是什么
  • BERT调优
    • 句子(对)分类任务
    • 分类器预测
  • 中文分类实践
    • 下载中文预训练模型
    • 修改run_classifier.py
    • 训练
    • 预测
  • 扩展阅读

介绍来自bert的github资料翻译,水平有限

BERT是什么

BERT是一种预训练语言表示的方法,在大量文本语料(维基百科)上训练了一个通用的“语言理解”模型,然后用这个模型去执行想做的NLP任务。BERT比之前的方法表现更出色,因为它是第一个用在预训练NLP上的无监督的、深度双向系统。

无监督意味着BERT只需要用纯文本语料来训练,这点非常重要,因为海量的文本语料可以在各种语言的网络的公开得到。

预训练表示可以是上下文无关的,也可以是上下文相关的,而且,上下文相关的表示可以是单向的或双向的。上下文无关模型例如word2vec或GloVe可以为词表中的每一个词生成一个单独的“词向量”表示,所以“bank”这个词在“bank deposit”(银行)和“river bank”(岸边)的表示是一样的。上下文相关的模型会基于句子中的其他词生成每一个词的表示。

BERT建立在最近的预训练相关表示工作之上——Semi-supervised Sequence Learning, Generative Pre-Training, ELMo,和ULMFit——但是关键是这些模型都是单向的或浅双向的。这以为意味着每个词之和它左边或右边的词相关。例如,在句子“I made an bank deposit”中,“bank”的单向表示只基于“I made a”而没有“deposit”。一些以前的工作也有结合了单独的左上下文和右上下文的,但只是用了一种简单的方式。BERT同时用左边和右边内容表示“bank”——“I made a … deposit”——从一个深度网络非常底层就开始了,所以说,他是deeply bidirectional(深层双向)的。

BERT用了一种简单的方法:我们遮蔽了输入的15%的单词,通过一个深层的双向transformer Encoder来运行整个序列,然后只预测被遮蔽的单词。

Input: the man went to the [MASK1] . he bought a [MASK2] of milk.
Labels: [MASK1] = store; [MASK2] = gallon

为了学习句子间的关系,我们也训练了一个简单的任务,能后用任何一种单语言语料:给出两个句子A和B,B是A的下一句,或者是语料中的两个随机句子?

Sentence A: the man went to the store .
Sentence B: he bought a gallon of milk .
Label: IsNextSentence
Sentence A: the man went to the store .
Sentence B: penguins are flightless .
Label: NotNextSentence

然后我们花了很长时间在大语料(Wikipedia + BookCorpus)上训练了一个大模型(12层到24层的Transformer),这就是BERT。

使用BERT后两个步骤:Pre-training和fine-tuning

Pre-training相当昂贵(四天,4到16台TPU),但每种语言是一次性程序(最近的模型只有英语,但多语言模型近期会发布)。我们正在发布大量的google论文中被训练的pre-trained模型。这样,多数NLP研究者将不用从最底层去训练模型。

Fine-tunin不昂贵。论文中的所有结果从相同的预训练模型开始,可以在一台单独的云TPU上一小时就可以复现,或者在GPU上需要几个小时。例如,SQuAD,任务,在一台单独的TPU上训练30分钟就可以达到F2值91%,这是一个经典的单系统。

BERT另一个重要的方面是,他极容易被用于多种NLP任务。论文中,我们展示了经典的结果 sentence-level (e.g., SST-2), sentence-pair-level (e.g., MultiNLI), word-level (e.g., NER), and span-level (e.g., SQuAD)他们都没修改过任务。

BERT调优

重点:论文中所有的结果是在一台64G RAM的TPU上调优的。所以用一台12-16GRAM的GPU去复现论文中BERT-Large的结果是不可能,因为,能fit到内存里的最大batch size太小了。我们正在努力提交代码能允许在GPU上用更大的batch size。详情看out of memory issues.

代码在TensorFlow1.11.0上测试,用python2 和python3(用python2更多,因为google内部用python2更多)。

用Bert-Base调优的例子用给定的超参数可以运行在至少12G内存的GPU上。

句子(对)分类任务

运行这个例子之前,你需要运行脚本下载GLUE数据集,并解压到$GLUE_DIR,然后,下载BERT-Base并解压到目录$BERT_BASE_DIR
这个例子对BERT-Base在MRPC(包括3600个例子,在多数GPU上运行只要几分钟)

export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export GLUE_DIR=/path/to/gluepython run_classifier.py \--task_name=MRPC \--do_train=true \--do_eval=true \--data_dir=$GLUE_DIR/MRPC \--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=128 \--train_batch_size=32 \--learning_rate=2e-5 \--num_train_epochs=3.0 \--output_dir=/tmp/mrpc_output/

得到如下结果:

***** Eval results *****eval_accuracy = 0.845588eval_loss = 0.505248global_step = 343loss = 0.505248

意思是Dev准确度为84.55%,像MRPC这样的小数据集有一个高方差在准确度上,即使是从相同的checkpoint上开始训练。如果训练多次(输出到不同的out_dir),你会发现结果再84%到88%之间。

一些其他的预训练模型在run_classifier.py上直接执行,所以按照这些例子去用BERT执行但句子或句子对分类任务特别直接明了。

提示:你可能看到了一条信息 Running train on CPU。这只是说明他挣运行在一些出云TPU以外的机器上,包括GPU。

分类器预测

训练好了分类器,就可以用与预测模式,通过 --do_predice=true命令。输入文件夹需要有一个test.tsv文件。输出被写在了输出文件夹中的test_results.tsv文件中。每行包括一个样例的输出,列为类别概率

export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12export GLUE_DIR=/path/to/glueexport TRAINED_CLASSIFIER=/path/to/fine/tuned/classifierpython run_classifier.py \--task_name=MRPC \--do_predict=true \--data_dir=$GLUE_DIR/MRPC \--vocab_file=$BERT_BASE_DIR/vocab.txt \--bert_config_file=$BERT_BASE_DIR/bert_config.json \--init_checkpoint=$TRAINED_CLASSIFIER \--max_seq_length=128 \--output_dir=/tmp/mrpc_output/

中文分类实践

下载中文预训练模型

从git上下载代码,并下载中文预训练模型

代码解压,模型解压,模型文件包括:
bert_config.json
bert_model.ckpt.data-00000-of-00001
bert_model.ckpt.index
bert_model.ckpt.meta
vocab.txt
看了下vocab.txt,一共两万多个,汉字简体+繁体显然没那么多,有一些英文字符,无意义字符串等

修改run_classifier.py

  1. 重载DataProcessor类
    按照自己文件的格式改写DataProcessor类,需要重写一下几个函数:
class ChiProcessor(DataProcessor):""" Processor for chinese multi-classes data set"""def __init__(self):self.labels = set()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_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_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_labels(self, data_dir):lines = self._read_tsv(os.path.join(data_dir, "train.tsv"))for line in lines:label = tokenization.convert_to_unicode(line[0])self.labels.add(label)return list(self.labels)def _create_examples(self, lines, set_type):examples = [] for (i, line) in enumerate(lines):guid = "%s-%s" % (set_type, i)text_a = tokenization.convert_to_unicode(line[1])label = tokenization.convert_to_unicode(line[0])self.labels.add(label)examples.append(InputExample(guid=guid, text_a=text_a, text_b=None, label=label))return examples

_read_tsv()函数可直接使用;新建_create_examples函数用来将读取的数据转化为InputExample格式。
我自己的train.tsv,格式如下:

label1 \t text1
label1 \t text2
label2 \t text3
......

查看InputExample类,定义如下:

class InputExample(object):"""A single training/test example for simple sequence classification."""def __init__(self, guid, text_a, text_b=None, label=None):"""Constructs a InputExample.Args:guid: Unique id for the example.text_a: string. The untokenized text of the first sequence. For singlesequence tasks, only this sequence must be specified.text_b: (Optional) string. The untokenized text of the second sequence.Only must be specified for sequence pair tasks.label: (Optional) string. The label of the example. This should bespecified for train and dev examples, but not for test examples."""self.guid = guidself.text_a = text_aself.text_b = text_bself.label = label

可以看到text_b,和label为可选。
在处理分类问题是,text_a为分类文本,label为类标;在处理文本相似性问题是,text_a为文本1,text_b为文本2,label为是否相似标记;相似问题可抽象为二分类问题。
def get_labels函数,为获取分类类标列表,在分类数少的情况下可以直接给出,如:

  def get_labels(self):"""See base class."""return ["0", "1"]

分类较多的情况下,可以按照上面的代码读取train文件中的类标,或者直接把类标写入一个文件进行读取。
2. 在主函数中添加processor

def main(_):tf.logging.set_verbosity(tf.logging.INFO)processors = {"cola": ColaProcessor,"mnli": MnliProcessor,"mrpc": MrpcProcessor,"xnli": XnliProcessor,"chi": ChiProcessor,}

添加后,可通过–task_name=chi调用ChiProcessor读取训练验证测试文件。

训练

在data文件,下准备train.tsv, dev.tsv, test.tsv文件。运行:

export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export DATA_DIR=/path/to/datapython run_classifier_mine.py \
--task_name=chi \
--do_train=true \
--do_eval=true  \
--do_predict=false \
--data_dir=$DATA_DIR \
--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=128 \
--train_batch_size=32 \
--learning_rate=2e-5 \
--num_train_epochs=3.0 \
--output_dir=/path/to/output

–do_train、–do_eval、–do_predict需至少有一个为true。–do_predict=true时,需要准备test.tsv,预测的结果也会一并写入–output_dir目录下。

预测

export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export DATA_DIR=/path/to/data
# TRAINED_CLASSIFIER为刚刚训练的输出目录,无需在进一步指定模型模型名称,否则分类结果会不对
export TRAINED_CLASSIFIER=/path/to/fine/tuned/classifierpython run_classifier.py \--task_name=chi \--do_predict=true \--data_dir=$DATA_DIR \--vocab_file=$BERT_BASE_DIR/vocab.txt \--bert_config_file=$BERT_BASE_DIR/bert_config.json \--init_checkpoint=$TRAINED_CLASSIFIER \--max_seq_length=128 \--output_dir=/tmp/output/

预测结果会写入–output_dir目录,格式:每行为一条数据的预测记过,每列为每个类别的概率。

扩展阅读

  • 从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史
  • 图解2018年领先的两大NLP模型:BERT和ELMo

BERT简介及中文分类相关推荐

  1. bert中文分类模型训练+推理+部署

    文章预览: 0. bert简介 1. bert结构 1. bert中文分类模型训练 1 下载bert项目代码 代码结构 2 下载中文预训练模型 3 制作中文训练数据集 2. bert模型推理 1.te ...

  2. 何使用BERT模型实现中文的文本分类

    原文网址:https://blog.csdn.net/Real_Brilliant/article/details/84880528 如何使用BERT模型实现中文的文本分类 前言 Pytorch re ...

  3. 详述BERT fine-tune 中文分类实战及预测

    这几天在研究bert fine-tune相关的知识,现在基本熟悉了,也踩了一些坑,记录一下,一是总结,二是备忘. bert 的 finetune 主要存在两类应用场景:分类和阅读理解.因分类较为容易获 ...

  4. 基于朴素贝叶斯和预训练Bert模型的中文句子情感分类实践

    基于朴素贝叶斯和预训练Bert模型的中文句子情感分类实践 1.任务介绍   本次实践选题为AI研习社2019年9月份举办的中文对话情感分析任务,并在原任务基础上进行了拓展.任务首先给定一中文语句数据集 ...

  5. 手把手教 | 使用Bert预训练模型文本分类(内附源码)

    作者:GjZero 标签:Bert, 中文分类, 句子向量 本文约1500字,建议阅读8分钟. 本文从实践入手,带领大家进行Bert的中文文本分类和作为句子向量进行使用的教程. Bert介绍 Bert ...

  6. bert模型可以做文本主题识别吗_GitHub - jkszw2014/TextClassify_with_BERT: 使用BERT模型做文本分类;面向工业用途...

    TextClassify_with_BERT 使用BERT模型做文本分类:面向工业用途 自己研究了当前开源的使用BERT做文本分类的许多存储库,各有各的缺点.通病就是面向学术,不考虑实际应用. 使用t ...

  7. Deeplearning4j 实战 (21):Bert简介及NLP问题应用

    Eclipse Deeplearning4j GitChat课程:https://gitbook.cn/gitchat/column/5bfb6741ae0e5f436e35cd9f Eclipse ...

  8. bert简介_BERT简介

    bert简介 BERT, Bi-directional Encoder Representation from Transformer, is a state of the art language ...

  9. 使用bert模型做句子分类

    使用bert模型微调做下游任务,在goole发布的bert代码和huggingface的transformer项目中都有相应的任务,有的时候只需要把代码做简单的修改即可使用.发现代码很多,我尝试着自己 ...

  10. 使用transformers框架导入bert模型提取中文词向量

    导言 在笔者的上一篇文章大白话讲懂word2vec原理和如何使用中提到了如何将词语转变成计算机能够识别的语言,即将文本数据转换成计算机能够运算的数字或者向量这个概念,并详细阐述了word2vec这个模 ...

最新文章

  1. JavaScript基础学习--事件代理
  2. iOS----------学习路线思维导图
  3. mysql tinyint和char(1)性能对比
  4. leetcode4两数相加
  5. 不修改数组找出重复的数字
  6. vk_down 每次下翻丙行 c++_笔记本接口不够用?不妨试试这款Type-C拓展坞,给你7个接口用...
  7. 如何使用 GRUB 2 直接从硬盘运行 ISO 文件
  8. 【正点原子STM32连载】第二章 STM32简介 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
  9. mysql批量sql语句 c_Mysql批量插入数据sql语句
  10. hive sql alter table 修改表操作小记
  11. 新版edge浏览器换主题皮肤,使用Chrome浏览器的主题皮肤
  12. python 图像格式转换文件夹下 jpg 转 bmp | 目录遍历
  13. lrd热加载方式启动本地web服务(我用于从github把别人服务器代码拉倒本地去搭建自己的网络服务)
  14. 红宝书初步研读随手笔记
  15. 再叙AngularJS
  16. 教程 参数设置_高分辨质谱教程汇总
  17. Qt单元测试工具 QTestlib
  18. 基于vue的tiptap编辑器插件(三)
  19. 联想笔记本进入BIOS开启Intel VT-x
  20. 2D游戏地图编辑器的制作(一)

热门文章

  1. 计算机如何安装无线网络适配器,小编教你电脑无线网卡驱动怎么安装
  2. 百分比布局参照物的总结
  3. java-net-php-python-springboot羽毛球场地管理系统演示录像计算机毕业设计程序
  4. ed是什么梗_美国大学EA,ED什么意思?
  5. mysql限制小数位_mysql-控制小数位数
  6. 1024程序员节日随笔
  7. PM也要学会每天反省
  8. DOS下常用网络命令技巧
  9. springboot:运行(部署)时出现WebServerException: Unable to create tempDir.
  10. viper4Android md风格,ViPER4Android音效驱动