# 中文NER的那些事儿1. Bert-Bilstm-CRF基线模型详解&代码实现

## NER问题抽象

• BIO：B标记实体的开始，I标记其余部分，非实体是O
• BMOES：B标记开始，E标记结束，中间是M，单字实体是S，非实体是O

## NER评估

NER评估分为Tag级别（B-LOC,I-LOC)和Entity级别(LOC)，一般以entity的micro F1-score为准。因为tag预测准确率高但是抽取出的entity有误，例如边界错误，在实际应用时依旧抽取的是错误的实体。repo中的evalution.py会针对预测结果分别计算Tag和Entity的指标，以下是Bert-bilstm-crf在MSRA数据集上的表现

[\begin{align} precision &= \frac{预测正确实体}{预测得到实体}\ recall &= \frac{预测正确实体}{实际实体} \ F1 &=\frac{2precisionrecall}{precision+recall}\ \end{align} ]

## 基线模型 Bert-Bilstm-CRF

def build_graph(features, labels, params, is_training):
input_ids = features['token_ids']
label_ids = features['label_ids']
segment_ids = features['segment_ids']
seq_len = features['seq_len']

embedding = pretrain_bert_embedding(input_ids, input_mask, segment_ids, params['pretrain_dir'],
params['embedding_dropout'], is_training)

lstm_output = bilstm(embedding, params['cell_type'], params['rnn_activation'],
params['hidden_units_list'], params['keep_prob_list'],
params['cell_size'], params['dtype'], is_training)

logits = tf.layers.dense(lstm_output, units=params['label_size'], activation=None,
use_bias=True, name='logits')

trans, log_likelihood = crf_layer(logits, label_ids, seq_len, params['label_size'], is_training)
pred_ids = crf_decode(logits, trans, seq_len, params['idx2tag'], is_training)
crf_loss = tf.reduce_mean(-log_likelihood)

return crf_loss, pred_ids


### Layer1 – Bert：Contextual Embedding/Pretrain Language Model

paper：Semi-supervised sequence tagging with bidirectional language models

### Layer2 – BiLSTM层真的需要么？

paper：Bidirectional LSTM-CRF Models for Sequence Tagging

16年的paper算是首篇把BiLSTM-CRF用于NER任务的尝试。Bilstm的存在是提取双向文本信息。和多数文本任务一样，如果想要speed up训练速度会考虑用CNN来替代RNN，想要捕捉kernel_size长度之外的信息，可以尝试stack-CNN或者拼接不同长度kernel_size的CNN。当时这些都是SOTA级别的模型，不过放在BERT出世后的今天，bilstm/cnn作为文本上下文信息提取的作用究竟还有多大嘞？

### Layer3-Cross-entropy vs CRF

paper: Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data

#### 1. HMM

• 齐次马尔可夫性假设：(P(s_{t}|s_{1,2,…t-1})=P(s_{t}|s_{t-1}))，当前实体label只和前一位置的label有关
• 不动性假设：转移概率矩阵和位置无关(P(s_i|s_{i-1})=P(s_j|s_{j-1}))
• 观测独立假设：观测只和当前位置隐状态有关(P(O_t|s_{1,2,…t-1},O_{1,2,…t-1})=P(O_t|s_t))

[\begin{align} argmax P(s_1,…,s_T|O_1,…,O_T) &\propto argmax P(s_1,…,s_T,O_1,…,O_T)\ &= argmax P(O_1,…,O_T|s_1,…,s_T)\cdot P(s_1,…,s_T)\ &= argmax P(s_0)\cdot \prod_{i=1}^TP(s_t|s_{t-1})\cdot P(O_t|s_t) \end{align} ]

• 初始状态(P(s_0))：句子第一个label是B-PER/I-PER/…/O的概率
• 全局转移矩阵(P(s_t|s_{t-1}))：B-PER->I-PER, I-PER->B-LOC，实体label间的转移概率
• 输出概率(P(O_t|s_t))：P(北｜B-LOC)已知状态输出是某一token的概率

• 观测独立假设，每个输出（character）当然不只依赖隐状态（label）还会依赖上下文信息
• HMM作为生成模型要计算联合概率，如果要引入额外特征来描述观测，例如大小写前缀后缀，需要计算每个特征的likelihood，所以很难引入额外特征。同时模型拟和的是联合概率，和预测需要的P(S|O)条件概率存在不一致。

