cover

75. Google BERT 预训练技术#

75.1. 介绍#

2018 年,自然语言处理领域最大的新闻之一莫过于 Google BERT 的横空出世。Google BERT 声称是最先进的 NLP 预训练技术,支持中文和更多语言。相关论文中,BERT 展示了包括斯坦福问答数据集(SQUAD v1.1)在内 11 个 NLP 任务的最新结果,均取得了最好的效果。

75.2. 知识点#

  • Google BERT

  • NLP 预训练技术

BERT 是 Google 开源的 NLP 预训练技术,它的全称是 Bidirectional Encoder Representations from Transformers。

BERT 建立在最新的预训练与上下文相关的语言表示的工作之上,包括 Semi-supervised Sequence Learning、Generative Pre-Training、ELMo 和 ULMFit。然而,与以前的模型不同,BERT 是第一个深度、双向、无监督的语言表示模型,仅使用无标签的文本语料库(在本例中为维基百科)进行预训练。

由于模型结构复杂,再加上语料庞大,BERT 在目前最强商用 GPU 上都需要训练长达数个月之久。不过好消息是,Google 发布了支持中文以及多语言的预训练基础模型 BERT-Base。借助于预训练模型,我们就可以很轻松地完成多种 NLP 任务。

Exercise 75.1

开放型挑战

挑战:利用 Google BERT 提供的中文预训练语言模型,完成假新闻数据文本分类任务。我们建议你对提供的数据进行 8:2 切分,并最终得到测试集上的准确度。

提示:仔细阅读 官方开源页面 的说明和仓库 Issues 页面 已知问题来解决遇到的麻烦。

挑战需使用实验中提供的假新闻数据下载链接。

https://cdn.aibydoing.com/aibydoing/files/wsdm_mini.csv  # 假新闻数据
https://storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip # Google 提供下载链接

75.2.1. 指导说明#

本次挑战不适合于通过线上 Notebook 完成,推荐你在本地完成挑战。由于挑战难度较大,在此提供一些指导说明。请注意,示例代码无法正常执行,请仔细揣摩并灵活变通。

这里使用 BERT 完成文本分类将利用微调的方法,首先需要下载 Google 提供的预训练语言模型。然后,克隆 BERT 官方仓库,以便于直接利用 Google 提供的模型训练源码:

# 克隆 BERT 官方仓库
git clone https://github.com/google-research/bert.git

Google 提供的模型训练源码中,完成文本分类的代码放在 run_classifier.py 中。其中,Google 提供了在 4 个基准数据集上的测试代码,并对应 XnliProcessor,MnliProcessor,MrpcProcessor 和 ColaProcessor 中。那么,要想完成自己的文本分类任务,我们只需要模仿并改写类即可。

改写 Processor 类的过程非常简单,只需要按照自己的需要传入数据即可,建议参考源码中 XnliProcessor 类的实现过程,和本次分类任务比较相似。例如,我们这里把自己的文本分类类定为 WSDMProcessor,其中包含下面四个函数:

class WSDMProcessor(DataProcessor):
    # 传入训练数据
    def get_train_examples(self, data_dir):
        # 读取训练数据路径
        file_path = os.path.join(data_dir, 'train.csv')
        # 使用 Pandas 读取数据
        df = pd.read_csv(file_path)
        # 将训练数据切分为 80% 训练集和 20% 验证集
        df_train, self.df_dev = train_test_split(df, test_size=0.2)
        examples = []
        # 按 BERT 推荐格式处理数据
        for index, row in df_train.iterrows():
            guid = 'train-%d' % index  # 索引
            text_a = tokenization.convert_to_unicode(str(row[0]))  # 文本 1
            text_b = tokenization.convert_to_unicode(str(row[1]))  # 文本 2
            label = row[2]  # 文本标签
            examples.append(InputExample(guid=guid, text_a=text_a,
                                         text_b=text_b, label=label))
        return examples

    # 传入验证数据
    def get_dev_examples(self, data_dir):
        examples = []
        for index, row in self.df_dev.iterrows():
            guid = 'dev-%d' % index
            text_a = tokenization.convert_to_unicode(str(row[0]))
            text_b = tokenization.convert_to_unicode(str(row[1]))
            label = row[2]
            examples.append(InputExample(guid=guid, text_a=text_a,
                                         text_b=text_b, label=label))
        return examples

    # 传入测试数据(预测)
    def get_test_examples(self, data_dir):
        file_path = os.path.join(data_dir, 'test.csv')
        df_test = pd.read_csv(file_path)
        examples = []
        for index, row in df_test.iterrows():
            guid = 'test-%d' % index
            text_a = tokenization.convert_to_unicode(str(row[0]))
            text_b = tokenization.convert_to_unicode(str(row[1]))
            label = '0'  # 随意指定测试数据标签
            examples.append(InputExample(guid=guid, text_a=text_a,
                                         text_b=text_b, label=label))
        return examples

    def get_labels(self):
        return ['A', 'B', 'C'] # 示例三分类任务对应数据标签

你会发现,传入训练、验证和测试数据的函数基本一致,关键在于按 BERT 要求将数据处理成规定。

接下来,我们还需要修改 main() 函数中的 processors,添加刚刚自定义的 WSDMProcessor:

def main(_):
    tf.logging.set_verbosity(tf.logging.INFO)

    processors = {
        "cola": ColaProcessor,
        "mnli": MnliProcessor,
        "mrpc": MrpcProcessor,
        "xnli": XnliProcessor,
        "self": WSDMProcessor, # 添加自定义 Processor
    }

完成上面的工作,就可以开始执行文本分类任务了。按照 BERT 开源仓库示例的执行代码运行即可,例如:

python run_classifier.py \
  --task_name=self \  # 执行 processor
  --do_train=true \  # 开启训练模型
  --do_eval=true \  # 开启验证模型
  --do_predict=true \  # 开启测试模型
  --data_dir=./dataset \  # 数据路径
  --vocab_file=./chinese_L-12_H-768_A-12/vocab.txt \  # 预训练模型下载文件路径
  --bert_config_file=./chinese_L-12_H-768_A-12/bert_config.json \
  --init_checkpoint=./chinese_L-12_H-768_A-12/bert_model.ckpt \
  --max_seq_length=128 \  # 模型训练参数
  --train_batch_size=32 \
  --learning_rate=5e-5 \
  --num_train_epochs=1.0 \
  --output_dir=./dataset/output  # 输出文件路径

注意,只有定义了相关的函数,才开启相应的选项。例如,Processor 中未定义验证集函数,那么就把 --do_eval=false 即可。模型训练完成之后,会在输出文件路径下保留相应的模型和测试结果。

现在就自己去试一试吧,仔细阅读官方开源页面的说明和仓库 Issues 页面 已知问题来解决遇到的麻烦。


○ 欢迎分享本文链接到你的社交账号、博客、论坛等。更多的外链会增加搜索引擎对本站收录的权重,从而让更多人看到这些内容。