命名实体识别不只有BiLSTM+CRF

最近做命名实体识别(NER)的任务比较多,也刚刚接触NER不久,做一下小小的总结。近两年中文命名实体识别在信息抽取和关系抽取上的应用受到了研究人员的广泛关注,很多比赛也以NER为主题来命题。

最开始接触NER看到的大多数方法都是以BiLSTM+CRF的框架进行,包括工业界的很多大厂都是在用这个模型来做序列标注任务,效果也比较理想。除此之外工业界的传统方法还包括Softmax、HMM、MEMM、CRF、CRF++、IDCNN+CRF等等模型,但是在大多数情况下的表现不如BiLSTM+CRF。

BiLSTM+CRF一般采用预练词向量的方式,底层可以接Word2vec、Fasttext、CNN、Glove、ELMo等任意预训练的char级别的或bichar级别的Embedding。普遍采用封锁固定向量的方式,将输入映射成向量作为输入层接入双向的LSTM,再将前向和后向的结果拼接,接全连接层输出每个字符属于每个标签的概率,再接CRF,最后用Viterbi算法解码。

BERT及XLNet的出现将预训练词向量带到了一个前所未有的新高度,BERT无需封锁向量,词向量可以随着顶层任务进行微调。自然地,BERT+BiLSTM+CRF的方式逐渐取代了传统的序列标注方法,一跃成为各大比赛榜上的常客。

可能的模型结构

但是NER任务想要取得好的效果只能基于BiLSTM+CRF这一种网络结构吗?答案肯定是否定的。看了‘达观杯’文本智能信息抽取挑战赛的前几名的解决方案,我也找到了一些新的思路,前几名的方案中包含了以下在序列标注中很少见的网络结构:

  • BiLSTM+Attention+CRF
  • BiLSTM+CNN+CRF
  • BiLSTM+CNN+Attention+CRF
  • BiLSTM+SPAN

其中第一名方案的七个融合模型都采用了BiLSTM+CNN+CRF的网络结构,所以,打算自己实验一下,看看前三种网络的效果如何。

实验配置

设定参数

  • 网络层数=6层(为了训练得快点)
  • crf_only=False
  • batch_size=8(GPU跑不了更大的batch_size了)
  • num_train_epochs=10
    其余参数使用默认值
    以下实验可能不够严谨,不具有参考价值,由于训练时间过长,epoch只选择了10轮,远远没有达到模型最好的效果,只是自己单纯测试一下。每个模型只训练了一次,没有多次训练取平均值。

开始实验

首先先放上crf_only=True的结果,即只用BERT+CRF来做NER任务

              LOC: precision:  93.62%; recall:  94.83%; FB1:  94.22  3509
              ORG: precision:  88.61%; recall:  91.27%; FB1:  89.92  2231
              PER: precision:  96.69%; recall:  96.43%; FB1:  96.56  1815

接着是crf_only=False的结果,即BERT+BiLSTM+CRF

              LOC: precision:  93.27%; recall:  95.21%; FB1:  94.23  3536
              ORG: precision:  87.97%; recall:  91.14%; FB1:  89.52  2244
              PER: precision:  96.56%; recall:  97.25%; FB1:  96.91  1833

可以看到加了BiLSTM后,效果好像有一点提升,但是很多指标好像还不如不加BiLSTM

BERT+BiLSTM+CNN+CRF