#### 2.MEMM

HMM在序列标注中的优势是隐状态间的跳转，会有效提高实体预测label之间的一致性。让我们保留优点，放松观测独立的假设，再把生成模型换成判别模型，直接对P(S|O)进行建模我们就得到了MEMM最大熵马尔可夫模型。MEMM可以方便的引入任意特征来对观测数据进行描述，并且没有观测独立假设后实体标签可以依赖任意上下文信息。

[P(s_t|s_{t-1}, O) = \frac{1}{Z(s_{t-1},O)}exp(W^T \cdot F(s_t,s_{t-1},O)) ]

[\begin{align} & argmax P(s_1,…,s_T|O_1,…,O_T) \ &=\prod_{i=1}^TP(s_t|s_{t-1},O_1,…O_T) \ &=\prod_{i=1}^T\frac{1}{Z(s_{t-1},O)}exp(W^T \cdot F(s_t,s_{t-1},O)) \ \end{align} ]

#### 3. CRF

[\begin{align} & argmax P(s_1,…,s_T|O_1,…,O_T) \ &=\frac{1}{Z(x)} \prod_{i=1}^Texp(W^T \cdot F(s_i,s_{i-1},O))\ &=\frac{1}{\sum_{N^T\text{个paths} }exp( \sum_{i=1}^T W^T \cdot F(s_i,s_{i-1},O))}exp( \sum_{i=1}^T W^T \cdot F(s_i,s_{i-1},O)) \end{align} ]

[W^T \cdot F(s_{i-1},s_i,O) = \sum_{k=1}^{K} w_k f_k(s_i,O) + \sum_{l=1}^{L} w_l f_l(s_i,s_{i-1},O) ]

1. 计算真实序列的特征得分

2. binary_score =(\sum_{\text{real path}} \text{transition probabitliy})

3. unary_score =(\sum_{\text{real path}} \text{logits})
4. sequence_score = bianry_score + unary_score

5. 计算用于正则化的全部路径得分log_norm

crf_log_norm巧妙利用了矩阵计算把遍历所有路径(O(N^T))的复杂度降低到了(O(N^2T)), 每一步都是N*N的矩阵乘积运算在CrfForwardRnnCell中实现，细节可以去看李航大大的统计学习方法，简单来说就是定义矩阵M

[\begin{align} M(s_{i-1},s_i|O) &= exp(W^T \cdot F(s_i,s_{i-1},O))\ log(Z(x))&= log(s_1) + \sum_{i=2}^{T-1} M_i(X) +log(s_T)\ \end{align} ]

1. 输出crf_log_likelihood = sequence_score – log_norm

### Ref-A

1. Conditional Random Fields: Probabilistic Models for Segmenting and Labeling Sequence Data, 2001
2. Bidirectional LSTM-CRF Models for Sequence Tagging, 2015
3. Named Entity Recognition with Bidirectional LSTM-CNNs, 2016
4. Neural Architectures for Named Entity Recognition, 2016
5. Semi-supervised sequence tagging with bidirectional language model
6. 你的CRF层的学习率可能不够大
7. http://www.davidsbatista.net/blog/2018/05/09/Named_Entity_Evaluation/
8. https://zhuanlan.zhihu.com/p/103779616

### Ref-B Viterbi

1. 定义t时刻到达状态i的最大概率路径 [\delta_t(i)=max_{s_1,..s_{t-1}}P(s_1,..,s_{t-1},s_t=i,O_1,…,O_t|\pi,A,B) ]
2. 综合转移概率和输出概率，(\delta_t(i))存在以下递归关系，因此每一步只需要做N->N个状态复杂度为(O(N^2))的递归计算

[\delta_{t+1}(i) = max_{j}[\delta_{t}(j) \cdot A_{j,i}] \cdot B_i(O_{t+1}) ]

1. 向前递归计算的同时记录每一步状态i前一刻的状态j，当递归到序列尽头，得到T时刻最大概率的状态再往前回溯，得到最大概率对应的状态序列

Original: https://www.cnblogs.com/gogoSandy/p/14716671.html
Author: 风雨中的小七
Title: 中文NER的那些事儿1. Bert-Bilstm-CRF基线模型详解&代码实现

(0)