*****新的3月11日,2020年:較小的Bert模型*****
這是24個較小的BERT模型(僅英語,未固定,接受文字掩蓋訓練)的發行版,在閱讀良好的學生中提到了更好的學習:關於預訓練的緊湊型模型的重要性。
我們已經表明,標準的BERT配方(包括模型架構和訓練目標)在廣泛的模型大小上是有效的,除了Bert-Base和Bert-large之外。較小的BERT模型旨在用於具有限制計算資源的環境。它們可以以與原始BERT模型相同的方式進行微調。但是,它們在知識蒸餾的背景下最有效,在知識蒸餾的背景下,微調標籤是由更大,更準確的老師生產的。
我們的目標是在具有更少的計算資源的機構中進行研究,並鼓勵社區尋求創新替代方向以提高模型能力。
您可以從這裡下載全部24個,也可以從下表中單獨下載:
H = 128 | H = 256 | H = 512 | H = 768 | |
---|---|---|---|---|
L = 2 | 2/128(Bert-微小) | 2/256 | 2/512 | 2/768 |
L = 4 | 4/128 | 4/256(Bert-Mini) | 4/512(Bert-Small) | 4/768 |
L = 6 | 6/128 | 6/256 | 6/512 | 6/768 |
L = 8 | 8/128 | 8/256 | 8/512(Bert-Medium) | 8/768 |
L = 10 | 10/128 | 10/256 | 10/512 | 10/768 |
L = 12 | 12/128 | 12/256 | 12/512 | 12/768(Bert-base) |
請注意,此版本中的BERT基本模型僅用於完整性;它在與原始模型相同的方向下進行了重新訓練。
這是測試集上的相應膠水分數:
模型 | 分數 | 可樂 | SST-2 | MRPC | STS-B | QQP | mnli-m | mnli-mm | QNLI(v2) | rte | wnli | 斧頭 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
伯特小 | 64.2 | 0.0 | 83.2 | 81.1/71.1 | 74.3/73.6 | 62.2/83.4 | 70.2 | 70.3 | 81.5 | 57.2 | 62.3 | 21.0 |
伯特·米尼(Bert-Mini) | 65.8 | 0.0 | 85.9 | 81.1/71.8 | 75.4/73.3 | 66.4/86.2 | 74.8 | 74.3 | 84.1 | 57.9 | 62.3 | 26.1 |
伯特·薩爾 | 71.2 | 27.8 | 89.7 | 83.4/76.2 | 78.8/77.0 | 68.1/87.0 | 77.6 | 77.0 | 86.4 | 61.8 | 62.3 | 28.6 |
伯特中等 | 73.5 | 38.0 | 89.6 | 86.6/81.6 | 80.4/78.4 | 69.6/87.9 | 80.0 | 79.1 | 87.7 | 62.2 | 62.3 | 30.5 |
對於每個任務,我們從下面的列表中選擇了最佳的微調超參數,並接受了4個時代的培訓:
如果您使用這些模型,請引用以下論文:
@article{turc2019,
title={Well-Read Students Learn Better: On the Importance of Pre-training Compact Models},
author={Turc, Iulia and Chang, Ming-Wei and Lee, Kenton and Toutanova, Kristina},
journal={arXiv preprint arXiv:1908.08962v2 },
year={2019}
}
*****新的2019年5月31日:整個單詞蒙版模型*****
這是幾種新模型的版本,這是改進預處理代碼的結果。
在原始的預處理代碼中,我們隨機選擇文字代幣將其掩蓋。例如:
Input Text: the man jumped up , put his basket on phil ##am ##mon ' s head
Original Masked Input: [MASK] man [MASK] up , put his [MASK] on phil [MASK] ##mon ' s head
新技術稱為整個單詞掩蔽。在這種情況下,我們總是掩蓋與單詞相對應的所有令牌。總體掩蔽率保持不變。
Whole Word Masked Input: the man [MASK] up , put his basket on [MASK] [MASK] [MASK] ' s head
培訓是相同的 - 我們仍然可以獨立預測每個蒙版的文章令牌令牌。改進來自以下事實:原始預測任務對於已經分為多個文字的單詞太“容易”。
可以通過傳遞標誌--do_whole_word_mask=True
to create_pretraining_data.py
在數據生成過程中啟用這一點。
帶有整個單詞掩蔽的預訓練模型在下面鏈接。數據和培訓是相同的,模型與原始模型具有相同的結構和詞彙。我們僅包括Bert-large模型。使用這些模型時,請在論文中清楚地表明您使用的是Bert-Large的整個單詞掩蓋變體。
BERT-Large, Uncased (Whole Word Masking)
:24層,1024個隱藏,16個頭,340m參數
BERT-Large, Cased (Whole Word Masking)
:24層,1024隱藏,16頭,340m參數
模型 | 小隊1.1 F1/EM | 多NLI準確性 |
---|---|---|
Bert-large,未露面(原始) | 91.0/84.3 | 86.05 |
Bert-large,未露面(整個單詞掩蓋) | 92.8/86.7 | 87.07 |
Bert-large,Cased(原始) | 91.5/84.8 | 86.09 |
Bert-large,Cased(整個單詞掩蔽) | 92.9/86.7 | 86.46 |
*****新的2019年2月7日:TFHUB模塊*****
Bert已上傳到TensorFlow Hub。有關如何使用TF集線器模塊的示例,請參見run_classifier_with_tfhub.py
。或在COLAB上的瀏覽器中運行示例。
*****新的2018年11月23日:非正態化的多語言模型 +泰語 +蒙古人*****
我們上傳了一個新的多語言模型,該模型在輸入上不執行任何歸一化(沒有較低的套管,口音剝離或Unicode歸一化),還包括泰語和蒙古人。
建議使用此版本來開發多語言模型,尤其是在具有非拉丁字母的語言上。
這不需要任何代碼更改,可以在此處下載:
BERT-Base, Multilingual Cased
:104種語言,12層,768隱藏,12個頭,110m參數*****新的2018年11月15日:Sota Squad 2.0系統*****
我們發布了代碼更改,以重現我們的83%F1 Squad 2.0系統,該系統目前在排行榜上排名3%。有關詳細信息,請參見README的小隊2.0部分。
*****新的2018年11月5日:Bert的第三方Pytorch和Chainer版本*****
Huggingface的NLP研究人員為BERT提供了Pytorch版本,該版本與我們的預訓練檢查點兼容,並能夠重現我們的結果。 Sosuke Kobayashi還製作了Bert的連鎖版本(謝謝!),我們沒有參與Pytorch實施的創建或維護,因此請將任何問題指向該存儲庫的作者。
*****新的2018年11月3日:多語言和中文模型*****
我們已經製造了兩個新的BERT模型:
BERT-Base, Multilingual
(不建議使用Multilingual Cased
) :102種語言,12層,768隱藏,12個頭,110m參數BERT-Base, Chinese
:中文簡化和傳統,12層,768隱藏,12個頭,1.10億參數我們為中文使用基於字符的令牌化,以及所有其他語言的文字詞組化。這兩種模型均應在沒有任何代碼更改的情況下開箱即用。我們確實更新了在tokenization.py
中的BasicTokenizer
的實現,以支持中文令牌化,因此,如果您分叉,請更新。但是,我們沒有更改令牌化API。
有關更多信息,請參閱多語言讀數。
*****結束新信息*****
BERT或t Ransformers的bert e Ncoder resentations是一種新的訓練語言表示的方法,可以在各種自然語言處理(NLP)任務中獲得最新的結果。
我們的學術論文詳細描述了BERT,並可以在此處找到許多任務的完整結果:https://arxiv.org/abs/1810.04805。
要提供幾個數字,以下是小隊v1.1問題回答任務的結果:
小隊V1.1排行榜(2018年10月8日) | 測試EM | 測試F1 |
---|---|---|
第一名合奏 - 伯特 | 87.4 | 93.2 |
第二名合奏-NLNET | 86.0 | 91.7 |
第一名單模型 - 伯特 | 85.1 | 91.8 |
第二名單模型-NLNET | 83.5 | 90.1 |
以及幾個自然語言推理任務:
系統 | Multinli | 問題NLI | 贓物 |
---|---|---|---|
伯特 | 86.7 | 91.1 | 86.3 |
Openai GPT(sota Press) | 82.2 | 88.1 | 75.0 |
加上許多其他任務。
此外,這些結果幾乎沒有特定於任務的神經網絡體系結構設計獲得。
如果您已經知道Bert是什麼,並且只想開始,則可以下載預訓練的型號,並在幾分鐘內進行最新的微調。
伯特是一種預訓練語言表示的方法,這意味著我們可以在大型文本語料庫(如Wikipedia)上訓練通用的“語言理解”模型,然後將該模型用於我們關心的下游NLP任務(例如問題)回答)。伯特(Bert)的表現要優於先前的方法,因為它是第一個無監督的,深層的雙向系統,用於訓練NLP。
無監督意味著BERT僅使用純文本語料庫進行培訓,這很重要,因為在網絡上以多種語言在網絡上公開獲得大量的純文本數據。
預訓練的表示也可以是無上下文的或上下文的,上下文表示可以進一步是單向或雙向。諸如Word2Vec或Glove之類的無上下文模型為詞彙中的每個單詞產生一個單一的“詞嵌入”表示形式,因此bank
在bank deposit
和river bank
中的代表性相同。上下文模型相反,會生成基於句子中其他單詞的每個單詞的表示。
伯特(Bert)建立在訓練前上下文表示的最新工作基礎上,包括半監督序列學習,生成的預訓練,Elmo和Ulmfit - 但至關重要的是,這些模型都是單向或淺薄的雙向。這意味著每個單詞僅使用其左側(或右)的單詞進行上下文化。例如,在句子中I made a bank deposit
的單向表示bank
表示僅基於I made a
但沒有deposit
。以前的某些工作確實結合了單獨的左轉文字和右文本模型的表示形式,但僅以“淺”方式。 Bert使用其左和右下文代表“銀行” - I made a ... deposit
- 從深度神經網絡的底部開始,因此它是深度的雙向。
伯特使用一種簡單的方法:我們掩蓋了輸入中的15%單詞,通過深層雙向變壓器編碼運行整個序列,然後僅預測掩蓋的單詞。例如:
Input: the man went to the [MASK1] . he bought a [MASK2] of milk.
Labels: [MASK1] = store; [MASK2] = gallon
為了學習句子之間的關係,我們還訓練可以從任何單語語料庫生成的簡單任務:給定兩個A
A
和B
是B
?
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層變壓器)長時間(1m更新步驟),這就是Bert。
使用BERT有兩個階段:預訓練和微調。
預訓練相當昂貴(在4至16個雲TPU上進行四天),但是每種語言的一次性程序(當前模型僅英語,但多語言模型將在不久的將來發布)。我們正在從Google預先培訓的論文中釋放許多預先培訓的模型。大多數NLP研究人員無需從頭開始預先培訓自己的模型。
微調便宜。從單個雲TPU或GPU上幾個小時,本文中的所有結果最多可以在完全相同的預訓練模型上複製。例如,可以在大約30分鐘內對單個雲TPU進行訓練,以達到91.0%的開發F1分數,這是單個系統的最新系統。
BERT的另一個重要方面是,它可以非常輕鬆地適應許多類型的NLP任務。在本文中,我們在句子級別(例如,SST-2),句子級級別(例如,Multinli),Word級(例如,NER)和Span-Level上演示了最新的結果(例如,小隊)幾乎沒有特定任務修改的任務。
我們發布以下內容:
BERT-Base
和BERT-Large
的小寫和外殼版本的預訓練檢查點。該存儲庫中的所有代碼都使用CPU,GPU和Cloud TPU播放。
我們正在從論文中釋放BERT-Base
和BERT-Large
模型。 Uncased
意味著文字在文字詞造型之前已經被降低了,例如, John Smith
成為john smith
。 Uncased
模型還剝離了任何重音標記。 Cased
意味著保留真實的情況和重音標記。通常,除非您知道該案例信息對於您的任務很重要(例如,命名實體識別或詞性詞性標記), Uncased
會更好。
這些模型均與源代碼相同的許可(Apache 2.0)發布。
有關多語言和中文模型的信息,請參見多語言讀數。
使用殼體模型時,請確保通過--do_lower=False
to to training腳本。 (或通過使用自己的腳本,將do_lower_case=False
直接傳遞到FullTokenizer
。)
指向模型的鏈接在此處(右鍵單擊,在名稱上保存鏈接為...”):
BERT-Large, Uncased (Whole Word Masking)
:24層,1024個隱藏,16個頭,340m參數BERT-Large, Cased (Whole Word Masking)
:24層,1024隱藏,16頭,340m參數BERT-Base, Uncased
:12層,768隱藏,12個頭,110m參數BERT-Large, Uncased
:24層,1024個隱藏,16頭,340m參數BERT-Base, Cased
:12層,768 HIDDER,12頭,110m參數BERT-Large, Cased
:24層,1024隱藏,16頭,340m參數BERT-Base, Multilingual Cased (New, recommended)
:104種語言,12層,768隱藏,12個頭,110m參數BERT-Base, Multilingual Uncased (Orig, not recommended)
(不建議使用,使用Multilingual Cased
) :102種語言,12層,768隱藏,12個頭,120m的參數BERT-Base, Chinese
:中文簡化和傳統,12層,768隱藏,12個頭,1.10億參數每個.zip文件包含三個項目:
bert_model.ckpt
),其中包含預先訓練的權重(實際上是3個文件)。vocab.txt
)將文字映射到單詞ID。bert_config.json
)指定模型的超參數。 重要的是:紙上的所有結果均在單個雲TPU上進行了微調,該雲TPU具有64GB的RAM。目前無法使用具有12GB-16GB RAM的GPU在紙上重新生產大多數BERT-Large
結果,因為可以適合內存的最大批量大小太小。我們正在為此存儲庫添加代碼,該存儲庫允許在GPU上更大的有效批量尺寸。有關更多詳細信息,請參見有關默認問題的部分。
使用TensorFlow 1.11.0測試了此代碼。它通過Python2和Python3進行了測試(但更徹底地用Python2進行了測試,因為這是Google內部使用的內容)。
使用BERT-Base
微調示例應該能夠在具有至少12GB RAM的GPU上運行,使用給定的超參數。
下面的大多數示例都假定您將使用像Titan X或GTX 1080這樣的GPU在本地機器上進行培訓/評估。
但是,如果您可以訪問要訓練的雲TPU,只需將以下標誌添加到run_classifier.py
或run_squad.py
:
--use_tpu=True
--tpu_name=$TPU_NAME
請參閱Google Cloud TPU教程,以了解如何使用Cloud TPU。另外,您可以使用Google Colab筆記本“與Cloud TPU的Bert Finetuning”。
在Cloud TPU上,驗證的模型和輸出目錄將需要在Google Cloud Storage上。例如,如果您有一個名為some_bucket
的存儲桶,則可以使用以下標誌:
--output_dir=gs://some_bucket/my_output_dir/
也可以在Google Cloud Storage文件夾gs://bert_models/2018_10_18
中找到未拉鍊的預訓練模型文件。例如:
export BERT_BASE_DIR=gs://bert_models/2018_10_18/uncased_L-12_H-768_A-12
在運行此示例之前,您必須通過運行此腳本並將其解放到某些目錄$GLUE_DIR
之前下載膠水數據。接下來,下載BERT-Base
檢查點,然後將其解壓縮到某些目錄$BERT_BASE_DIR
。
此示例代碼在Microsoft Research釋義語料庫(MRPC)語料庫上進行微調BERT-Base
,該語料庫僅包含3,600個示例,並且在大多數GPU中可以在幾分鐘內進行微調。
export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export GLUE_DIR=/path/to/glue
python 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.845588
eval_loss = 0.505248
global_step = 343
loss = 0.505248
這意味著開發設置的精度為84.55%。即使從相同的預訓練檢查點開始時,諸如MRPC之類的小集合在開發設置的精度上也具有很大的差異。如果您多次重新運行(確保指向不同的output_dir
),則應看到結果在84%至88%之間。
在run_classifier.py
中實現了其他一些預訓練的模型,因此,遵循這些示例以將BERT用於任何單句或句子對分類任務,應該直接實現。
注意:您可能會看到Running train on CPU
消息。這實際上只是意味著它在包括GPU的雲TPU以外的其他東西上運行。
訓練分類器後,可以使用-do_predict = true命令在推理模式下使用它。您需要在輸入文件夾中使用一個名為test.tsv的文件。輸出將在輸出文件夾中的名為test_results.tsv的文件中創建。每行將包含每個樣本的輸出,列是類概率。
export BERT_BASE_DIR=/path/to/bert/uncased_L-12_H-768_A-12
export GLUE_DIR=/path/to/glue
export TRAINED_CLASSIFIER=/path/to/fine/tuned/classifier
python 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/
斯坦福問題回答數據集(小隊)是回答基準數據集的一個流行問題。 BERT(在發佈時)在小隊上獲得最先進的結果,幾乎沒有特定於任務的網絡體系結構修改或數據增強。但是,它確實需要半複合數據預處理和後處理才能處理(a)小隊上下文段落的可變長度性質,以及(b)用於小隊訓練的字符級答案註釋。此處理已在run_squad.py
中實現和記錄。
要在小隊上運行,您將首先需要下載數據集。該小隊網站似乎不再鏈接到v1.1數據集,但是可以在此處找到必要的文件:
將這些下載到一些目錄$SQUAD_DIR
。
由於內存限制,目前無法在12GB-16GB GPU上複製該論文的最先進小隊(實際上,即使是批次1也似乎不適合使用BERT-Large
)。但是,可以使用這些超參數在GPU上訓練合理強大的BERT-Base
模型:
python run_squad.py
--vocab_file= $BERT_BASE_DIR /vocab.txt
--bert_config_file= $BERT_BASE_DIR /bert_config.json
--init_checkpoint= $BERT_BASE_DIR /bert_model.ckpt
--do_train=True
--train_file= $SQUAD_DIR /train-v1.1.json
--do_predict=True
--predict_file= $SQUAD_DIR /dev-v1.1.json
--train_batch_size=12
--learning_rate=3e-5
--num_train_epochs=2.0
--max_seq_length=384
--doc_stride=128
--output_dir=/tmp/squad_base/
開發集預測將被保存到一個名為predictions.json
的output_dir
中。
python $SQUAD_DIR /evaluate-v1.1.py $SQUAD_DIR /dev-v1.1.json ./squad/predictions.json
應該產生這樣的輸出:
{ " f1 " : 88.41249612335034, " exact_match " : 81.2488174077578}
您應該看到類似於BERT-Base
論文中報告的88.5%的結果。
如果您可以訪問云TPU,則可以使用BERT-Large
訓練。這是一組超參數(略有不同),始終獲得約90.5%-91.0%的F1單一系統,僅在小隊上訓練:
python run_squad.py
--vocab_file= $BERT_LARGE_DIR /vocab.txt
--bert_config_file= $BERT_LARGE_DIR /bert_config.json
--init_checkpoint= $BERT_LARGE_DIR /bert_model.ckpt
--do_train=True
--train_file= $SQUAD_DIR /train-v1.1.json
--do_predict=True
--predict_file= $SQUAD_DIR /dev-v1.1.json
--train_batch_size=24
--learning_rate=3e-5
--num_train_epochs=2.0
--max_seq_length=384
--doc_stride=128
--output_dir=gs://some_bucket/squad_large/
--use_tpu=True
--tpu_name= $TPU_NAME
例如,一個隨機運行這些參數會產生以下DEV分數:
{ " f1 " : 90.87081895814865, " exact_match " : 84.38978240302744}
如果您在此之前在Triviaqa上微調一個時代,則結果將會更好,但是您需要將Triviaqa轉換為小隊JSON格式。
該模型還在run_squad.py
中實現和記錄。
要在Squad 2.0上運行,您首先需要下載數據集。必要的文件可以在此處找到:
將這些下載到一些目錄$SQUAD_DIR
。
在Cloud TPU上,您可以使用Bert-Large運行,如下所示:
python run_squad.py
--vocab_file= $BERT_LARGE_DIR /vocab.txt
--bert_config_file= $BERT_LARGE_DIR /bert_config.json
--init_checkpoint= $BERT_LARGE_DIR /bert_model.ckpt
--do_train=True
--train_file= $SQUAD_DIR /train-v2.0.json
--do_predict=True
--predict_file= $SQUAD_DIR /dev-v2.0.json
--train_batch_size=24
--learning_rate=3e-5
--num_train_epochs=2.0
--max_seq_length=384
--doc_stride=128
--output_dir=gs://some_bucket/squad_large/
--use_tpu=True
--tpu_name= $TPU_NAME
--version_2_with_negative=True
我們假設您已經復制了從輸出目錄到稱為./squad/的本地目錄的所有內容。最初的開發設置預測將在./squad/predictions.json以及無答案的分數(“”)與每個問題的最佳非零答案之間的差異。/squad/null_odds.json中
運行此腳本以調整預測零與非空的答案的閾值:
python $ squad_dir/evaluate-v2.0.py $ skead_dir/dev-v2.0.json ./squad/predictions.json -na-prob-file ./squad/squad/null_odds.json
假設腳本輸出“ BEST_F1_THRESH”閾值。 (典型值在-1.0和-5.0之間。現在,您可以重新運行模型以生成衍生閾值的預測,也可以從./squad/nbest_predictions.json提取適當的答案。
python run_squad.py
--vocab_file= $BERT_LARGE_DIR /vocab.txt
--bert_config_file= $BERT_LARGE_DIR /bert_config.json
--init_checkpoint= $BERT_LARGE_DIR /bert_model.ckpt
--do_train=False
--train_file= $SQUAD_DIR /train-v2.0.json
--do_predict=True
--predict_file= $SQUAD_DIR /dev-v2.0.json
--train_batch_size=24
--learning_rate=3e-5
--num_train_epochs=2.0
--max_seq_length=384
--doc_stride=128
--output_dir=gs://some_bucket/squad_large/
--use_tpu=True
--tpu_name= $TPU_NAME
--version_2_with_negative=True
--null_score_diff_threshold= $THRESH
紙上的所有實驗均在雲TPU上進行微調,該雲TPU具有64GB的設備RAM。因此,當使用具有12GB-16GB RAM的GPU時,如果您使用論文中描述的相同的超參數,則可能會遇到不可存儲的問題。
影響內存使用的因素是:
max_seq_length
:釋放的型號的序列長度最高為512,但您可以以較短的最大序列長度進行微調以節省大量內存。這是由我們示例代碼中的max_seq_length
標誌控制的。
train_batch_size
:內存使用也與批處理大小成正比。
模型類型, BERT-Base
與BERT-Large
: BERT-Large
模型所需的記憶比BERT-Base
要多得多。
優化器:BERT的默認優化器是Adam,它需要大量的存儲器來存儲m
和v
向量。切換到更有效的內存優化器可以減少內存使用量,但也會影響結果。我們尚未對其他優化器進行微調。
使用默認培訓腳本( run_classifier.py
和run_squad.py
),我們用TensorFlow 1.11.0:在單泰坦X GPU(12GB RAM)上基準了最大批量大小:
系統 | SEQ長度 | 最大批處理大小 |
---|---|---|
BERT-Base | 64 | 64 |
... | 128 | 32 |
... | 256 | 16 |
... | 320 | 14 |
... | 384 | 12 |
... | 512 | 6 |
BERT-Large | 64 | 12 |
... | 128 | 6 |
... | 256 | 2 |
... | 320 | 1 |
... | 384 | 0 |
... | 512 | 0 |
不幸的是,這些最大批量的大小是BERT-Large
如此之小,以至於無論使用的學習率如何,它們實際上會損害模型的準確性。我們正在為此存儲庫添加代碼,該庫將允許在GPU上使用更大的有效批量大小。該代碼將基於以下技術之一:
梯度積累:在Minibatch中的樣品通常相對於梯度計算獨立(不包括批准歸一化,此處未使用)。這意味著在執行重量更新之前,可以累積多個較小小型匹配的梯度,這將完全等同於單個較大的更新。
梯度檢查點:DNN訓練期間GPU/TPU存儲器的主要用途是緩存向前通行中有效計算所必需的中間激活。 “梯度檢查點”通過以智能方式重新計算激活來交換內存時間。
但是,這在當前版本中尚未實現。
在某些情況下,與其微調整個預訓練的模型端到端,不如獲得預訓練的上下文嵌入,它們是從PRE的隱藏層生成的每個輸入令牌的固定上下文表示 - 訓練模型。這也應該減輕大多數陳舊的問題。
例如,我們包括腳本extract_features.py
,可以這樣使用:
# Sentence A and Sentence B are separated by the ||| delimiter for sentence
# pair tasks like question answering and entailment.
# For single sentence inputs, put one sentence per line and DON'T use the
# delimiter.
echo ' Who was Jim Henson ? ||| Jim Henson was a puppeteer ' > /tmp/input.txt
python extract_features.py
--input_file=/tmp/input.txt
--output_file=/tmp/output.jsonl
--vocab_file= $BERT_BASE_DIR /vocab.txt
--bert_config_file= $BERT_BASE_DIR /bert_config.json
--init_checkpoint= $BERT_BASE_DIR /bert_model.ckpt
--layers=-1,-2,-3,-4
--max_seq_length=128
--batch_size=8
這將創建一個JSON文件(每行輸入線一行),該文件包含來自layers
指定的每個變壓器層的BERT激活(-1是變壓器的最終隱藏層等)。
請注意,此腳本將產生非常大的輸出文件(默認情況下,每個輸入令牌約為15kb)。
如果您需要保持原始單詞和令牌化詞(用於投影培訓標籤)之間的一致性,請參見下面的令牌化部分。
注意:您可能會Could not find trained model in model_dir: /tmp/tmpuB5g5c, running initialization to predict.
可以預期此消息,這只是意味著我們正在使用init_from_checkpoint()
API而不是保存的模型API。如果您沒有指定檢查點或指定無效的檢查點,則此腳本將抱怨。
對於句子級任務(或句子意)任務,令牌化非常簡單。只需按照run_classifier.py
和extract_features.py
中的示例代碼。句子級任務的基本過程是:
實例化tokenizer = tokenization.FullTokenizer
tokens = tokenizer.tokenize(raw_text)
tokenize原始文本。
截斷至最大序列長度。 (您最多可以使用512,但是如果可能的話,您可能想使用較短的時間。)
在正確的位置添加[CLS]
和[SEP]
令牌。
文字級別和跨度級任務(例如,小隊和NER)更為複雜,因為您需要保持輸入文本和輸出文本之間的一致性,以便可以投影培訓標籤。小隊是一個特別複雜的例子,因為輸入標籤是基於字符的,而小隊的段落通常比我們的最大序列長度更長。請參閱run_squad.py
中的代碼以顯示我們如何處理此操作。
在我們描述處理單詞級任務的一般配方之前,重要的是要了解我們的令牌機在做什麼。它有三個主要步驟:
文本歸一化:將所有空格字符轉換為空間,(對於Uncased
型號)縮小輸入並剝離口音標記。例如, John Johanson's, → john johanson's,
。
標點符號拆分:將所有標點字符分開(即,圍繞所有標點字符添加空格)。標點字符定義為(a)具有P*
unicode類的任何內容,(b)任何非字母/number/space ascii字符(例如,諸如$
之類的字符在技術上不是標點符號)。例如, john johanson's, → john johanson ' s ,
WordPiece令牌化:將Whitespace令牌化應用於上述過程的輸出,並將單詞令牌化應用於每個令牌。 (我們的實現直接基於鏈接的tensor2tensor
的實現)。例如, john johanson ' s , → john johan ##son ' s ,
該方案的優點是它與大多數現有的英語象徵器“兼容”。例如,想像一下您有一個詞性標記任務,看起來像這樣:
Input: John Johanson 's house
Labels: NNP NNP POS NN
令牌化輸出看起來像這樣:
Tokens: john johan ##son ' s house
至關重要的是,這將是相同的輸出,就像原始文本是John Johanson's house
(在's
之前沒有空間)。
如果您具有帶有單詞級註釋的預先講述的表示形式,則可以獨立地將每個輸入單詞歸為每個輸入單詞,並確定性地維護原始的對準:
### Input
orig_tokens = [ "John" , "Johanson" , "'s" , "house" ]
labels = [ "NNP" , "NNP" , "POS" , "NN" ]
### Output
bert_tokens = []
# Token map will be an int -> int mapping between the `orig_tokens` index and
# the `bert_tokens` index.
orig_to_tok_map = []
tokenizer = tokenization . FullTokenizer (
vocab_file = vocab_file , do_lower_case = True )
bert_tokens . append ( "[CLS]" )
for orig_token in orig_tokens :
orig_to_tok_map . append ( len ( bert_tokens ))
bert_tokens . extend ( tokenizer . tokenize ( orig_token ))
bert_tokens . append ( "[SEP]" )
# bert_tokens == ["[CLS]", "john", "johan", "##son", "'", "s", "house", "[SEP]"]
# orig_to_tok_map == [1, 2, 4, 6]
現在, orig_to_tok_map
可用於將labels
投影到令牌化表示形式。
有普通的英語令牌化方案,這將導致BERT預先培訓的方式之間的不匹配。例如,如果您的輸入令牌化do n't
收縮分開,這將導致不匹配。如果有可能這樣做,則應預處理數據以將其轉換回原始文本,但是如果不可能,則此不匹配可能沒什麼大不了的。
我們正在發布代碼以在任意文本語料庫上進行“蒙版LM”和“下一個句子預測”。請注意,這不是用於論文使用的確切代碼(原始代碼是用C ++編寫的,並且具有額外的複雜性),但是此代碼確實會如文紙中所述生成預訓練數據。
這是運行數據生成的方法。輸入是一個純文本文件,每行1個句子。 (重要的是,這些是“下一個句子預測”任務的實際句子)。文檔由空線界定。輸出是一組tf.train.Example
序列化為TFRecord
文件格式。
您可以使用現成的NLP工具包(例如Spacy)執行句子細分。 create_pretraining_data.py
腳本將連接段,直到達到最大序列長度,以最大程度地減少填充的計算浪費(有關更多詳細信息,請參見腳本)。但是,您可能需要故意在輸入數據(例如,隨機截斷輸入段的2%)中添加少量噪聲,以使其在微調過程中更適合非句子輸入。
該腳本將整個輸入文件的所有示例存儲在內存中,因此,對於大型數據文件,您應該將輸入文件碎片並多次調用腳本。 (您可以將文件圈傳遞到run_pretraining.py
,例如, tf_examples.tf_record*
。)
max_predictions_per_seq
是每個序列蒙版LM預測的最大數量。您應該將其設置為圍繞max_seq_length
* masked_lm_prob
(腳本不會自動執行此操作,因為確切的值需要傳遞給兩個腳本)。
python create_pretraining_data.py
--input_file=./sample_text.txt
--output_file=/tmp/tf_examples.tfrecord
--vocab_file= $BERT_BASE_DIR /vocab.txt
--do_lower_case=True
--max_seq_length=128
--max_predictions_per_seq=20
--masked_lm_prob=0.15
--random_seed=12345
--dupe_factor=5
這是運行預訓練的方法。如果您是從頭開始的預訓練,請勿包括init_checkpoint
。 bert_config_file
中指定了模型配置(包括詞彙大小)。此演示代碼僅針對少數步驟(20)進行預訓練,但是實際上,您可能希望將num_train_steps
設置為10000個或更多步驟。傳遞給run_pretraining.py
max_seq_length
和max_predictions_per_seq
參數必須與create_pretraining_data.py
相同。
python run_pretraining.py
--input_file=/tmp/tf_examples.tfrecord
--output_dir=/tmp/pretraining_output
--do_train=True
--do_eval=True
--bert_config_file= $BERT_BASE_DIR /bert_config.json
--init_checkpoint= $BERT_BASE_DIR /bert_model.ckpt
--train_batch_size=32
--max_seq_length=128
--max_predictions_per_seq=20
--num_train_steps=20
--num_warmup_steps=10
--learning_rate=2e-5
這將產生這樣的輸出:
***** Eval results *****
global_step = 20
loss = 0.0979674
masked_lm_accuracy = 0.985479
masked_lm_loss = 0.0979328
next_sentence_accuracy = 1.0
next_sentence_loss = 3.45724e-05
請注意,由於我們的sample_text.txt
文件很小,因此此示例培訓將僅以幾個步驟擬合該數據並產生不切實際的高精度數字。
bert_config.json
中更改vocab_size
。如果您使用較大的詞彙量而不更改此詞彙,則由於未經檢查的外部訪問,在GPU或TPU上進行培訓時,您可能會得到NAN。max_seq_length
的不同值生成兩次數據。BERT-Base
,該基礎大約需要2週,費用約為500美元(基於2018年10月的價格) 。與論文中使用的內容相比,僅在單個雲TPU上進行訓練時,您將不得不縮小批量尺寸。建議使用適合TPU內存的最大批量尺寸。我們將無法釋放論文中使用的預處理數據集。對於Wikipedia,建議的預處理是下載最新的轉儲,使用WikiExtractor.py
提取文本,然後應用任何必要的清理以將其轉換為純文本。
不幸的是,收集BookCorpus的研究人員不再可以公開下載。 Guttenberg數據集項目是一個較小的(200m)的舊書籍(200m),這些舊書籍是公共領域。
Common Crawl是另一個非常大的文本集合,但是您可能需要進行大量的預處理和清理才能提取可用的語料庫進行預訓練BERT。
該存儲庫不包括學習新文字詞彙的代碼。原因是本文中使用的代碼是在C ++中實現的,並具有對Google內部庫的依賴關係。對於英語而言,從我們的詞彙和預訓練的模型開始幾乎總是更好。對於學習其他語言的詞彙,有許多開源選項可用。但是,請記住,它們與我們的tokenization.py
不兼容。
Google的句子庫
Tensor2Tensor的文字生成腳本
Rico Sennrich的字節對編碼庫
如果您想將Bert與Colab一起使用,則可以開始使用筆記本“與Cloud TPU的Bert Finetuning”。在撰寫本文時(2018年10月31日),Colab用戶可以免費免費訪問Cloud TPU。注意:每個用戶有限公司有限公司,需要一個帶有存儲的Google雲平台帳戶(儘管可以免費獲得與GCP註冊的免費信用存儲),並且將來可能不再可用。單擊剛剛鏈接的Bert Colab以獲取更多信息。
是的,此存儲庫中的所有代碼都使用CPU,GPU和Cloud TPU開箱即用。但是,GPU培訓僅是單GPU。
有關更多信息,請參見有關存儲外問題的部分。
沒有官方的Pytorch實施。但是,HuggingFace的NLP研究人員為Bert提供了Pytorch版本,該版本與我們的預訓練檢查點兼容,並能夠重現我們的結果。我們沒有參與Pytorch實施的創建或維護,因此請將任何問題引向該存儲庫的作者。
沒有官方的Chainer實施。但是,Sosuke Kobayashi製作了Bert的連鎖版本,它與我們的預訓練檢查點兼容,並能夠重現我們的結果。我們不參與Chainer實施的創建或維護,因此請將任何問題引向該存儲庫的作者。
是的,我們計劃在不久的將來發布多種語言BERT模型。我們無法確切地承諾將包括哪些語言包括在內,但它可能是一個單一的模型,其中包括大多數具有大小尺寸的Wikipedia的語言。
BERT-Large
的模型嗎?到目前為止,我們還沒有試圖訓練BERT-Large
的任何東西。如果我們能夠獲得重大改進,我們可能會發布更大的模型。
所有代碼和模型均在Apache 2.0許可下發布。有關更多信息,請參見LICENSE
文件。
現在,引用Arxiv紙:
@article{devlin2018bert,
title={BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding},
author={Devlin, Jacob and Chang, Ming-Wei and Lee, Kenton and Toutanova, Kristina},
journal={arXiv preprint arXiv:1810.04805},
year={2018}
}
如果我們將論文提交給會議或期刊,我們將更新Bibtex。
這不是官方的Google產品。
有關使用BERT的幫助或問題,請提交GitHub問題。
有關與Bert相關的個人交流,請聯繫Jacob Devlin( [email protected]
),Ming-Wei Chang( [email protected]
)或Kenton Lee( [email protected]
)。