源码阅读笔记 BiLSTM+CRF做NER任务(二)

源码地址:https://github.com/ZhixiuYe/NER-pytorch

本篇正式进入源码的阅读,按照流程顺序,一一解剖。

一、流程图

源码阅读笔记 BiLSTM+CRF做NER任务(二)

二、详细步骤

1、数据预处理

1)将数据集从文件中加载出来,如果句子中出现了数字,会将其置零(可选),删除源码阅读笔记 BiLSTM+CRF做NER任务(二)无用句。 

2)转换标注模式,将iob1(数据集原有标注模式)转换为iob2,如果选用的是IOBES则将iob2转换成iobes选用的是IOB,则将iob2返回。iob1和iob2都是表示里面只有I、O、B,不同的是iob1中的B是为了隔断同类实体不同实体名的,而iob2中的B是为了作为实体名的开头的iobes中包含I(实体名内部)O(非实体)B(实体的开头)E(实体的结尾)S(单字实体名)

下例将说明iob1、iob2、iobes的形式:

源码阅读笔记 BiLSTM+CRF做NER任务(二)

3)创建word、char、tag、cap字典(根据训练集)。

word字典:统计单词词频,筛选出词频大于3的单词,按照词频逆序、单词顺序对单词由0开始编号并加入字典中。除此,加入'<PAD>'、'<UNK>'这两个单词,分别表示pad和未知词汇,赋予最大的两个编号。

char字典:统计字母频数,按照词频逆序、字母顺序对字母由0开始编号并加入字典中,除此,加入'<PAD>'并赋予最大的编号。

tag字典:统计标签频数,按照标签频数逆序、标签顺序对标签由0开始编号并加入字典中,除此,加入'<START>'和'<STOP>'并分别赋予-1和-2编号

cap字典:无法创建字典,映射关系为全小写:0,全大写:1,首字母大写:2,其他:3。

4)根据3创建的字典和映射关系,分别对训练集、验证集、测试集的word、char、cap、tag等特征做数值化。得出的数据集中每一句由{'str_words': str_words,'words': words,'chars': chars,'caps': caps,'tags': tags,}字典组成,句中每个单词对应一个这样的字典。

2、进入训练

从上面的数据预处理中,假如我们得到这么一个句子数据:

{'str_words': ['Amy','goes','to','Beijing','to','visit','Peking','University'],

'words': [0,1,2,3,2,4,5,6], 

'chars': [[0, 1, 2], [3, 4, 5, 6], [7, 4], [8, 5, 9, 10, 9, 11, 3], [7, 4], [12, 9, 6, 9, 7], [13, 5, 14, 9, 11, 3], [15, 11, 9, 12, 5, 16, 6, 9, 7, 2]],

'caps': [2,0,0,2,0,0,2,2], 

'tags': [0,1,1,2,1,1,3,3], }

注:该示例的words、chars、tags并未按照1所说的根据词频进行的编码,只是按照出现的先后顺序进行的编码。

1)char Embedding

① 对'chars'根据word长度进行排序,得到排序后的列表,与原列表对比生成索引映射关系。

② 对排序后的列表进行mask处理,即对word进行尾部填充0知道达到最长word长度。本例中,即是生成:[[15, 11, 9, 12, 5, 16, 6, 9, 7, 2],[8, 5, 9, 10, 9, 11, 3, 0, 0, 0],......],为8×10的矩阵。

③ 将生成的char新矩阵输入Embedding层,设置的size为25,在本例中将得到8×10×25的矩阵,并进行转置,成为10×8×25的矩阵。

④ 对得到的矩阵进行pack操作(去除pad),成为39×25的PackedSequence,batchsize为(10,7,6,5,4,3,2,2)。

⑤ 将PackedSequence输入到双向LSTM中,然后把输出的output的pack操作还原回去,再进行转置操作。

⑥ 提取出output中最后一个字母的out和第一个字母的out进行拼接,并且将排序的结果还原。

注:如果在进行pack操作时,选择batch_first=True,则不用进行转置操作;进行长度排序是pack操作必经的过程;双向lstm的结果的第三维长度为2*size,拼接时选择第一个字母的后size长度(t→1)和最后一个字母的前size长度(1→t)。

2)word Embedding

输入embedding层

3)cap Embedding

输入embedding层

4)拼接所有的Embedding并输入LSTM中

① 拼接char、word、cap Embedding

② 对最终的Embedding增加第二维(unsqueeze)

③ 输入到dropout层

④ 输入到双向LSTM层

⑤ 减去第二维

⑥ 输入到dropout层

⑦ 输入到一个线性层

5)无crf的话,使用交叉熵作为loss函数。

 

 

 

 

 

上一篇:Embedding一下看清楚


下一篇:百分点认知智能实验室出品:深度迁移学习十八问