google-research/bert官方代碼中的坑_run_classifier_效果很差原因

[[TOC好像還不支持]]

簡介

bert官方代碼google-research/bert中有很多很強的設定,稍有改動就會導致結果很差。此文檔簡單總結如下浸剩。
google-research/bert版本:d66a146

該文檔撰寫時間:2019年4月11日

主要基于任務:run_classifier.py

一糠馆、學習率相關

代碼使用了帶warmup和decay的Adam(AdamWeightDecayOptimizer),這兩個參數(shù)策略是動態(tài)學習率常用的工腋,問題在于,官方代碼中此兩參數(shù)跟命令行參數(shù)num_train_epochs-訓練輪數(shù)強關聯(lián)畅卓,如果盲目修改代碼而不恰當?shù)卦O置num_train_epochs參數(shù)就會很糟糕擅腰。

一個重要、多次用的參數(shù):訓練總步數(shù)num_train_steps=num_train_steps = int(len(train_examples) / FLAGS.train_batch_size * FLAGS.num_train_epochs)是由樣本數(shù)翁潘、batch_size和命令行參數(shù)num_train_epochs輪數(shù)計算出來的趁冈。【很重要拜马,一定注意】

1.1 warmup

在訓練的開始階段使用較小的學習率再逐漸調整到預設初始學習率對訓練有一定的幫助(某共識渗勘,出處未尋)。代碼中使用了線性的調整俩莽,計算公式(github)如下:

  # Implements linear warmup. I.e., if global_step < num_warmup_steps, the
  # learning rate will be `global_step/num_warmup_steps * init_lr`.
  if num_warmup_steps:
    global_steps_int = tf.cast(global_step, tf.int32)
    warmup_steps_int = tf.constant(num_warmup_steps, dtype=tf.int32)

    global_steps_float = tf.cast(global_steps_int, tf.float32)
    warmup_steps_float = tf.cast(warmup_steps_int, tf.float32)

    warmup_percent_done = global_steps_float / warmup_steps_float
    warmup_learning_rate = init_lr * warmup_percent_done

    is_warmup = tf.cast(global_steps_int < warmup_steps_int, tf.float32)
    learning_rate = (
        (1.0 - is_warmup) * learning_rate + is_warmup * warmup_learning_rate)

當訓練的步數(shù)global_steps小于warmup_steps時旺坠,將學習率乘以global_steps/warmup_steps這樣一個線性增長的系數(shù)。warmup_steps的計算公式(github)是num_warmup_steps = int(num_train_steps * FLAGS.warmup_proportion),其中warmup_proportion是一個命令行參數(shù)扮超,默認0.1取刃,num_train_steps是總共訓練的步數(shù),由num_train_epochs輪數(shù)計算出瞒津,如果這個數(shù)設的太大(尤其當訓練樣本超大時)前期學習率會很低基本不優(yōu)化蝉衣。

1.2 lr decay

代碼中使用了線性學習率衰減,使用了tf.train.polynomial_decay多項式衰減巷蚪,參數(shù)如下:

# Implements linear decay of the learning rate.
  learning_rate = tf.train.polynomial_decay(
      learning_rate,
      global_step,
      num_train_steps,
      end_learning_rate=0.0,
      power=1.0,
      cycle=False)

經(jīng)過num_train_steps后將學習率衰減到end_learning_rate=0.0病毡,power=1.0表示是個線性衰減。num_train_steps是根據(jù)命令行參數(shù)FLAGS.num_train_epochs-輪數(shù)計算出的屁柏,F(xiàn)LAGS.num_train_epochs默認是3啦膜,即如果未設置該參數(shù),3個epoch后學習率將是0L视鳌僧家!。

附tf.train.polynomial_decay介紹:

global_step = min(global_step, decay_steps)
  decayed_learning_rate = (learning_rate - end_learning_rate) *
                          (1 - global_step / decay_steps) ^ (power) +
                          end_learning_rate

【注意】:

  1. CASE1:訓練時間后裸删,調大batch_size八拱,會導致訓練總步數(shù)num_train_steps變小,甚至小于當前全局步數(shù)global_steps,此時學習率會變成0肌稻,就沒必要訓練了清蚀。可以對應比例調整num_train_epochs訓練輪數(shù)解決爹谭。

1.3 二次訓練

訓練一次后發(fā)現(xiàn)沒有完全收斂秽誊,要再接著訓練一次椎咧,但最新的checkpoints中學習率已經(jīng)變成0了鹰服,修改num_train_epochs直接訓練會導致沒有任何效果议惰。可以做如下修改:

  1. 指定新的output_dir, FLAGS.init_checkpoint指向上一次訓練的output_dir腹泌。
  2. model_fn函數(shù)初始化模型時不要restore優(yōu)化器相關的權重嘶卧,尤其learning_rate。

