BERT与Colab

万壑松风知客来,摇扇抚琴待留声

Google 在我心中一直是顶尖级的技术大佬,能用 Google 解决的问题,就别想其它了,至于为什么这里举两个例子:BERT 与 Colab。

给个前言吧:

BERT 与 Colab 都是我在第一家公司实习时遇见的,第一次相遇总是难忘的美好,而这份美好我想留给另一个自己。谈不上熟悉,两者目前我都只使用过一次,而且道路艰难,所以文章谈不上深奥或佳作,仅仅是简单的抛砖引玉,开始吧。

BERT:

BERT 全称:Bidirectional Encoder Representations from Transformers,是 Google 开源的 NLP 预训练新技术,经测试取得了多项非凡的成绩,甚至超越了人类 (Github 仓库)。

BERT 技术:

BERT 是第一个深度、双向、无监督的语言表示模型,仅使用无标签的文本语料库进行训练的模型。该模型机构复杂,加上语料庞大,在顶级民用的 GPU 上都需要训练长达数个月之久。不过一个好消息是,Google 已经替我们训练好了不同的基础模型支持(BERT-Base),包括中文及多种其它语言。有了这些预训练模型就算你不会 NLP 也能通过 BERT 微调机制得到一个很不错的结果。

例如我,(除了 word2vec 后建立机器学习模型算法)自然语言的处理我并不擅长,所以关于 BERT 的原理还需参考官方文档。本文旨在阐述如何简单使用 BERT(通过结果显示我一度认为熟练使用该工具可以取代自然语言算法工程师~~)

BERT 文本分类:

在自然语言处理中,文本分类是很常见的问题,如:情感分析、情绪分级等。这类问题可以通过使用 BERT 框架进行微调适应不同场景,下面通过一个例子来说明。

首先要使用 BERT 微调的方法,需要在该 GitHub 仓库下,下载预训练模型(如下图,这里选择中文预训练模型),我尝试在 Windows 下进行分类。Linux 下可以:

1
2
3
# 下载预训练模型
wget -nc "https://storage.googleapis.com/bert_models/2018_11_03/chinese_L-12_H-768_A-12.zip"
unzip -o "chinese_L-12_H-768_A-12.zip"

1

接着克隆 BERT 的官方仓库(如上所给),以便可以直接使用Google所提供的相关源码。

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

在该仓库下包含多个文件,但完成文本分类的代码放在 run_classifier.py ,该文件中包含 Google 提供了在 4 个基准数据集上的测试代码,并对应在 XnliProcessor,MnliProcessor,MrpcProcessor 和 ColaProcessor 中。如果需要完成自己的文本分类任务,只需要模仿其形式改写自己的类即可。

改写 Processor 类:

如果熟悉的话,改写 Processor 类并不难,打开刚才克隆下来的仓库,找到 run_classifier.py 文件,添加一个自定义的类,这里以 DaiProcessor 为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class DaiProcessor(DataProcessor):
# 返回训练集
def get_train_examples(self,data_dir):
return self._create_examples(self._read_tsv(os.path.join(data_dir,'train.csv')),'train') # 传入 通过_read_tsv函数读取给定路径下的文件、文件类型名
# 返回验证集
def get_dev_examples(self,data_dir):
return self._create_examples(self._read_tsv(os.path.join(data_dir,'dev.csv')),'dev')
# 返回测试集
def get_test_examples(self,data_dir):
return self._create_examples(self._read_tsv(os.path.join(data_dir,'test.csv')),'test')
# 指定文本分类标签并返回
def get_labels(self):
return ["-1","0","1","2"]
# 上面函数调用的处理数据方法
def _create_examples(self,lines,set_type):
examples = []
for (i,line) in enumerate(lines):
guid = "%s-%d" % (set_type,i) # 索引
# print("{0}数据:{1}:".format(set_type,line))
text_a = tokenization.convert_to_unicode(line[0]) # 每条文本数据需要使用tokenization.convert_to_unicode来处理
# label = None
if set_type != 'test':
label = line[1] # 不是测试集,则需要指定标签
else:
label = '-1' # 测试集(应该)可以随意指定一个以有标签
examples.append(InputExample(guid=guid,text_a=text_a,text_b=None,label=label)) # 指定 索引、文本a、文本b(这里单文本预测)、标签 添加到返回列表中
return examples

说明:本来应该在 get_train_examples、get_dev_examples、get_test_examples 函数中各自写一个 _create_examples 函数,但是可以根据实际情况将该函数写在外部,做修改同时兼容处理每个调用。其中有部分函数我们可以直接使用。其中路径参数 data_dir 为在运行文件时传入的参数;lines 为数据集,若有标签长度为2,如无标签则长度为1,具体训练、测试数据如下图(根据自身实际情况提供数据):

2

3

同时需要修改 main 函数,添加刚刚的自定义类 DaiProcessor:

1
2
3
4
5
6
7
8
9
10
def main(_):
tf.logging.set_verbosity(tf.logging.INFO)

processors = {
"cola": ColaProcessor,
"mnli": MnliProcessor,
"mrpc": MrpcProcessor,
"xnli": XnliProcessor,
"daihuidai": DaiProcessor # 给自定义类一个键名,后续运行程序调用
}

执行文本分类:

完成了上述工作,就可以执行文本分类了。参考 BERT 官方仓库的示例执行代码即可,这里所给为 Linux 下的运行代码,后续给出 Windows 下类似的运行代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
python run_classifier.py \
--task_name=daihuidai \ # 自己添加在processors字典里的key名
--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 # 输出文件路径

