BERT用于语言模型

背景

BERT取得了较大成功,但是原始的模型并不能直接用于对句子打分,也就是常规的语言模型任务。
如何利用bert的预训练模型对句子打分?序列掩码的方式应该比较合理。

简介

对于一个句子 $S = w_1, w_2,…, w_k$,通常可以这样来表示整个句子的概率

传统的语言模型,比如RNN中, $context = w1, …, w{i-1}$,

如何利用bert对句子打分?一个简单的思路就是每次mask掉一个词 $wi$ ,然后利用bert得到该词的概率 $p(w_i)$。即作为双向语言模型,BERT具有更大的上下文信息,$context = 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

参考