二真屯、shuffle-訓練時的數(shù)據(jù)打亂

如果訓練樣本順序輸入脸候,且同類樣本較多時,代碼中的shuffle可能起不到作用绑蔫。d = d.shuffle(buffer_size=100)使用了Dataset的shuffle,其中buffer_size指緩沖區(qū)大小泵额。訓練時每次從緩沖區(qū)中按batch取樣本配深,但緩沖區(qū)的補充是順序取后續(xù)樣本,如果buffer_size=1那就是沒有打亂嫁盲,順序地取樣本篓叶,如果buffer_size等于樣本總數(shù)就相當于全局shuflle,但可能內(nèi)存不夠羞秤。

【建議】:數(shù)據(jù)處理時提前打亂缸托;或buffer_size調大些,比如調成最大類下樣本數(shù)瘾蛋。

三俐镐、流程相關-Estimator

Estimator時tensorflow高級api,旨在將訓練哺哼、驗證佩抹、預測、部署統(tǒng)一取董,但會帶來很大的不靈活棍苹。常用流程一個epoch后eval一次,可以通過多次/循環(huán)調用estimator.train茵汰、estimator.evaluate枢里。但是:

  1. 目前代碼版本,每次train/evaluate都會重新構建model、加載與訓練模型栏豺、回復最新的checkpoint梭灿,目前有個PR提出通過RunHook避免,相見google-research/bert/pull/450

  2. 一定不要忽略FLAGS.num_train_epochsnum_train_epochs

后記

相比pytorch冰悠,tf學習成本要高一些堡妒,尤其一些高級api。預研型實驗還是pytorch簡單高效溉卓。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末皮迟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子桑寨,更是在濱河造成了極大的恐慌伏尼,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,640評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尉尾,死亡現(xiàn)場離奇詭異爆阶,居然都是意外死亡,警方通過查閱死者的電腦和手機沙咏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評論 3 395
  • 文/潘曉璐 我一進店門辨图,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肢藐,你說我怎么就攤上這事故河。” “怎么了吆豹?”我有些...
    開封第一講書人閱讀 165,011評論 0 355
  • 文/不壞的土叔 我叫張陵鱼的,是天一觀的道長。 經(jīng)常有香客問我痘煤,道長凑阶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,755評論 1 294
  • 正文 為了忘掉前任衷快,我火速辦了婚禮宙橱,結果婚禮上,老公的妹妹穿的比我還像新娘烦磁。我一直安慰自己养匈,他們只是感情好,可當我...
    茶點故事閱讀 67,774評論 6 392
  • 文/花漫 我一把揭開白布都伪。 她就那樣靜靜地躺著呕乎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪陨晶。 梳的紋絲不亂的頭發(fā)上猬仁,一...
    開封第一講書人閱讀 51,610評論 1 305
  • 那天帝璧,我揣著相機與錄音,去河邊找鬼湿刽。 笑死的烁,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的诈闺。 我是一名探鬼主播渴庆,決...
    沈念sama閱讀 40,352評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼雅镊!你這毒婦竟也來了襟雷?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,257評論 0 276
  • 序言:老撾萬榮一對情侶失蹤仁烹,失蹤者是張志新(化名)和其女友劉穎耸弄,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體卓缰,經(jīng)...
    沈念sama閱讀 45,717評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡计呈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,894評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了征唬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片捌显。...
    茶點故事閱讀 40,021評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖鳍鸵,靈堂內(nèi)的尸體忽然破棺而出苇瓣,到底是詐尸還是另有隱情,我是刑警寧澤偿乖,帶...
    沈念sama閱讀 35,735評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站哲嘲,受9級特大地震影響贪薪,放射性物質發(fā)生泄漏。R本人自食惡果不足惜眠副,卻給世界環(huán)境...
    茶點故事閱讀 41,354評論 3 330
  • 文/蒙蒙 一画切、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧囱怕,春花似錦霍弹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至台丛,卻和暖如春耍缴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評論 1 270
  • 我被黑心中介騙來泰國打工防嗡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留变汪,地道東北人。 一個月前我還...
    沈念sama閱讀 48,224評論 3 371
  • 正文 我出身青樓蚁趁,卻偏偏與公主長得像裙盾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子他嫡,可洞房花燭夜當晚...
    茶點故事閱讀 44,974評論 2 355

推薦閱讀更多精彩內(nèi)容