## 目录
- [8. 命名实体识别](#8-命名实体识别)
- [8.1 概述](#81-概述)
- [8.2 基于隐马尔可夫模型序列标注的命名实体识别](#82-基于隐马尔可夫模型序列标注的命名实体识别)
- [8.3 基于感知机序列标注的命名实体识别](#83-基于感知机序列标注的命名实体识别)
- [8.4 基于条件随机场序列标注的命名实体识别](#84-基于条件随机场序列标注的命名实体识别)
- [8.5 命名实体识别标准化评测](#85-命名实体识别标准化评测)
- [8.6 自定义领域命名实体识别](#86-自定义领域命名实体识别)

## 8. 命名实体识别

### 8.1 概述

1. **命名实体**

   文本中有一些描述实体的词汇。比如人名、地名、组织机构名、股票基金、医学术语等，称为**命名实体**。具有以下共性:

   - 数量无穷。比如宇宙中的恒星命名、新生儿的命名不断出现新组合。
   - 构词灵活。比如中国工商银行，既可以称为工商银行，也可以简称工行。
   - 类别模糊。有一些地名本身就是机构名，比如“国家博物馆”

2. **命名实体识别**

   识别出句子中命名实体的边界与类别的任务称为**命名实体识别**。由于上述难点，命名实体识别也是一个统计为主、规则为辅的任务。

   对于规则性较强的命名实体，比如网址、E-mail、IBSN、商品编号等，完全可以通过正则表达式处理，未匹配上的片段交给统计模型处理。

   命名实体识别也可以转化为一个序列标注问题。具体做法是将命名实体识别附着到{B,M,E,S}标签，比如， 构成地名的单词标注为“B/ME/S- 地名”，以此类推。对于那些命名实体边界之外的单词，则统一标注为0 ( Outside )。具体实施时，HanLP做了一个简化，即所有非复合词的命名实体都标注为S，不再附着类别。这样标注集更精简，模型更小巧。

命名实体识别实际上可以看作分词与词性标注任务的集成: 命名实体的边界可以通过{B,M,E,S}确定，其类别可以通过 B-nt 等附加类别的标签来确定。

HanLP内部提供了语料库转换工序，用户无需关心，只需要传入 PKU 格式的语料库路径即可。



### 8.2 基于隐马尔可夫模型序列标注的命名实体识别

之前我们就介绍过隐马尔可夫模型，详细见: [4.隐马尔可夫模型与序列标注](https://github.com/NLP-LOVE/Introduction-NLP/blob/master/chapter/4.%E9%9A%90%E9%A9%AC%E5%B0%94%E5%8F%AF%E5%A4%AB%E6%A8%A1%E5%9E%8B%E4%B8%8E%E5%BA%8F%E5%88%97%E6%A0%87%E6%B3%A8.md)

隐马尔可夫模型命名实体识别代码见(**自动下载 PKU 语料库**): hmm_ner.py

[https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch08/hmm_ner.py](https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch08/hmm_ner.py)

运行代码后结果如下:

```
华北电力公司/nt 董事长/n 谭旭光/nr 和/c 秘书/n 胡花蕊/nr 来到/v 美国纽约/ns 现代/ntc 艺术/n 博物馆/n 参观/v
```

其中机构名“华北电力公司”、人名“谭旭光”“胡花蕊”全部识别正确。但是地名“美国纽约现代艺术博物馆”则无法识别。有以下两个原因:

- PKU 语料库中没有出现过这个样本。
- 隐马尔可夫模型无法利用词性特征。

对于第一个原因，只能额外标注一些语料。对于第二个原因可以通过切换到更强大的模型来解决。



### 8.3 基于感知机序列标注的命名实体识别

之前我们就介绍过感知机模型，详细见: [5.感知机分类与序列标注](https://github.com/NLP-LOVE/Introduction-NLP/blob/master/chapter/5.%E6%84%9F%E7%9F%A5%E6%9C%BA%E5%88%86%E7%B1%BB%E4%B8%8E%E5%BA%8F%E5%88%97%E6%A0%87%E6%B3%A8.md)

感知机模型词性标注代码见(**自动下载 PKU 语料库**): perceptron_ner.py

[https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch08/perceptron_ner.py](https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch08/perceptron_ner.py)

运行会有些慢，结果如下:

```
华北电力公司/nt 董事长/n 谭旭光/nr 和/c 秘书/n 胡花蕊/nr 来到/v [美国纽约/ns 现代/ntc 艺术/n 博物馆/n]/ns 参观/v
```

与隐马尔可夫模型相比，已经能够正确识别地名了。



### 8.4 基于条件随机场序列标注的命名实体识别

之前我们就介绍过条件随机场模型，详细见: [6.条件随机场与序列标注](https://github.com/NLP-LOVE/Introduction-NLP/blob/master/chapter/6.%E6%9D%A1%E4%BB%B6%E9%9A%8F%E6%9C%BA%E5%9C%BA%E4%B8%8E%E5%BA%8F%E5%88%97%E6%A0%87%E6%B3%A8.md)

条件随机场模型词性标注代码见(**自动下载 PKU 语料库**): crf_ner.py

[https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch08/crf_ner.py](https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch08/crf_ner.py)

运行时间会比较长，结果如下:

```
华北电力公司/nt 董事长/n 谭旭光/nr 和/c 秘书/n 胡花蕊/nr 来到/v [美国纽约/ns 现代/ntc 艺术/n 博物馆/n]/ns 参观/v
```

得到了结果是一样的。



### 8.5 命名实体识别标准化评测

各个命名实体识别模块的准确率如何，并非只能通过几个句子主观感受。任何监督学习任务都有一套标准化评测方案，对于命名实体识别，按照惯例引入P、R 和 F1 评测指标。

在1998年1月《人民日报》语料库上的标准化评测结果如下:

| 模型           | P     | R     | F1    |
| -------------- | ----- | ----- | ----- |
| 隐马尔可夫模型 | 79.01 | 30.14 | 43.64 |
| 感知机         | 87.33 | 78.98 | 82.94 |
| 条件随机场     | 87.93 | 73.75 | 80.22 |

值得一提的是，准确率与评测策略、特征模板、语料库规模息息相关。通常而言，当语料库较小时，应当使用简单的特征模板，以防止模型过拟合；当语料库较大时，则建议使用更多特征，以期更高的准确率。当特征模板固定时，往往是语料库越大，准确率越高。



### 8.6 自定义领域命名实体识别

以上我们接触的都是通用领域上的语料库，所含的命名实体仅限于人名、地名、机构名等。假设我们想要识别专门领域中的命名实体，这时，我们就要自定义领域的语料库了。

1. **标注领域命名实体识别语料库**

   首先我们需要收集一些文本， 作为标注语料库的原料，称为**生语料**。由于我们的目标是识别文本中的战斗机名称或型号，所以生语料的来源应当是些军事网站的报道。在实际工程中，求由客户提出，则应当由该客户提供生语料。语料的量级越大越好，一般最低不少于数千个句子。

   生语料准备就绪后，就可以开始标注了。对于命名实体识别语料库，若以词语和词性为特征的话，还需要标注分词边界和词性。不过我们不必从零开始标注，而可以在HanLP的标注基础上进行校正，这样工作量更小。

   样本标注了数千个之后，生语料就被标注成了**熟语料**。下面代码自动下载语料库。

2. **训练领域模型**

   选择感知机作为训练算法(**自动下载 战斗机 语料库**): plane_ner.py

   [https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch08/plane_ner.py](https://github.com/NLP-LOVE/Introduction-NLP/tree/master/code/ch08/plane_ner.py)

   运行结果如下:

   ```
   下载 http://file.hankcs.com/corpus/plane-re.zip 到 /usr/local/lib/python3.7/site-packages/pyhanlp/static/data/test/plane-re.zip
   100.00%, 0 MB, 552 KB/s, 还有 0 分  0 秒   
   米高扬/nrf 设计/v [米格/nr -/w 17/m PF/nx]/np ：/w [米格/nr -/w 17/m]/np PF/n 型/k 战斗机/n 比/p [米格/nr -/w 17/m P/nx]/np 性能/n 更好/l 。/w
   [米格/nr -/w 阿帕奇/nrf -/w 666/m S/q]/np 横空出世/l 。/w
   ```

   这句话已经在语料库中出现过，能被正常识别并不意外。我们可以伪造一款“米格-阿帕奇-666S”战斗机，试试模型的繁华能力，发现依然能够正确识别。