接下来将四层相同的CNN网络加入BiLSTM和CRF之间,卷积核尺寸为5,400维。没有drouout等其它层,修改lstm_crf_layer.py中的add_blstm_crf_layer函数为

    def add_blstm_crf_layer(self, crf_only):
        """
        blstm-cnn-crf网络
        :return:
        """
        if self.is_training:
            # lstm input dropout rate i set 0.9 will get best score
            self.embedded_chars = tf.nn.dropout(self.embedded_chars, self.dropout_rate)

        if crf_only:
            logits = self.project_crf_layer(self.embedded_chars)
        else:
            # blstm
            lstm_output = self.blstm_layer(self.embedded_chars)
            conv1 = tf.layers.conv1d(lstm_output, 400, 5, padding='same',
                                         name='conv1')
            conv2 = tf.layers.conv1d(conv1, 400, 5, padding='same',
                                         name='conv2')
            conv3 = tf.layers.conv1d(conv2, 400, 5, padding='same',
                                         name='conv3')
            conv4 = tf.layers.conv1d(conv3, 400, 5, padding='same',
                                         name='conv4')
            logits = self.project_bilstm_layer(conv4)
            # project
            # logits = self.project_bilstm_layer(lstm_output)
            
        # crf
        loss, trans = self.crf_layer(logits)
        # CRF decode, pred_ids 是一条最大概率的标注路径
        pred_ids, _ = crf.crf_decode(potentials=logits, transition_params=trans, sequence_length=self.lengths)
        return (loss, logits, trans, pred_ids)

实验结果:

              LOC: precision:  94.09%; recall:  95.06%; FB1:  94.57  3500
              ORG: precision:  88.92%; recall:  91.87%; FB1:  90.37  2238
              PER: precision:  96.71%; recall:  96.87%; FB1:  96.79  1823

BERT+BiLSTM+Attention+CRF

采用self-attention,其中的attention_layer, get_shape_list函数来自于bert_base.bert.modeling

    def add_blstm_crf_layer(self, crf_only):
        """
        blstm-attention-crf网络
        :return:
        """
        if self.is_training:
            # lstm input dropout rate i set 0.9 will get best score
            self.embedded_chars = tf.nn.dropout(self.embedded_chars, self.dropout_rate)

        if crf_only:
            logits = self.project_crf_layer(self.embedded_chars)
        else:
            # blstm
            lstm_output = self.blstm_layer(self.embedded_chars)
            input_shape = get_shape_list(lstm_output, expected_rank=3)
            attention_head = attention_layer(
                from_tensor=lstm_output,
                to_tensor=lstm_output,
                attention_mask=None,
                num_attention_heads=12,
                size_per_head=int(768 / 12),
                attention_probs_dropout_prob=0.1,
                initializer_range=0.02,
                do_return_2d_tensor=True,
                batch_size=input_shape[0],
                from_seq_length=input_shape[1],
                to_seq_length=input_shape[1])

            logits = self.project_bilstm_layer(attention_head)
            # project
            # logits = self.project_bilstm_layer(lstm_output)
            
        # crf
        loss, trans = self.crf_layer(logits)
        # CRF decode, pred_ids 是一条最大概率的标注路径
        pred_ids, _ = crf.crf_decode(potentials=logits, transition_params=trans, sequence_length=self.lengths)
        return (loss, logits, trans, pred_ids)

实验结果为:

              LOC: precision:  92.58%; recall:  92.55%; FB1:  92.57  3463
              ORG: precision:  85.48%; recall:  88.87%; FB1:  87.14  2252
              PER: precision:  94.16%; recall:  95.66%; FB1:  94.90  1849

BiLSTM+CNN+Attention+CRF

简单地将上面两个模型结合起来,代码就不贴了
实验结果为

              LOC: precision:  93.29%; recall:  94.66%; FB1:  93.97  3515
              ORG: precision:  88.22%; recall:  90.26%; FB1:  89.23  2216
              PER: precision:  96.26%; recall:  96.15%; FB1:  96.21  1818

总结

虽然实验结果不够严谨,不具有权威性,但总的来看BERT+BiLSTM+CNN+CRF的效果比较好,其余的几个结果差不多,起码没有比基准的BERT+CRF差。CNN的参数和一些dropout的搭配可能会让效果有所提升,但是加上CNN的原因和原理不得而知,可能有相关的论文我没看到,等有时间再看一下SPAN的原理和实现,和NER任务结合做一些实验。
\color{red}{(纯原创,转载请注明来源)}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容