日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一文读懂最强中文NLP预训练模型ERNIE

發(fā)布時(shí)間:2024/7/5 编程问答 92 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一文读懂最强中文NLP预训练模型ERNIE 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基于飛槳開源的持續(xù)學(xué)習(xí)的語義理解框架ERNIE 2.0,及基于此框架的ERNIE 2.0預(yù)訓(xùn)練模型,在共計(jì)16個(gè)中英文任務(wù)上超越了BERT和XLNet, 取得了SOTA效果。本文帶你進(jìn)一步深入了解ERNIE的技術(shù)細(xì)節(jié)。

一:ERNIE 簡介

1.1 簡介

Google 最近提出的 BERT 模型,通過隨機(jī)屏蔽15%的字或者word,利用 Transformer 的多層 self-attention 雙向建模能力,在各項(xiàng)nlp 下游任務(wù)中(如 sentence pair classification task,singe sentence classification task,question answering task) 都取得了很好的成績。但是,BERT 模型主要是聚焦在針對字或者英文word粒度的完形填空學(xué)習(xí)上面,沒有充分利用訓(xùn)練數(shù)據(jù)當(dāng)中詞法結(jié)構(gòu),語法結(jié)構(gòu),以及語義信息去學(xué)習(xí)建模。比如?“我要買蘋果手機(jī)”,BERT 模型?將?“我”,“要”,?“買”,“蘋”,?“果”,“手”,?“機(jī)”?每個(gè)字都統(tǒng)一對待,隨機(jī)mask,丟失了“蘋果手機(jī)” 是一個(gè)很火的名詞這一信息,這個(gè)是詞法信息的缺失。同時(shí) 我 + 買 + 名詞 是一個(gè)非常明顯的購物意圖的句式,BERT 沒有對此類語法結(jié)構(gòu)進(jìn)行專門的建模,如果預(yù)訓(xùn)練的語料中只有“我要買蘋果手機(jī)”,“我要買華為手機(jī)”,哪一天出現(xiàn)了一個(gè)新的手機(jī)牌子比如栗子手機(jī),而這個(gè)手機(jī)牌子在預(yù)訓(xùn)練的語料當(dāng)中并不存在,沒有基于詞法結(jié)構(gòu)以及句法結(jié)構(gòu)的建模,對于這種新出來的詞是很難給出一個(gè)很好的向量表示的,而ERNIE 通過對訓(xùn)練數(shù)據(jù)中的詞法結(jié)構(gòu),語法結(jié)構(gòu),語義信息進(jìn)行統(tǒng)一建模,極大地增強(qiáng)了通用語義表示能力,在多項(xiàng)任務(wù)中均取得了大幅度超越BERT的效果!!

?

1.2 下載地址(這么好用的模型趕緊下載起來吧!)

ERNIE 的Fine-tuning代碼和英文預(yù)訓(xùn)練模型已通過飛槳開源

?

Github 地址:

https://github.com/PaddlePaddle/ERNIE

?

二:ERNIE 詳解

2.1 ERNIE 結(jié)構(gòu)

2.1.1 ERNIE?初探

?

?

2.1.1 ERNIE?結(jié)構(gòu)詳解

?

Figure 2:ERNIE?的encoder?結(jié)構(gòu)詳解?

?

相比transformer,ERNIE?基本上是 transformer 的encoder 部分,并且encoder 在結(jié)構(gòu)上是全部一樣的,但是并不共享權(quán)重,具體區(qū)別如下:

  • 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

?

從輸入上來看第一個(gè)輸入是一個(gè)特殊的CLS, CLS 表示分類任務(wù)就像 transformer 的一般的encoder, ERINE 將一序列的words 輸入到encoder 中。?每層使用self-attention, feed-word network, 然后把結(jié)果傳入到下一個(gè)encoder。

?

2.1.2 ERNIE encoder?說明

encoder

encoder 由兩層構(gòu)成, 首先流入self-attention layer,self-attention layer 輸出流入 feed-forward 神經(jīng)網(wǎng)絡(luò)。至于self-attention的結(jié)構(gòu),我們在這里不再展開,有興趣的同學(xué)可以進(jìn)入以下鏈接仔細(xì)閱讀http://jalammar.github.io/illustrated-transformer/,來進(jìn)一步了解self-attention的結(jié)構(gòu)!!

?

Figure 3: encoder?結(jié)構(gòu)詳解

?

embedding

最下層的encoder的輸入是embedding的向量, 其他的encoder的輸入,便是更下層的encoder的輸出,?一般設(shè)置輸入的vectors 的維度為512,同學(xué)們也可以自己設(shè)置。

?

Figure 4: encoder?結(jié)構(gòu)詳解

?

2.2 : ERNIE 1.0 介紹

