背景
BERT取得了较大成功,但是原始的模型并不能直接用于对句子打分 #35,也就是常规的语言模型任务。
如何利用bert的预训练模型对句子打分?
序列掩码的方式应该比较合理。
并非autoregressive结构,速度较快
方案
- 双向
- 采用sequential mask. 计算量较大,精度也最高
- 单向,类似GPT。计算量稍微小点,但是作为12层的transformer,计算量仍然不小
- 只用embedding(768维),自己构造小结构的语言模型
- 动态embedding: 用bert作为embedding layer
- 静态embedding
1比较靠谱,因此后面重点介绍方案一。
简介
对于一个句子 $S = w_1, w_2,…, w_k$,通常可以这样来表示整个句子的概率
$$
p(S) = \prod_{i=1}^{k} p(w_i | context)
$$
传统的语言模型,比如RNN中, $context = w_1, …, w_{i-1}$,
$$
p(S) = \prod_{i=1}^{k} p(w_i | w_1, …, w_{i-1})
$$
如何利用bert对句子打分?一个简单的思路就是每次mask掉一个词 $w _ i$ ,然后利用bert得到该词的概率 $p(w _ i)$。即作为双向语言模型,BERT具有更大的上下文信息,$context = w_1, …, w_{i-1}, w_{i+1}, …, w_k$,
$$
p(S) = \prod_{i=1}^{k} p(w_i | w_1, …, w_{i-1},w_{i+1}, …,w_k)
$$
进一步可以转化为句子的ppl。
总体评价
char-level的语言模型,由于词组内的高概率,会使整个句子ppl普遍偏高。句子间的相对ppl还靠谱。
单个word/char的概率预测效果较好。
建议:
用分词后的中文重新pretrain,然后进行word-level language model predict。
中文测试
1 2 3 4 5 6 7 8 9
| export BERT_BASE_DIR=model/chinese_L-12_H-768_A-12 export INPUT_FILE=data/lm/test.zh.tsv python run_lm_predict.py \ --input_file=$INPUT_FILE \ --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 \ --output_dir=/tmp/lm_output/
|
以下是部分结果,更多见result.zh.json
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| [ { "tokens": [ { "token": "2016", "prob": 0.06563900411128998 }, { "token": "全", "prob": 0.4981258511543274 }, { "token": "国", "prob": 0.9088247418403625 }, { "token": "低", "prob": 1.6259804397122934e-05 }, { "token": "考", "prob": 0.4023572504520416 }, ... ], "ppl": 13.400421357093588 }, { "tokens": [ { "token": "落", "prob": 0.1483132392168045 }, { "token": "霞", "prob": 0.42232587933540344 }, { "token": "与", "prob": 0.8615185022354126 }, { "token": "孤", "prob": 0.9975666999816895 }, { "token": "鹜", "prob": 0.5613960027694702 }, { "token": "齐", "prob": 0.18012434244155884 }, { "token": "跑", "prob": 1.3388593288254924e-05 }, ... ], "ppl": 11.983086642867598 },
|
中文测试样例来源于百度云dnnlm
更多测试
中文model给英文句子打分
1 2 3 4
| hello world gone with bad gone with the wind slavery african
|
采用的chinese_L-12_H-768_A-12
。即中文词典跑英文,会出现很多OOV,造成较多subtoken。
ppl较大。
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| [ { "tokens": [ { "token": "hello", "prob": 0.01559396181255579 }, { "token": "world", "prob": 7.31540481524462e-08 } ], "ppl": 29607.558139141183 }, { "tokens": [ { "token": "go", "prob": 0.16923364996910095 }, { "token": "##ne", "prob": 0.0627128928899765 }, { "token": "with", "prob": 0.019953709095716476 }, { "token": "bad", "prob": 9.239820428774692e-07 } ], "ppl": 267.37285553187235 }, { "tokens": [ { "token": "go", "prob": 0.026223953813314438 }, { "token": "##ne", "prob": 0.06661253422498703 }, { "token": "with", "prob": 0.04489848017692566 }, { "token": "the", "prob": 0.7770023941993713 }, { "token": "wind", "prob": 7.36875972506823e-06 } ], "ppl": 74.05246212422989 }, { "tokens": [ { "token": "s", "prob": 0.15798506140708923 }, { "token": "##la", "prob": 0.06484799832105637 }, { "token": "##ver", "prob": 0.04713333398103714 }, { "token": "##y", "prob": 0.022265272215008736 }, { "token": "af", "prob": 0.9910877346992493 }, { "token": "##ric", "prob": 0.9998739957809448 }, { "token": "##an", "prob": 0.17350609600543976 } ], "ppl": 6.592083876588999 } ]
|
我觉得,不能按照token来mask
char-level lm的一大缺陷,就是会造成局部概率过高,使得整体ppl失真。
ppl的本意是要考虑word间的
参考