说明:只有在 run_classifier.py 中设置了相关的函数,才能开启对应方法,例如类中未定义验证集函数,则 --do_eval=false 即可。还有,一般模型预测并不和训练、验证一起做,都是先开启训练、验证,关闭模型预测;最后单独开启模型预测,关闭训练、验证。两次步骤传参不同,需要注意修改相关路径(后面 Windows 有说明区别较大)。

一段时间的训练后,预测结果会在输出文件路径下生成,经过判断准确率高达 90% 以上,而通过传统机器学习稍加处理在 70% 左右的。到此 Linux 下通过 BERT 来做文本分类的任务就完成了,下面我将介绍在 Windows 下结合 Colab 做 BERT 微调训练。

Colab:

Google Colab 全称 Colaboratory,(使用类似Jupyter)这是 Google 提供的一个免费云端机器学习服务,使用 GPU 为 Tesla K80。通过该服务,学习者可以在上面提升 Python 技能,使用 Keras、TensorFlow、PyTorch、OpenCV等等流行的深度学习库来练练手,开发深度学习应用。Google 贴心地提供了中文版的使用简介

所以这里不做单一的描述,下面通过在 Colab 上运行 BERT 来作为一个说明。

连接 Google 云盘:

如果你需要使用外部数据,可以尝试连接 Google 云盘,通过配置 Colab 可以直接访问 Google 云盘上挂在的文件,当然这需要你将文件数据上传到 Google 云盘。配置代码如下:

首先运行下面这些代码,来安装必要的库、执行授权。

1
2
3
4
5
6
7
8
9
10
11
12
!apt-get install -y -qq software-properties-common python-software-properties module-init-tools
!add-apt-repository -y ppa:alessandro-strada/ppa 2>&1 > /dev/null
!apt-get update -qq 2>&1 > /dev/null
!apt-get -y install -qq google-drive-ocamlfuse fuse
from google.colab import auth
auth.authenticate_user()
from oauth2client.client import GoogleCredentials
creds = GoogleCredentials.get_application_default()
import getpass
!google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret} < /dev/null 2>&1 | grep URL
vcode = getpass.getpass()
!echo {vcode} | google-drive-ocamlfuse -headless -id={creds.client_id} -secret={creds.client_secret}

运行过程中会出现外部链接,你需要点击它,按操作点击下一步,最后复制验证码并粘贴到文本框里。

接着授权完成后,就可以挂载Google Drive了:

1
2
!mkdir -p drive
!google-drive-ocamlfuse drive

完成挂载后,查看右边的文件可以看到一个名字为 drive 的挂载文件,里面有你所上传到 Google 云盘的所有数据,调用文件的路径需从drive开始:drive/a文件、drive/a目录/b文件 等。

Colab 中训练模型:

前面说过预训练与预测分两步执行。通过正确设置参数也可以在本地 Windows 上运行代码,但由于配置过低,所以这个任务可以在 Colab 中更快完成。你需要上传之前克隆下来的仓库(run_classifier.py 做同样修改哦)到挂载文件中。此时便可以通过在 Colab 中指定路径调用这些源代码,下面为预训练执行代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
import os

file = 'drive/BERT/BERT/bert-master/run_classifier.py' # run_classifier.py文件路径
name = 'daihuidai' # 自定义类的键名
MY_DATASET = 'drive/BERT/BERT/data/second' # 数据存放位置
a = 'drive/BERT/BERT/chinese/vocab.txt' # 三个预训练模型
b = 'drive/BERT/BERT/chinese/bert_config.json'
c = 'drive/BERT/BERT/chinese/bert_model.ckpt'
model = 'drive/BERT/BERT/model/second' # 训练的模型保存地址
# 通过os模块调用终端运行代码
print("开始进行训练:")
print(os.system("python {0} --task_name={1} --do_train=true --do_eval=true --data_dir={2} --vocab_file={3} --bert_config_file={4} --init_checkpoint={5} --max_seq_length=128 --train_batch_size=32 --learning_rate=5e-5 --num_train_epochs=2.0 --output_dir={6}".format(file,name,MY_DATASET,a,b,c,model)))
print("训练完成,结果不为 0 则训练失败。")

特别注意参数名与参数的正确设置传入,通过上面的的训练,在指定路径下生成了用于预测的模型(一大堆文件),下面使用预测模型来进行数据预测。

Colab 中预测数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
import os

file = 'drive/BERT/BERT/bert-master/run_classifier.py'
name = 'daihuidai'
MY_DATASET = 'drive/BERT/BERT/data/second'
a = 'drive/BERT/BERT/chinese/vocab.txt'
b = 'drive/BERT/BERT/chinese/bert_config.json'
c = 'drive/BERT/BERT/model/second' # 通过上面训练后获得的模型路径
predict = 'drive/BERT/BERT/predict/second' # 预测数据输出路径

print("开始进行预测:")
print(os.system("python {0} --task_name={1} --do_predict=true --data_dir={2} --vocab_file={3} --bert_config_file={4} --init_checkpoint={5} --max_seq_length=128 --output_dir={6}".format(file,name,MY_DATASET,a,b,c,predict)))
print("预测完成,结果不为 1 则预测失败。")

说明:训练和预测的参数有较大不同,需要注意。开启 --do_predict=true 预测,关闭训练和测试。传入之前训练好的模型,指定预测数据输出位置。

总结:

通过 BERT 你能发现 Google 的强大技术,通过 Colab 你能发现 Google 的奉献精神。其中 BERT 的使用远不止于此,优秀的你肯定能发现更多。

这里还是记录一下心得:一个人的探索之路很奇妙、很充实,但同时带来的也是一个个需要独自面对的困难。在 get 到新知识的喜悦前,你可能正处在快两个星期的郁闷中。在坚持一下吧!说不定下一刻你就会感谢自己。