相比于BERT, ERNIE 1.0 改進(jìn)了兩種 masking 策略,一種是基于phrase (在這里是短語 比如 a series of, written等)的masking策略,另外一種是基于 entity(在這里是人名、位置、組織、產(chǎn)品等名詞,比如Apple, J.K. Rowling)的masking 策略。在ERNIE 當(dāng)中,將由多個(gè)字組成的phrase 或者entity 當(dāng)成一個(gè)統(tǒng)一單元,相比于bert 基于字的mask,這個(gè)單元當(dāng)中的所有字在訓(xùn)練的時(shí)候,統(tǒng)一被mask。對比直接將知識類的query 映射成向量然后直接加起來,ERNIE 通過統(tǒng)一mask的方式可以潛在地學(xué)習(xí)到知識的依賴以及更長的語義依賴來讓模型更具泛化性。

?

Figure 5: ERNIE 1.0?不同的mask?策略說明

?

?

2.3: ERNIE 2.0 介紹

傳統(tǒng)的pre-training 模型主要基于文本中words ?和 sentences 之間的共現(xiàn)進(jìn)行學(xué)習(xí)。?事實(shí)上,訓(xùn)練文本數(shù)據(jù)中的詞法結(jié)構(gòu)、語法結(jié)構(gòu)、語義信息也同樣是很重要的。在命名實(shí)體識別中人名、機(jī)構(gòu)名、組織名等名詞包含概念信息對應(yīng)了詞法結(jié)構(gòu),句子之間的順序?qū)?yīng)了語法結(jié)構(gòu),文章中的語義相關(guān)性對應(yīng)了語義信息。為了去發(fā)現(xiàn)訓(xùn)練數(shù)據(jù)中這些有價(jià)值的信息,在ERNIE 2.0 中,提出了一個(gè)預(yù)訓(xùn)練框架,可以在大型數(shù)據(jù)集合中進(jìn)行增量訓(xùn)練。

?

Figure 6: ERNIE 2.0?框架

?

2.3.1 ERNIE?2.0?結(jié)構(gòu)

ERNIE 2.0 中有一個(gè)很重要的概念便是連續(xù)學(xué)習(xí)(Continual Learning),連續(xù)學(xué)習(xí)的目的是在一個(gè)模型中順序訓(xùn)練多個(gè)不同的任務(wù),以便在學(xué)習(xí)下個(gè)任務(wù)當(dāng)中可以記住前一個(gè)學(xué)習(xí)任務(wù)學(xué)習(xí)到的結(jié)果。通過使用連續(xù)學(xué)習(xí),可以不斷積累新的知識,模型在新任務(wù)當(dāng)中可以用歷史任務(wù)學(xué)習(xí)到參數(shù)進(jìn)行初始化,一般來說比直接開始新任務(wù)的學(xué)習(xí)會(huì)獲得更好的效果。

?

a:?預(yù)訓(xùn)練連續(xù)學(xué)習(xí)

ERNIE 的預(yù)訓(xùn)練連續(xù)學(xué)習(xí)分為兩步,首先,連續(xù)用大量的數(shù)據(jù)與先驗(yàn)知識連續(xù)構(gòu)建不同的預(yù)訓(xùn)練任務(wù)。其次,不斷的用預(yù)訓(xùn)練任務(wù)更新ERNIE 模型。

?

對于第一步,ERNIE 2.0 分別構(gòu)建了詞法級別,語法級別,語義級別的預(yù)訓(xùn)練任務(wù)。所有的這些任務(wù),都是基于無標(biāo)注或者弱標(biāo)注的數(shù)據(jù)。需要注意的是,在連續(xù)訓(xùn)練之前,首先用一個(gè)簡單的任務(wù)來初始化模型,在后面更新模型的時(shí)候,用前一個(gè)任務(wù)訓(xùn)練好的參數(shù)來作為下一個(gè)任務(wù)模型初始化的參數(shù)。這樣不管什么時(shí)候,一個(gè)新的任務(wù)加進(jìn)來的時(shí)候,都用上一個(gè)模型的參數(shù)初始化保證了模型不會(huì)忘記之前學(xué)習(xí)到的知識。通過這種方式,在連續(xù)學(xué)習(xí)的過程中,ERNIE 2.0 框架可以不斷更新并記住以前學(xué)習(xí)到的知識可以使得模型在新任務(wù)上獲得更好的表現(xiàn)。我們在下面的e, f, g 中會(huì)具體介紹ERNIE 2.0 構(gòu)建哪些預(yù)訓(xùn)練任務(wù),并且這些預(yù)訓(xùn)練任務(wù)起了什么作用。

?

在圖7中,介紹了ERNIE2.0連續(xù)學(xué)習(xí)的架構(gòu)。這個(gè)架構(gòu)包含了一系列共享文本encoding layers 來 encode 上下文信息。這些encoder layers 的參數(shù)可以被所有的預(yù)訓(xùn)練任務(wù)更新。有兩種類型的 loss function,一種是sequence level 的loss,?一種是word level的loss。在ERNIE 2.0 預(yù)訓(xùn)練中,一個(gè)或多個(gè)sentence level的loss function可以和多個(gè)token level的loss functions 結(jié)合來共同更新模型。

