基于飛槳開源的持續學習的語義理解框架ERNIE 2.0,及基于此框架的ERNIE 2.0預訓練模型,在共計16個中英文任務上超越了BERT和XLNet, 取得了SOTA效果。本文帶你進一步深入了解ERNIE的技術細節。
一:ERNIE 簡介
1.1 簡介
Google 最近提出的 BERT 模型,通過隨機屏蔽15%的字或者word,利用 Transformer 的多層 self-attention 雙向建模能力,在各項nlp 下游任務中(如 sentence pair classification task,singe sentence classification task,question answering task) 都取得了很好的成績。但是,BERT 模型主要是聚焦在針對字或者英文word粒度的完形填空學習上面,沒有充分利用訓練數據當中詞法結構,語法結構,以及語義信息去學習建模。比如?“我要買蘋果手機”,BERT 模型?將?“我”,“要”,?“買”,“蘋”,?“果”,“手”,?“機”?每個字都統一對待,隨機mask,丟失了“蘋果手機” 是一個很火的名詞這一信息,這個是詞法信息的缺失。同時 我 + 買 + 名詞 是一個非常明顯的購物意圖的句式,BERT 沒有對此類語法結構進行專門的建模,如果預訓練的語料中只有“我要買蘋果手機”,“我要買華為手機”,哪一天出現了一個新的手機牌子比如栗子手機,而這個手機牌子在預訓練的語料當中并不存在,沒有基于詞法結構以及句法結構的建模,對于這種新出來的詞是很難給出一個很好的向量表示的,而ERNIE 通過對訓練數據中的詞法結構,語法結構,語義信息進行統一建模,極大地增強了通用語義表示能力,在多項任務中均取得了大幅度超越BERT的效果!!
?
1.2 下載地址(這么好用的模型趕緊下載起來吧!)
ERNIE 的Fine-tuning代碼和英文預訓練模型已通過飛槳開源
?
Github 地址:
https://github.com/PaddlePaddle/ERNIE
?
二:ERNIE 詳解
2.1 ERNIE 結構
2.1.1 ERNIE?初探
?
?
2.1.1 ERNIE?結構詳解
?
Figure 2:ERNIE?的encoder?結構詳解?
?
相比transformer,ERNIE?基本上是 transformer 的encoder 部分,并且encoder 在結構上是全部一樣的,但是并不共享權重,具體區別如下:
-
Transformer: 6 encoder layers, 512 hidden units, 8 attention heads
-
ERNIE Base: 12 encoder layers, 768 hidden units, 12 attention heads
-
ERNIE Large: 24 encoder layers,1024 hidden units, 16 attention heads
?
從輸入上來看第一個輸入是一個特殊的CLS, CLS 表示分類任務就像 transformer 的一般的encoder, ERINE 將一序列的words 輸入到encoder 中。?每層使用self-attention, feed-word network, 然后把結果傳入到下一個encoder。
?
2.1.2 ERNIE encoder?說明
encoder
encoder 由兩層構成, 首先流入self-attention layer,self-attention layer 輸出流入 feed-forward 神經網絡。至于self-attention的結構,我們在這里不再展開,有興趣的同學可以進入以下鏈接仔細閱讀http://jalammar.github.io/illustrated-transformer/,來進一步了解self-attention的結構!!
?
Figure 3: encoder?結構詳解
?
embedding
最下層的encoder的輸入是embedding的向量, 其他的encoder的輸入,便是更下層的encoder的輸出,?一般設置輸入的vectors 的維度為512,同學們也可以自己設置。
?
Figure 4: encoder?結構詳解
?
2.2 : ERNIE 1.0 介紹
相比于BERT, ERNIE 1.0 改進了兩種 masking 策略,一種是基于phrase (在這里是短語 比如 a series of, written等)的masking策略,另外一種是基于 entity(在這里是人名、位置、組織、產品等名詞,比如Apple, J.K. Rowling)的masking 策略。在ERNIE 當中,將由多個字組成的phrase 或者entity 當成一個統一單元,相比于bert 基于字的mask,這個單元當中的所有字在訓練的時候,統一被mask。對比直接將知識類的query 映射成向量然后直接加起來,ERNIE 通過統一mask的方式可以潛在地學習到知識的依賴以及更長的語義依賴來讓模型更具泛化性。
?
Figure 5: ERNIE 1.0?不同的mask?策略說明
?
?
2.3: ERNIE 2.0 介紹
傳統的pre-training 模型主要基于文本中words ?和 sentences 之間的共現進行學習。?事實上,訓練文本數據中的詞法結構、語法結構、語義信息也同樣是很重要的。在命名實體識別中人名、機構名、組織名等名詞包含概念信息對應了詞法結構,句子之間的順序對應了語法結構,文章中的語義相關性對應了語義信息。為了去發現訓練數據中這些有價值的信息,在ERNIE 2.0 中,提出了一個預訓練框架,可以在大型數據集合中進行增量訓練。
?
Figure 6: ERNIE 2.0?框架
?
2.3.1 ERNIE?2.0?結構
ERNIE 2.0 中有一個很重要的概念便是連續學習(Continual Learning),連續學習的目的是在一個模型中順序訓練多個不同的任務,以便在學習下個任務當中可以記住前一個學習任務學習到的結果。通過使用連續學習,可以不斷積累新的知識,模型在新任務當中可以用歷史任務學習到參數進行初始化,一般來說比直接開始新任務的學習會獲得更好的效果。
?
a:?預訓練連續學習
ERNIE 的預訓練連續學習分為兩步,首先,連續用大量的數據與先驗知識連續構建不同的預訓練任務。其次,不斷的用預訓練任務更新ERNIE 模型。
?
對于第一步,ERNIE 2.0 分別構建了詞法級別,語法級別,語義級別的預訓練任務。所有的這些任務,都是基于無標注或者弱標注的數據。需要注意的是,在連續訓練之前,首先用一個簡單的任務來初始化模型,在后面更新模型的時候,用前一個任務訓練好的參數來作為下一個任務模型初始化的參數。這樣不管什么時候,一個新的任務加進來的時候,都用上一個模型的參數初始化保證了模型不會忘記之前學習到的知識。通過這種方式,在連續學習的過程中,ERNIE 2.0 框架可以不斷更新并記住以前學習到的知識可以使得模型在新任務上獲得更好的表現。我們在下面的e, f, g 中會具體介紹ERNIE 2.0 構建哪些預訓練任務,并且這些預訓練任務起了什么作用。
?
在圖7中,介紹了ERNIE2.0連續學習的架構。這個架構包含了一系列共享文本encoding layers 來 encode 上下文信息。這些encoder layers 的參數可以被所有的預訓練任務更新。有兩種類型的 loss function,一種是sequence level 的loss,?一種是word level的loss。在ERNIE 2.0 預訓練中,一個或多個sentence level的loss function可以和多個token level的loss functions 結合來共同更新模型。
?
Figure 7: ERINE 2.0?連續學習流程
?
b: encoder
ERNIE 2.0 用了我們前文提到的transformer 結構encoder,結構基本一致,但是權重并不共享。
?
c: task embedding.
ERNIE 2.0 用了不同的task id 來標示預訓練任務,task id 從1 到N 對應下面的e, f ,g中提到的預訓練任務。對應的token segment position 以及task embedding 被用來作為模型的輸入。
?
Figure 8: ERNIE 2.0?連續學習詳解
?
?
e:?構建詞法級別的預訓練任務,來獲取訓練數據中的詞法信息
1: knowledge masking task,即 ERNIE 1.0 中的entity mask 以及 phrase entity mask 來獲取phrase 以及entity的先驗知識,相較于 sub-word masking, 該策略可以更好的捕捉輸入樣本局部和全局的語義信息。
?
2: Capitalization Prediction Task,大寫的詞比如Apple相比于其他詞通常在句子當中有特定的含義,所以在ERNIE?2.0 加入一個任務來判斷一個詞是否大寫。
?
3: Token-Document Relation Prediction Task,類似于tf-idf,預測一個詞在文中的A 段落出現,是否會在文中的B 段落出現。如果一個詞在文章當中的許多部分出現一般就說明這個詞經常被用到或者和這個文章的主題相關。通過識別這個文中關鍵的的詞, 這個任務可以增強模型去獲取文章的關鍵詞語的能力。
?
f:?構建語法級別的預訓練任務,來獲取訓練數據中的語法信息
1: ?Sentence Reordering Task,在訓練當中,將paragraph 隨機分成1 到m 段,將所有的組合隨機shuffle。我們讓pre-trained 的模型來識別所有的這些segments正確的順序。這便是一個k 分類任務
?
?
通常來說,這些sentence 重排序任務能夠讓pre-trained 模型學習到document 中不同sentence 的關系。
?
2: Sentence Distance Task,?構建一個三分類任務來判別句子的距離,0表示兩個句子是同一個文章中相鄰的句子,1表示兩個句子是在同一個文章,但是不相鄰,2表示兩個句子是不同的文章。通過構建這樣一個三分類任務去判斷句對 (sentence pairs) 位置關系 (包含鄰近句子、文檔內非鄰近句子、非同文檔內句子 3 種類別),更好的建模語義相關性。
?
g:構建語義級別的預訓練任務,來獲取訓練數據中的語義任務
1: Discourse Relation Task,除了上面的distance task,ERNIE通過判斷句對 (sentence pairs) 間的修辭關系 (semantic & rhetorical relation),更好的學習句間語義。
?
2: IR Relevance Task,在這里主要是利用baidu 的日志來獲取這個關系,將query 作為第一個sentence,title 作為第二個 sentence。0 表示強關系, 1 表示弱關系,2表示無關系,通過類似google-distance 的關系來衡量 兩個query之間的語義相關性,更好的建模句對相關性。
?
三: 代碼梳理
3.1 : 預訓練腳本
?
set?-eux export?FLAGS_eager_delete_tensor_gb=0 export?FLAGS_sync_nccl_allreduce=1 export?CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7 python?./pretrain_launch.py??\??? --nproc_per_node?8?\???? --selected_gpus?0,1,2,3,4,5,6,7?\???? --node_ips?$(hostname?-i)?\???? --node_id?0?\. /train.py??--use_cuda?True?\???????????????? --is_distributed?False\???????????????? --use_fast_executor?True?\???????????????? --weight_sharing?True?\???????????????? --in_tokens?true?\???????????????? --batch_size?8192?\???????????????? --vocab_path?./config/vocab.txt?\??????????????? --train_filelist?./data/train_filelist?\??????????????? --valid_filelist?./data/valid_filelist?\???????????????? --validation_steps?100?\??????????????? --num_train_steps?1000000?\???????????????? --checkpoints?./checkpoints?\??????????????? --save_steps?10000?\???????????????? --ernie_config_path?./config/ernie_config.json?\??????????????? --learning_rate?1e-4?\?????????????? --use_fp16?false?\???????????????? --weight_decay?0.01?\??????????????? --max_seq_len?512?\???????????????? --skip_steps?10
腳本初始化代碼 pretrain_launch.py
from?__future__?import?absolute_import from?__future__?import?division from?__future__?import?print_function from?__future__?import?unicode_literals from?__future__?import?absolute_import from?__future__?import?division import?sys import?subprocess import?os import?six import?copy import?argparse import?time import?logging from?utils.args?import?ArgumentGroup,?print_arguments,?????prepare_logger from?pretrain_args?import?parser?as?worker_parser #?yapf:?disable parser?=?argparse.ArgumentParser(__doc__) multip_g?=?ArgumentGroup(parser,?"multiprocessing", "start?paddle?training?using?multi-processing?mode.") multip_g.add_arg("node_ips",?str,?None, "paddle?trainer?ips") multip_g.add_arg("node_id",?int,?0, "the?trainer?id?of?the?node?for?multi-node?distributed?training.") multip_g.add_arg("print_config",?bool,?True, "print?the?config?of?multi-processing?mode.") multip_g.add_arg("current_node_ip",?str,?None, "the?ip?of?current?node.") multip_g.add_arg("split_log_path",?str,?"./log", "log?path?for?each?trainer.") multip_g.add_arg("log_prefix",?str,?"", "the?prefix?name?of?job?log.") multip_g.add_arg("nproc_per_node",?int,?8, "the?number?of?process?to?use?on?each?node.") multip_g.add_arg("selected_gpus",?str,?"0,1,2,3,4,5,6,7", "the?gpus?selected?to?use.") multip_g.add_arg("training_script",?str,?None,?"the?program/script?to?be?lauched?" "in?parallel?followed?by?all?the?arguments",?????positional_arg=True) multip_g.add_arg("training_script_args",?str,?None, "training?script?args",?positional_arg=True,?nargs=argparse.REMAINDER) #?yapf:?enable log?=?logging.getLogger() def?start_procs(args): procs?=?[] log_fns?=?[] default_env?=?os.environ.copy() node_id?=?args.node_id node_ips?=?[x.strip()?for?x?in?args.node_ips.split(',')] current_ip?=?args.current_node_ip if?args.current_node_ip?is?None: assert?len(node_ips)?==?1 current_ip?=?node_ips[0] log.info(current_ip) num_nodes?=?len(node_ips) selected_gpus?=?[x.strip()?for?x?in?args.selected_gpus.split(',')] selected_gpu_num?=?len(selected_gpus) all_trainer_endpoints?=?"" for?ip?in?node_ips: for?i?in?range(args.nproc_per_node): if?all_trainer_endpoints?!=?"": all_trainer_endpoints?+=?"," all_trainer_endpoints?+=?"%s:617%d"?%?(ip,?i) nranks?=?num_nodes?*?args.nproc_per_node gpus_per_proc?=?args.nproc_per_node?%?selected_gpu_num if?gpus_per_proc?==?0: gpus_per_proc?=??selected_gpu_num? else: gpus_per_proc?=??selected_gpu_num? log.info(gpus_per_proc) selected_gpus_per_proc?=?[selected_gpus[i:i?+?gpus_per_proc]?for?i?in?range(0,?len(selected_gpus),?gpus_per_proc)] if?args.print_config: log.info("all_trainer_endpoints:?%s" ",?node_id:?%s" ",?current_ip:?%s" ",?num_nodes:?%s" ",?node_ips:?%s" ",?gpus_per_proc:?%s" ",?selected_gpus_per_proc:?%s" ",?nranks:?%s"?%?( all_trainer_endpoints, node_id, current_ip, num_nodes, node_ips, gpus_per_proc, selected_gpus_per_proc, nranks)) current_env?=?copy.copy(default_env) procs?=?[] cmds?=?[] log_fns?=?[] for?i?in?range(0,?args.nproc_per_node): trainer_id?=?node_id?*?args.nproc_per_node?+?i current_env.update({ "FLAGS_selected_gpus":?"%s"?%?",".join([str(s)?for?s?in?selected_gpus_per_proc[i]]), "PADDLE_TRAINER_ID"?:?"%d"?%?trainer_id, "PADDLE_CURRENT_ENDPOINT":?"%s:617%d"?%?(current_ip,?i), "PADDLE_TRAINERS_NUM":?"%d"?%?nranks, "PADDLE_TRAINER_ENDPOINTS":?all_trainer_endpoints, "PADDLE_NODES_NUM":?"%d"?%?num_nodes }) try: idx?=?args.training_script_args.index('--is_distributed') args.training_script_args[idx?+?1]?=?'true' except?ValueError: args.training_script_args?+=?['--is_distributed',?'true'] cmd?=?[sys.executable,?"-u", args.training_script]?+?args.training_script_args cmds.append(cmd) if?args.split_log_path: fn?=?open("%s/%sjob.log.%d"?%?(args.split_log_path,?args.log_prefix,?trainer_id),?"a") log_fns.append(fn) process?=?subprocess.Popen(cmd,?env=current_env,?stdout=fn,?stderr=fn) else: process?=?subprocess.Popen(cmd,?env=current_env) log.info('subprocess?launched') procs.append(process) try: for?i?in?range(len(procs)): proc?=?procs[i] proc.wait() if?len(log_fns)?>?0: log_fns[i].close() if?proc.returncode?!=?0:???? raise?subprocess.CalledProcessError(returncode=procs[i].returncode, cmd=cmds[i]) else: log.info("proc?%d?finsh"?%?i) except?KeyboardInterrupt?as?e: for?p?in?procs: log.info('killing?%s'?%?p) p.terminate() def?main(args): if?args.print_config: print_arguments(args) start_procs(args) if?__name__?==?"__main__": prepare_logger(log) lanch_args?=?parser.parse_args() pretraining_args?=?worker_parser.parse_args( lanch_args.training_script_args) init_path?=?pretraining_args.init_checkpoint if?init_path?and?not?pretraining_args.use_fp16: os.system('rename?.master?""?'?+?init_path?+?'/*.master') main(lanch_args)
訓練代碼 train.py
#???Copyright?(c)?2019?PaddlePaddle?Authors.?All?Rights?Reserved. # #?Licensed?under?the?Apache?License,?Version?2.0?(the?"License"); #?you?may?not?use?this?file?except?in?compliance?with?the?License. #?You?may?obtain?a?copy?of?the?License?at # #?????http: # #?Unless?required?by?applicable?law?or?agreed?to?in?writing,?software #?distributed?under?the?License?is?distributed?on?an?"AS?IS"?BASIS, #?WITHOUT?WARRANTIES?OR?CONDITIONS?OF?ANY?KIND,?either?express?or?implied. #?See?the?License?for?the?specific?language?governing?permissions?and #?limitations?under?the?License. """ERNIE?pretraining.""" from?__future__?import?absolute_import from?__future__?import?division from?__future__?import?print_function from?__future__?import?unicode_literals from?__future__?import?absolute_import import?os import?time import?multiprocessing import?logging import?numpy?as?np import?paddle.fluid?as?fluid from?reader.pretraining?import?ErnieDataReader from?model.ernie_v1?import?ErnieModel,?ErnieConfig from?optimization?import?optimization from?utils.args?import?print_arguments,?check_cuda,?prepare_logger from?utils.init?import?init_checkpoint,?init_pretraining_params from?pretrain_args?import?parser log?=?logging.getLogger() args?=?parser.parse_args() #?yapf:?enable. def?create_model(pyreader_name,?ernie_config): pyreader?=?fluid.layers.py_reader( capacity=70, shapes=[[-1,?args.max_seq_len,?1],?[-1,?args.max_seq_len,?1], [-1,?args.max_seq_len,?1],?[-1,?args.max_seq_len,?1],?[-1,?1], [-1,?1],?[-1,?1]], dtypes=[ 'int64',?'int64',?'int64',?'float32',?'int64',?'int64',?'int64' ], lod_levels=[0,?0,?0,?0,?0,?0,?0], name=pyreader_name, use_double_buffer=True) (src_ids,?pos_ids,?sent_ids,?input_mask,?mask_label,?mask_pos, labels)?=?fluid.layers.read_file(pyreader) ernie?=?ErnieModel( src_ids=src_ids, position_ids=pos_ids, sentence_ids=sent_ids, input_mask=input_mask, config=ernie_config, weight_sharing=args.weight_sharing, use_fp16=args.use_fp16) next_sent_acc,?mask_lm_loss,?total_loss?=?ernie.get_pretraining_output( mask_label,?mask_pos,?labels) return?pyreader,?next_sent_acc,?mask_lm_loss,?total_loss def?predict_wrapper(args, exe, ernie_config, test_prog=None, pyreader=None, fetch_list=None): #?Context?to?do?validation. filelist?=?args.test_filelist?if?args.do_test?else?args.valid_filelist data_reader?=?ErnieDataReader( filelist, vocab_path=args.vocab_path, batch_size=args.batch_size, voc_size=ernie_config['vocab_size'], shuffle_files=False, epoch=1, max_seq_len=args.max_seq_len, is_test=True) if?args.do_test: assert?args.init_checkpoint?is?not?None,?"[FATAL]?Please?use?--init_checkpoint?'/path/to/checkpoints'?\???????????????????????????????????????????? ??to?specify?you?pretrained?model?checkpoints" init_pretraining_params(exe,?args.init_checkpoint,?test_prog) def?predict(exe=exe,?pyreader=pyreader): pyreader.decorate_tensor_provider(data_reader.data_generator()) pyreader.start() cost?=?0 lm_cost?=?0 acc?=?0 steps?=?0 time_begin?=?time.time() while?True: try: each_next_acc,?each_mask_lm_cost,?each_total_cost?=?exe.run( fetch_list=fetch_list,?program=test_prog) acc?+=?each_next_acc lm_cost?+=?each_mask_lm_cost cost?+=?each_total_cost steps?+=?1 if?args.do_test?and?steps?%?args.skip_steps?==?0: log.info("[test_set]?steps:?%d"?%?steps) except?fluid.core.EOFException: pyreader.reset() break used_time?=?time.time()?-?time_begin return?cost,?lm_cost,?acc,?steps,?(args.skip_steps?/?used_time) return?predict def?test(args): ernie_config?=?ErnieConfig(args.ernie_config_path) ernie_config.print_config() test_prog?=?fluid.Program() test_startup?=?fluid.Program() with?fluid.program_guard(test_prog,?test_startup): with?fluid.unique_name.guard(): test_pyreader,?next_sent_acc,?mask_lm_loss,?total_loss?=?create_model( pyreader_name='test_reader',?ernie_config=ernie_config) test_prog?=?test_prog.clone(for_test=True) place?=?fluid.CUDAPlace(0)?if?args.use_cuda?==?True?else?fluid.CPUPlace() exe?=?fluid.Executor(place) exe.run(test_startup) predict?=?predict_wrapper( args, exe, ernie_config, test_prog=test_prog, pyreader=test_pyreader, fetch_list=[next_sent_acc.name,?mask_lm_loss.name,?total_loss.name]) log.info("test?begin") loss,?lm_loss,?acc,?steps,?speed?=?predict() log.info( "[test_set]?loss:?%f,?global?ppl:?%f,?next_sent_acc:?%f,?speed:?%f?steps/s" %?(np.mean(np.array(loss)?/?steps), np.exp(np.mean(np.array(lm_loss)?/?steps)), np.mean(np.array(acc)?/?steps),?speed)) def?train(args): log.info("pretraining?start") ernie_config?=?ErnieConfig(args.ernie_config_path) ernie_config.print_config() train_program?=?fluid.Program() startup_prog?=?fluid.Program() with?fluid.program_guard(train_program,?startup_prog): with?fluid.unique_name.guard(): train_pyreader,?next_sent_acc,?mask_lm_loss,?total_loss?=?create_model( pyreader_name='train_reader',?ernie_config=ernie_config) scheduled_lr,?_?=?optimization( loss=total_loss, warmup_steps=args.warmup_steps, num_train_steps=args.num_train_steps, learning_rate=args.learning_rate, train_program=train_program, startup_prog=startup_prog, weight_decay=args.weight_decay, scheduler=args.lr_scheduler, use_fp16=args.use_fp16, use_dynamic_loss_scaling=args.use_dynamic_loss_scaling, init_loss_scaling=args.init_loss_scaling, incr_every_n_steps=args.incr_every_n_steps, decr_every_n_nan_or_inf=args.decr_every_n_nan_or_inf, incr_ratio=args.incr_ratio, decr_ratio=args.decr_ratio) test_prog?=?fluid.Program() with?fluid.program_guard(test_prog,?startup_prog): with?fluid.unique_name.guard(): test_pyreader,?next_sent_acc,?mask_lm_loss,?total_loss?=?create_model( pyreader_name='test_reader',?ernie_config=ernie_config) test_prog?=?test_prog.clone(for_test=True) if?len(fluid.cuda_places())?==?0: raise?RuntimeError('not?cuda?device?cound,?check?ur?env?setting') if?args.use_cuda: place?=?fluid.cuda_places()[0] dev_count?=?fluid.core.get_cuda_device_count() else: place?=?fluid.CPUPlace() dev_count?=?int(os.environ.get('CPU_NUM',?multiprocessing.cpu_count())) log.info("Device?count?%d"?%?dev_count) log.info("theoretical?memory?usage:?") log.info(fluid.contrib.memory_usage( program=train_program,?batch_size=args.batch_size? nccl2_num_trainers?=?1 nccl2_trainer_id?=?0 log.info("args.is_distributed:?%s"?%?args.is_distributed) if?args.is_distributed: worker_endpoints_env?=?os.getenv("PADDLE_TRAINER_ENDPOINTS") worker_endpoints?=?worker_endpoints_env.split(",") trainers_num?=?len(worker_endpoints) current_endpoint?=?os.getenv("PADDLE_CURRENT_ENDPOINT") trainer_id?=?worker_endpoints.index(current_endpoint) if?trainer_id?==?0: log.info("train_id?==?0,?sleep?60s") time.sleep(60) log.info("worker_endpoints:{}?trainers_num:{}?current_endpoint:{}?\???????? ??trainer_id:{}".format(worker_endpoints,?trainers_num, current_endpoint,?trainer_id)) #?prepare?nccl2?env. config?=?fluid.DistributeTranspilerConfig() config.mode?=?"nccl2" t?=?fluid.DistributeTranspiler(config=config) t.transpile( trainer_id, trainers=worker_endpoints_env, current_endpoint=current_endpoint, program=train_program, startup_program=startup_prog) nccl2_num_trainers?=?trainers_num nccl2_trainer_id?=?trainer_id exe?=?fluid.Executor(place) exe.run(startup_prog) if?args.init_checkpoint?and?args.init_checkpoint?!=?"": init_checkpoint(exe,?args.init_checkpoint,?train_program,?args.use_fp16) data_reader?=?ErnieDataReader( filelist=args.train_filelist, batch_size=args.batch_size, vocab_path=args.vocab_path, voc_size=ernie_config['vocab_size'], epoch=args.epoch, max_seq_len=args.max_seq_len, generate_neg_sample=args.generate_neg_sample) exec_strategy?=?fluid.ExecutionStrategy() if?args.use_fast_executor: exec_strategy.use_experimental_executor?=?True exec_strategy.num_threads?=?dev_count exec_strategy.num_iteration_per_drop_scope?=?min(10,?args.skip_steps) build_strategy?=?fluid.BuildStrategy() build_strategy.remove_unnecessary_lock?=?False train_exe?=?fluid.ParallelExecutor( use_cuda=args.use_cuda, loss_name=total_loss.name, build_strategy=build_strategy, exec_strategy=exec_strategy, main_program=train_program, num_trainers=nccl2_num_trainers, trainer_id=nccl2_trainer_id) if?args.valid_filelist?and?args.valid_filelist?!=?"": predict?=?predict_wrapper( args, exe, ernie_config, test_prog=test_prog, pyreader=test_pyreader, fetch_list=[ next_sent_acc.name,?mask_lm_loss.name,?total_loss.name ]) train_pyreader.decorate_tensor_provider(data_reader.data_generator()) train_pyreader.start() steps?=?0 cost?=?[] lm_cost?=?[] acc?=?[] time_begin?=?time.time() while?steps?<?args.num_train_steps: try: steps?+=?nccl2_num_trainers skip_steps?=?args.skip_steps?*?nccl2_num_trainers if?nccl2_trainer_id?!=?0: train_exe.run(fetch_list=[]) continue if?steps?%?skip_steps?!=?0: train_exe.run(fetch_list=[]) else: each_next_acc,?each_mask_lm_cost,?each_total_cost,?np_lr?=?train_exe.run( fetch_list=[ next_sent_acc.name,?mask_lm_loss.name,?total_loss.name, scheduled_lr.name ]) acc.extend(each_next_acc) lm_cost.extend(each_mask_lm_cost) cost.extend(each_total_cost) log.info("feed_queue?size?%d"?%?train_pyreader.queue.size()) time_end?=?time.time() used_time?=?time_end?-?time_begin epoch,?current_file_index,?total_file,?current_file,?mask_type?=?data_reader.get_progress( ) log.info("current?learning_rate:%f"?%?np_lr[0]) log.info( "epoch:?%d,?progress:?%d/%d,?step:?%d,?loss:?%f,?" "ppl:?%f,?next_sent_acc:?%f,?speed:?%f?steps/s,?file:?%s,?mask_type:?%s" %?(epoch,?current_file_index,?total_file,?steps, np.mean(np.array(cost)), np.mean(np.exp(np.array(lm_cost))), np.mean(np.array(acc)),?skip_steps?/?used_time, current_file,?mask_type)) cost?=?[] lm_cost?=?[] acc?=?[] time_begin?=?time.time() if?steps?%?args.save_steps?==?0: save_path?=?os.path.join(args.checkpoints,?"step_"?+?str(steps)) fluid.io.save_persistables(exe,?save_path,?train_program) if?args.valid_filelist?and?steps?%?args.validation_steps?==?0: vali_cost,?vali_lm_cost,?vali_acc,?vali_steps,?vali_speed?=?predict( ) log.info("[validation_set]?epoch:?%d,?step:?%d,?" "loss:?%f,?global?ppl:?%f,?batch-averged?ppl:?%f,?" "next_sent_acc:?%f,?speed:?%f?steps/s"?% (epoch,?steps,?np.mean(np.array(vali_cost)?/?vali_steps), np.exp(np.mean(np.array(vali_lm_cost)?/?vali_steps)), np.mean(np.exp(np.array(vali_lm_cost)?/?vali_steps)), np.mean(np.array(vali_acc)?/?vali_steps),?vali_speed)) except?fluid.core.EOFException: train_pyreader.reset() break if?__name__?==?'__main__': prepare_logger(log) print_arguments(args)
總結
以上是生活随笔為你收集整理的一文读懂最强中文NLP预训练模型ERNIE的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。