?

Figure 7: ERINE 2.0?連續(xù)學(xué)習(xí)流程

?

b: encoder

ERNIE 2.0 用了我們前文提到的transformer 結(jié)構(gòu)encoder,結(jié)構(gòu)基本一致,但是權(quán)重并不共享。

?

c: task embedding.

ERNIE 2.0 用了不同的task id 來標(biāo)示預(yù)訓(xùn)練任務(wù),task id 從1 到N 對應(yīng)下面的e, f ,g中提到的預(yù)訓(xùn)練任務(wù)。對應(yīng)的token segment position 以及task embedding 被用來作為模型的輸入。

?

Figure 8: ERNIE 2.0?連續(xù)學(xué)習(xí)詳解

?

?

e:?構(gòu)建詞法級別的預(yù)訓(xùn)練任務(wù),來獲取訓(xùn)練數(shù)據(jù)中的詞法信息

1: knowledge masking task,即 ERNIE 1.0 中的entity mask 以及 phrase entity mask 來獲取phrase 以及entity的先驗(yàn)知識,相較于 sub-word masking, 該策略可以更好的捕捉輸入樣本局部和全局的語義信息。

?

2: Capitalization Prediction Task,大寫的詞比如Apple相比于其他詞通常在句子當(dāng)中有特定的含義,所以在ERNIE?2.0 加入一個(gè)任務(wù)來判斷一個(gè)詞是否大寫。

?

3: Token-Document Relation Prediction Task,類似于tf-idf,預(yù)測一個(gè)詞在文中的A 段落出現(xiàn),是否會(huì)在文中的B 段落出現(xiàn)。如果一個(gè)詞在文章當(dāng)中的許多部分出現(xiàn)一般就說明這個(gè)詞經(jīng)常被用到或者和這個(gè)文章的主題相關(guān)。通過識別這個(gè)文中關(guān)鍵的的詞, 這個(gè)任務(wù)可以增強(qiáng)模型去獲取文章的關(guān)鍵詞語的能力。

?

f:?構(gòu)建語法級別的預(yù)訓(xùn)練任務(wù),來獲取訓(xùn)練數(shù)據(jù)中的語法信息

1: ?Sentence Reordering Task,在訓(xùn)練當(dāng)中,將paragraph 隨機(jī)分成1 到m 段,將所有的組合隨機(jī)shuffle。我們讓pre-trained 的模型來識別所有的這些segments正確的順序。這便是一個(gè)k 分類任務(wù)

?

?

通常來說,這些sentence 重排序任務(wù)能夠讓pre-trained 模型學(xué)習(xí)到document 中不同sentence 的關(guān)系。

?

2: Sentence Distance Task,?構(gòu)建一個(gè)三分類任務(wù)來判別句子的距離,0表示兩個(gè)句子是同一個(gè)文章中相鄰的句子,1表示兩個(gè)句子是在同一個(gè)文章,但是不相鄰,2表示兩個(gè)句子是不同的文章。通過構(gòu)建這樣一個(gè)三分類任務(wù)去判斷句對 (sentence pairs) 位置關(guān)系 (包含鄰近句子、文檔內(nèi)非鄰近句子、非同文檔內(nèi)句子 3 種類別),更好的建模語義相關(guān)性。

?

g:構(gòu)建語義級別的預(yù)訓(xùn)練任務(wù),來獲取訓(xùn)練數(shù)據(jù)中的語義任務(wù)

1: Discourse Relation Task,除了上面的distance task,ERNIE通過判斷句對 (sentence pairs) 間的修辭關(guān)系 (semantic & rhetorical relation),更好的學(xué)習(xí)句間語義。

?

2: IR Relevance Task,在這里主要是利用baidu 的日志來獲取這個(gè)關(guān)系,將query 作為第一個(gè)sentence,title 作為第二個(gè) sentence。0 表示強(qiáng)關(guān)系, 1 表示弱關(guān)系,2表示無關(guān)系,通過類似google-distance 的關(guān)系來衡量 兩個(gè)query之間的語義相關(guān)性,更好的建模句對相關(guān)性。

?

三: 代碼梳理

3.1 : 預(yù)訓(xùn)練腳本

?

  • 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?//?args.nproc_per_node
  • else:
  • gpus_per_proc?=??selected_gpu_num?//?args.nproc_per_node?+?1
  • 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)
  • 訓(xùn)練代碼 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://www.apache.org/licenses/LICENSE-2.0
  • #
  • #?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?//?args.max_seq_len))
  • 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)
  • 總結(jié)

    以上是生活随笔為你收集整理的一文读懂最强中文NLP预训练模型ERNIE的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。