精华内容
下载资源
问答
  • CNN+BiLSTM 在一些任务当中,会选择在卷积层后加上一层LSTM或BiLSTM(反过来则不行),用于增强模型对语义的理解。CNN负责提取文本的特征,而BiLSTM负责理解句子的语义信息。当CNN融合了循环神经网络时,就是结合了...

    PS: 需要完整代码(包括图形界面代码)和详细说明的朋友,请先关注点赞收藏,再评论留下邮箱,我会第一时间发送给你。

    有积分的朋友也可以到这里下载:https://download.csdn.net/download/qq_44186838/22046704

    其他相关内容:

    轻松搞懂word2vec+SVM(支持向量机)实现中英文情感分类
    【TF-IDF、word2vec、svm、cnn、textcnn、bilstm、cnn+bilstm、bilstm+attention】英文长文本分类实战

    前言
    在这里插入图片描述
    讲道理,这篇博客应该可以帮助很多只有一点点NLP的朋友,在较短的时间内了解文本分类的整个过程并用代码复现整个流程。事先说明,这里大家先不要过分要求自己去理解整个模型的原理,先搞清楚整个实现流程,体验一下敲代码并成功应用的快感。

    模型简介

    Bi-LSTM

    LSTM的全称是Long Short-Term Memory,它是RNN(Recurrent Neural Network)的一种。LSTM由于其设计的特点,非常适合用于对时序数据的建模,如文本数据,该模型可以学习长期依赖信息,它通过特殊的门结构来去除或增加信息到细胞状态的能力,门是一种让信息选择式通过的方法,一共有三个门。第一层是忘记门,决定我们会从细胞状态中丢弃什么信息,下一步是确定什么样的新信息会被存放在细胞状态,下一步是更新细胞状态,最后输出信息。

    而Bi-LSTM模型由前向的LSTM和后向的LSTM组合而成,能够很好的处理双向数据的序列信息。一个LSTM层式从左往右处理,而另一个是从右往左处理。总体而言,更适合应用于长文本的分类任务。

    TextCNN

    TextCNN模型是由 Yoon Kim提出的Convolutional Naural Networks for Sentence Classification一文中提出的使用卷积神经网络来处理NLP问题的模型。TextCnn在文本分类问题上有着更加卓越的表现。从直观上理解,TextCNN通过一维卷积来获取句子中n-gram的特征表示。TextCNN对文本浅层特征的抽取能力很强,在短文本领域如搜索、对话领域专注于意图分类时效果很好,应用广泛,且速度快,一般是首选;对长文本领域,TextCNN主要靠filter窗口抽取特征,在长距离建模方面能力受限,且对语序不敏感。

    CNN+BiLSTM

    在一些任务当中,会选择在卷积层后加上一层LSTM或BiLSTM(反过来则不行),用于增强模型对语义的理解。CNN负责提取文本的特征,而BiLSTM负责理解句子的语义信息。当CNN融合了循环神经网络时,就是结合了这两者的功能,往往效果会有所提升。

    PS:不要想着拿TextCNN去融合BiLSTM,不是说不能融合,是没有必要。TextCNN本身就是一个非常优秀的模型了,在TextCNN后面加上一层循环神经网络,往往只是带来了更多的计算时间,其本身对于语义的理解,并没有什么帮助,甚至有可能对结果进行干扰。

    BiLSTM+注意力机制

    当输入的文本非常长的时候,我们之前引以为傲的双向长短期记忆模型也难以成为学霸,对文本有一个很好的向量表达。所以,这个时候就可以考虑使用注意力机制,来尝试抓住文本的重点。具体来讲,Attention机制就是通过保留BiLSTM编码器对输入序列的中间输出结果,再训练一个模型来对这些输入进行选择性的学习并且在模型输出时将输出序列与之进行关联。

    实现流程

    (1) 找数据集

    首先第一步,就是要找好数据集,没有数据集模型怎么学习,怎么涨知识。
    那这里呢,我们采用的情感数据集是weibo_senti_100k数据集,一共有119988条带情感标注的新浪微博评论,其中正负向评论均为 59994条,非常平衡的一个数据集。
    weibo_senti_100k
    其中label为文本标签,1代表正面评论,0代表负面评论。

    (2) 数据观察

    找完数据集之后呢,我们需要观察对数据集进行观察,判定它是否会不适合我们后续的任务,以及数据集的文本长度大致如何。
    这里我们先利用提取关键词的思想,生成一个词云图,用于观察该数据集的热门词。

    import os
    import numpy as np
    import pandas as pd
    import jieba.analyse
    
    from jieba import analyse
    
    from PIL import Image
    import matplotlib.pyplot as plt
    from matplotlib.font_manager import FontProperties
    from wordcloud import WordCloud,ImageColorGenerator
    
    if __name__ == '__main__':
        data = pd.read_csv('weibo_senti_100k.csv', header=0, encoding='utf-8-sig')['review']
        tfidf = analyse.extract_tags
        for line in data:
            if line.strip() == '':
                continue
            text = line
            # tfidf 仅仅从词的统计信息出发,而没有充分考虑词之间的语义信息
            keywords = tfidf(text,
                             allowPOS=('ns', 'nr', 'nt', 'nz', 'nl', 'n', 'vn', 'vd', 'vg', 'v', 'vf', 'a', 'an', 'i'))
            result = []
    
            for keyword in keywords:
                result.append(keyword)
            fo = open('keywords.txt', "a+", encoding='utf-8')  # 生成每句文本的关键词
            for j in result:
                fo.write(j)
                fo.write(' ')
            fo.write('\n')
            fo.close()
            
        # 开始生成词云图
        lyric = ''
        f = open('keywords.txt', 'r', encoding='utf-8')
    
        for i in f:
            lyric += f.read()
        # print(lyric)#自动加+'\n'
    
        # 考虑了相邻词的语义关系、基于图排序的关键词提取算法TextRank
        result = jieba.analyse.textrank(lyric, topK=50, withWeight=True)
    
        keywords = dict()
        for i in result:
            keywords[i[0]] = i[1]
        print(keywords)
    
        image = Image.open('./background.png')
        graph = np.array(image)
        print(graph)
        wc = WordCloud(font_path='SIMLI.TTF', background_color='White', max_words=200, mask=graph)
        wc.generate_from_frequencies(keywords)
        image_color = ImageColorGenerator(graph)  # 设置背景图像
        plt.imshow(wc)  # 画图
        plt.imshow(wc.recolor(color_func=image_color))  # 根据背景图片着色
        plt.axis("off")  # 不显示坐标轴
        plt.show()
        wc.to_file('wordCloud.png')
    
    

    数据集词云
    通过这个词云图,我们可以发现这个数据集并没有明显的领域偏向,也就是说它并不是单独在某一个领域下的文本内容。比方说,如果该数据集是汽车领域的文本内容,那么当使用该数据集进行其他领域的情感标注时的准确率就会变得相对较低。

    在进行实验之前,我进行了对数据集的句子长度与对应的数量进行了统计,大致结果如图所示。
    数据集长度统计图
    这里我以词为句子长度的基本单位,对数据集的句子长度进行了统计。不难发现的是,数据集的句子长度主要集中在了20附近,当长度超过100时,句子数量就几乎没有了。

    (3) 数据预处理

    首先,我们可以观察文本的内容,看是否有一些文本内容是对最终的情感标注没有影响甚至会有干扰的。假设我们在后续操作做自己爬取了数据的话,数据多少都会存在一些问题,比方说一些没有意义的标签符号。或者你发现你的任务是对长文本进行情感分类,但是数据集是短文本的时候,是否需要对这些长文本进行文本摘要。(这里我们就不对数据集的文本进行清洗,毕竟人家标注就是针对整个文本标注好的)

    接着,我们需要进行文本分词,这里我们用到的是结巴分词。同时我们也可以加载一些语料库,提高分词的准确性。

    import jieba
    
    jieba.load_userdict("SogouLabDic.txt")
    jieba.load_userdict("dict_baidu_utf8.txt")
    jieba.load_userdict("dict_pangu.txt")
    jieba.load_userdict("dict_sougou_utf8.txt")
    jieba.load_userdict("dict_tencent_utf8.txt")
    #jieba.load_userdict("my_dict.txt")
    
    def tokenizer(dataset_texts):
        text = [jieba.lcut(document.replace('\n', '')) for document in dataset_texts]
        return text
    

    需要注意的是,在很多文本分类的任务中,都会选择去除停用词。但是在情感分类中,也往往会选择不去除停用词。比方说“我可以!!!”和“我可以。”这两句话表达的情感差异是比较大的。当然啦,是否需要去除停用词,最好还是做下对比实验。

    (4) 文本特征提取

    分完词之后,就是准备将数据扔到模型训练啦。但是,模型可认不得自然语言,你需要将这些文本转换成模型认识的数据格式——矩阵。所以,我们需要对文本进行特征提取,即将文本转换成矩阵的形式。这里就需要用到一些方法啦,比方说传统的平权统计的方法、TF-IDF、BOW等。那在这里我们用到的方法是Word2vec的方法。

    Word2vec,是一群用来产生词向量的相关模型。这些模型为浅而双层的神经网络,用来训练以重新建构语言学之词文本。网络以词表现,并且需猜测相邻位置的输入词,在word2vec中词袋模型假设下,词的顺序是不重要的。训练完成之后,word2vec模型可用来映射每个词到一个向量,可用来表示词对词之间的关系,该向量为神经网络之隐藏层。通过Word2Vec算法得到每个词语的高维向量(词向量,Word Embedding)表示,词向量把相近意思的词语放在相近的位置。我们只需要有大量的某语言的语料,就可以用它来训练模型,获得词向量。

    那么在这里呢,我们就用数据集的文本来训练word2vec。

    from gensim.models.word2vec import Word2Vec
    
    cpu_count = multiprocessing.cpu_count()  
    vocab_dim = 100
    n_iterations = 1
    n_exposures = 10  # 所有频数超过10的词语
    window_size = 7
    
    def word2vec_train(data):
    	"""训练word2vec模型
        Parameters
        ----------
        data : 分词后的二维列表
        """
        model = Word2Vec(size=vocab_dim,
                         min_count=n_exposures,
                         window=window_size,
                         workers=cpu_count,
                         iter=n_iterations)
        model.build_vocab(data)  # input: list
        model.train(combined, total_examples=model.corpus_count, epochs=model.iter)
        model.save('Word2vec_model.pkl')
    

    此时我们已经得到了训练好的word2vec模型,即可以得到词语对应的词向量。到这里的话,文本特征提取就可以算结束了。但是由于标注是针对整一句话的,而非单独的一个词,我们需要求每一句话的句向量。

    from keras.preprocessing import sequence
    from gensim.corpora.dictionary import Dictionary
    
    def create_dictionaries(model=None, data=None):
    	"""将数据集文本转换成句向量,并得到两个词典(单词to序号、单词to向量)
        Parameters
        ----------
        model : 训练好的word2vec模型
        data : 分词后的文本列表
        Returns
        -------
        w2indx
            数据集中所有单词映射成序号的词典
        w2vec
        	数据集中所有单词映射成向量的词典
        data
        	数据集文本特征矩阵
    
        """
            if (data is not None) and (model is not None):
            gensim_dict = Dictionary()
            gensim_dict.doc2bow(model.wv.vocab.keys(),
                                allow_update=True)
            #  freqxiao10->0 所以k+1
            w2indx = {v: k + 1 for k, v in gensim_dict.items()}  # 频数超过10的词语的索引
            f = open("word2index.txt", 'w', encoding='utf8')
            for key in w2indx:
                f.write(str(key))
                f.write(' ')
                f.write(str(w2indx[key]))
                f.write('\n')
            f.close()
            w2vec = {word: model[word] for word in w2indx.keys()}  # 频数超过10的词语的词向量
    
            def parse_dataset(combined):
                data = []
                for sentence in combined:
                    new_txt = []
                    for word in sentence:
                        try:
                            new_txt.append(w2indx[word])
                        except:
                            new_txt.append(0)
                    data.append(new_txt)
                return data  # word=>index
    
            data = parse_dataset(data)
            data = sequence.pad_sequences(data, maxlen=maxlen)  
            return w2indx, w2vec, data
        else:
            print('文本为空!')
    

    为了满足后续建模的格式要求,这里采用的句特征的表示方法并非这种:[[词1向量], [词2向量], [词3向量], …, [词n向量]],这种表示方式的话,句特征就是一个二维的矩阵,而最终的表示方式为:[词1序号, 词2序号, 词3序号, …, 词n序号],此时句特征就成了一个向量。

    另外,由于模型对于输入格式的要求必须是矩阵的形式,那么就要求每个句向量的长度必须统一,但是实际上的句子长度并非统一的形式,所以我们设置了一个maxlen作为句子的最大长度值(这个值的选择可以参考我们在数据观察时得到的数据),当maxlen取100时,句子大于100的话就需要进行切割,句子小于100时,则进行填充(通常是直接补零),这里是直接调用了pad_sequences方法。

    (5) 划分训练集

    import numpy as np
    import keras
    from sklearn.model_selection import train_test_split
    
    def get_data(w2indx, w2vec, data, y):
        n_symbols = len(w2indx) + 1  # 补上索引为0(频数小于10)的词
        embedding_weights = np.zeros((n_symbols, vocab_dim))  
        for word, index in w2indx.items(): 
            embedding_weights[index, :] = w2vec[word]
        x_train, x_test, y_train, y_test = train_test_split(data, y, test_size=0.2)
        y_train = keras.utils.to_categorical(y_train, num_classes=2)  # 转换为one-hot特征
        y_test = keras.utils.to_categorical(y_test, num_classes=2)
        return n_symbols, embedding_weights, x_train, y_train, x_test, y_test
    

    这里是将数据集按8:2的比例划分成了训练集和测试集,并且得到了一个词典,该词典的关键词为词序号,对应的值为词向量。

    (6) 建立模型

    采用的损失函数为都是交叉熵损失函数,使用Adam进行优化。

    BiLSTM代码复现如下:

    from keras.models import Sequential
    from keras.models import load_model
    from keras.layers import Bidirectional, Activation
    from keras.layers.embeddings import Embedding
    from keras.layers.recurrent import LSTM
    from keras.layers.core import Dense, Dropout
    
    def train_bilstm(n_symbols, embedding_weights, x_train, y_train):
        model = Sequential()  # or Graph or whatever
        model.add(Embedding(output_dim=vocab_dim,
                            input_dim=n_symbols,
                            mask_zero=True,
                            weights=[embedding_weights],
                            input_length=maxlen))  
        model.add(Bidirectional(LSTM(output_dim=50, activation='tanh')))
        model.add(Dropout(0.5))
        model.add(Dense(2, activation='softmax'))  
    
        model.compile(loss='categorical_crossentropy',
                      optimizer='adam', metrics=['accuracy'])
    
        model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epoch, verbose=2)
    
        model.save('bilstm.h5')
    
    train_bilstm(n_symbols, embedding_weights, x_train, y_train)
    

    TextCNN代码复现如下:

    import keras
    from keras import Input, Model
    from keras.preprocessing import sequence
    from keras.models import load_model
    from keras.layers import Conv1D, MaxPooling1D, concatenate
    from keras.layers.embeddings import Embedding
    from keras.layers.core import Dense, Dropout, Flatten
    
    def train_textcnn(n_symbols, embedding_weights, x_train, y_train):
        main_input = Input(shape=(maxlen,), dtype='float64')
        embedder = Embedding(output_dim=vocab_dim,
                             input_dim=n_symbols,
                             input_length=maxlen,
                             weights=[embedding_weights])
        embed = embedder(main_input)
        cnn1 = Conv1D(256, 3, padding='same', strides=1, activation='relu')(embed)
        cnn1 = MaxPooling1D(pool_size=38)(cnn1)
        cnn2 = Conv1D(256, 4, padding='same', strides=1, activation='relu')(embed)
        cnn2 = MaxPooling1D(pool_size=37)(cnn2)
        cnn3 = Conv1D(256, 5, padding='same', strides=1, activation='relu')(embed)
        cnn3 = MaxPooling1D(pool_size=36)(cnn3)
        # 合并三个输出向量
        cnn = concatenate([cnn1, cnn2, cnn3], axis=-1)
        flat = Flatten()(cnn)
        drop = Dropout(0.5)(flat)
        main_output = Dense(2, activation='softmax')(drop)
        model = Model(inputs=main_input, outputs=main_output)
    
        model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    
        model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epoch, verbose=2)
    
        model.save('textcnn.h5')
    
    train_textcnn(n_symbols, embedding_weights, x_train, y_train)
    

    CNN+BiLSTM代码复现如下:

    import keras
    from keras import Input, Model
    from keras.preprocessing import sequence
    from keras.models import load_model
    from keras.layers import Conv1D, MaxPooling1D, concatenate
    from keras.layers import Bidirectional
    from keras.layers.embeddings import Embedding
    from keras.layers.recurrent import LSTM
    from keras.layers.core import Dense, Dropout, Flatten
    
    def train_cnn_bilstm(n_symbols, embedding_weights, x_train, y_train):
        main_input = Input(shape=(maxlen,), dtype='float64')
        embedder = Embedding(output_dim=vocab_dim,
                             input_dim=n_symbols,
                             input_length=maxlen,
                             weights=[embedding_weights])
        embed = embedder(main_input)
        cnn = Conv1D(64, 3, padding='same', strides=1, activation='relu')(embed)
        bilstm = Bidirectional(LSTM(output_dim=50, dropout=0.5, activation='tanh', return_sequences=True))(cnn)
        flat = Flatten()(bilstm)
        main_output = Dense(2, activation='softmax')(flat)
        model = Model(inputs=main_input, outputs=main_output)
        model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    
        model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epoch)
    
        model.save('cnnbilstm.h5')
    
    train_cnn_bilstm(n_symbols, embedding_weights, x_train, y_train)
    

    BiLSTM+注意力机制代码复现如下:

    import keras
    from keras import backend as K
    from keras.models import Sequential
    from keras.engine.topology import Layer
    from keras.layers import Bidirectional
    from keras.layers.embeddings import Embedding
    from keras.layers.recurrent import LSTM
    from keras.layers.core import Dense
    
    # 自定义Attention层
    class AttentionLayer(Layer):
        def __init__(self, attention_size=None, **kwargs):
            self.attention_size = attention_size
            super(AttentionLayer, self).__init__(**kwargs)
    
        def get_config(self):
            config = super().get_config()
            config['attention_size'] = self.attention_size
            return config
    
        def build(self, input_shape):
            assert len(input_shape) == 3
    
            self.time_steps = input_shape[1]
            hidden_size = input_shape[2]
            if self.attention_size is None:
                self.attention_size = hidden_size
    
            self.W = self.add_weight(name='att_weight', shape=(hidden_size, self.attention_size),
                                     initializer='uniform', trainable=True)
            self.b = self.add_weight(name='att_bias', shape=(self.attention_size,),
                                     initializer='uniform', trainable=True)
            self.V = self.add_weight(name='att_var', shape=(self.attention_size,),
                                     initializer='uniform', trainable=True)
            super(AttentionLayer, self).build(input_shape)
    
        def call(self, inputs):
            self.V = K.reshape(self.V, (-1, 1))
            H = K.tanh(K.dot(inputs, self.W) + self.b)
            score = K.softmax(K.dot(H, self.V), axis=1)
            outputs = K.sum(score * inputs, axis=1)
            return outputs
    
        def compute_output_shape(self, input_shape):
            return input_shape[0], input_shape[2]
    
    
    ##定义网络结构
    def train_bilstm_att(n_symbols, embedding_weights, x_train, y_train, ATT_SIZE):
        model = Sequential()
        model.add(Embedding(output_dim=vocab_dim,
                            input_dim=n_symbols,
                            weights=[embedding_weights],
                            input_length=maxlen))
    
        model.add(Bidirectional(LSTM(output_dim=50, dropout=0.5, return_sequences=True)))
        model.add(AttentionLayer(attention_size=ATT_SIZE))
        model.add(Dense(2, activation='softmax'))  
        model.compile(loss='categorical_crossentropy',
                      optimizer='adam', metrics=['accuracy'])
    
        model.fit(x_train, y_train, batch_size=batch_size, epochs=n_epoch)
    
        model.save('bilstmAtt.h5')
    
    train_bilstm_att(n_symbols, embedding_weights, x_train, y_train)
    

    补充一下,实现CNN+BiLSTM+Attention的融合模型的话,只需简单的在CNN+BiLSTM后加上一层Attention,或者在BiLSTM+Attention模型中的嵌入层后加上一层卷积层即可。

    (7) 模型评估

    from keras.models import load_model
    from sklearn.metrics import classification_report
    
    if __name__ == '__main__':
        model = load_model('bilstm.h5')
        # model = load_model('textcnn.h5')
        # model = load_model('cnnbilstm.h5')
        # model = load_model('bilstmAtt.h5', custom_objects={'AttentionLayer':AttentionLayer})
    
        y_pred = model.predict(x_test)
    
        for i in range(len(y_pred)):
            max_value = max(y_pred[i])
            for j in range(len(y_pred[i])):
                if max_value == y_pred[i][j]:
                    y_pred[i][j] = 1
                else:
                    y_pred[i][j] = 0
        # target_names = ['负面', '正面']
        print(classification_report(y_test, y_pred))
    

    自己玩玩

    在这里插入图片描述

    “智能”推荐:
    轻松搞懂word2vec+SVM(支持向量机)实现中英文情感分类
    【TF-IDF、word2vec、svm、cnn、textcnn、bilstm、cnn+bilstm、bilstm+attention】英文长文本分类实战

    展开全文
  • CRF Models for Sequence Tagging》的一个总结,先上链接:https://arxiv.org/pdf/1508.01991.pdf1. 概述这篇论文是百度2015年发表的,它并不是对LSTM进行创新,也不是对CRF进行创新,而是提出了将两种方法结合的...

    这篇文章是对《Bidirectional LSTM-CRF Models for Sequence Tagging》的一个总结,先上链接:https://arxiv.org/pdf/1508.01991.pdf

    1. 概述

    这篇论文是百度2015年发表的,它并不是对LSTM进行创新,也不是对CRF进行创新,而是提出了将两种方法结合的方式实现序列标注任务,并达到了当时的state of the art。BI-LSTM-CRF的优势在于可以有效地使用过去和未来的特征,这一点归功于双向LSTM的结构,同时它还可以通过CRF使用sentence level的标注信息(这里的sentence level我到后面再解释)。最后模型不仅鲁棒性强,而且对词嵌入的依赖较小。

    2. 基本介绍

    序列标注任务包括POS(词性标注)、chunking(组块分析:标出句子中的短语块)、NER(命名实体识别),文中的实验也是基于这三个经典的任务进行验证的。目前大多序列标注模型都是线性统计模型,例如HMM、MEMM、CRF等,文中作者提出了多种基于神经网络的序列标注模型,这些模型包括LSTM网络、BI-LSTM网络、LSTM-CRF和BI-LSTM-CRF。

    这篇paper的主要contribution:

    1. 系统地比较了上述提到的模型在NLP标注数据集上的性能
    2. BI-LSTM-CRF首次应用于NLP标准数据集上,并且在三个经典的序列标注任务中,该模型精度达到了state of the art
    3. 实验验证了BI-LSTM-CRF具有鲁棒性并且对词嵌入的依赖较小

    3. 模型介绍

    3.1 LSTM(Long Short-Term memory)网络

    在介绍LSTM网络之前,需要先提一下RNN(Recurrent neural networks),RNN是一类用于处理序列数据的神经网络,目前在语言模型和语音识别任务上都取得了不错的结果。RNN一个显著的优势是可以利用历史信息预测当前输出,下图是一个RNN结构。

    2e91fc33b45e8d6588310cf43108bc58.png

    一个简单的RNN结构包括输入层x,隐藏层h和输出层y。上图表示的是一个NER任务,每一个单词被标注为人名、地名、机构名、其他实体与非实体,其中B-,I-标签用于标注实体的开始和中间位置,文中还举了个例子:句子EU rejects German call to boycott British lamb 应该标注为B-ORG O B-MISC O O O B-MISC O O.

    输入层表示时刻t的特征,可以是独热编码、密集向量特征或是离散特征。与前馈网络相比,RNN引入了前一个隐藏状态和当前隐藏状态的连接关系,其隐藏层和输入层的公式如下:

    U、W、V是模型参数,f(z)和g(z)分别是sigmoid函数和softmax函数。

    LSTM是在RNN的基础上提出的,是RNN的一种改进方式。当序列长度较长时,RNN容易出现梯度消失的问题,即RNN只能有短期记忆,LSTM网络通过精妙的门控制将短期记忆与长期记忆结合起来,并且一定程度上解决了梯度消失的问题。

    bd44018fe6aedfafd7fd04a1d944b756.png

    论文中LSTM的图结构上不是很清晰,我一般会用上面的图对其结构进行分析。公式如下:

    其中i表示输入门,f表示遗忘门,o表示输出门,C表示神经元状态。下图为LSTM序列标注模型:

    cbb6fc8f51341a6bfbbbc7a403343d78.png

    3.2 双向LSTM网络

    BI-LSTM是对LSTM的改进,从下图可以观察出该网络能够有效的利用过去和未来的特征。

    e83b3ac109a2fc72829b9d1d0aa3a09e.png

    3.3 CRF网络

    在预测当前标签时,有两种方法可以利用相邻的标签信息。第一种是先预测每个时间步的标签分布,然后使用类似波束的解码方式来找到最佳标签序列。最大熵分类器和MEMM属于这一种工作机制。第二种是关注整个句子而不是单个位置的信息,CRF就属于这一类。实验表明,CRF通常可以获得更高的标注精度。

    cac9dbf9f4641b7e089c6bc3f36edf1d.png

    3.4 LSTM-CRF网络

    将LSTM与CRF结合生成LSTM-CRF模型,该模型同时具有两者的优势,即具备捕捉到输入的过去特征和句子级的标签信息的能力。CRF层有状态转移矩阵作为参数,该层可以使用过去和未来的标签信息来预测当前标签,这与双向LSTM相似。文中并没有具体介绍两个部分是如何进行连接的,所以我又去搜索了一些资料:

    要了解原理,必须知道损失函数是如何构建的!!CRF层的损失函数包括了两种类型的分数:Emission score和Transition score,这两个分数是CRF层的核心概念。

    3.4.1 Emission score

    这个分数来自LSTM层,如下图所示黄色框内的即为emission score,

    被标注为B-Person的分数为1.5。

    4092edd99e6d80074e42291e10e069a2.png

    为了方便说明,每个标签可以用下表的索引值表示:

    a393bacadb75906448d325bc8cfccd03.png

    接下来会用

    表示emission score,
    表示单词的索引,
    表示标签的索引,举个栗子:

    3.4.2 Transition score

    表示转移分数,例如
    表示从标签
    转换至
    的转移分数为0.9。因此所有标签之间的转换可用转移分数矩阵表示,为了使这个矩阵更具鲁棒性,可以添加两个标签START和END,下图为转移分数矩阵的示例:

    436d6eba384049af38b3e4c6ed155e3c.png

    这里的转移分数矩阵是整个模型的参数,是通过CRF层学习得到的,并不需要手动构建

    3.4.3 Loss Function

    CRF损失函数由实际路径得分和所有可能路径的总得分组成。 在所有可能的路径中,真实路径的得分最高。假设每个可能的路径都有一个分数

    ,总共有N个可能的路径,所有路径的总分数为
    ,CRF层的损失函数可以表示为下式:

    在训练过程中,模型的参数值会不断更新,以增加真实路径得分的百分比。

    • 计算RealPath scores

    公式中的
    表示第
    条路径的分数。
    ,如果RealPath为
    “START B-Person I-Person O B-Organization O END”,则其Emission score和Transition score的计算非常简单:

    • 计算TotalPath score

    计算所有路径的分数有一个非常简单的方法,就是将每条路径的分数都算出来然后再相加,当然这个方法肯定是很低效的,时间复杂度会非常高。高效的实现方法是动态规划,我在这里就不介绍了。。。

    到这里。。模型的整个连接思路差不多就介绍完了~继续说论文

    3.5 BI-LSTM-CRF网络

    与LSTM-CRF网络相似,将双向LSTM网络和CRF网络结合起来,形成了BI-LSTM-CRF网络。 除了过去的输入特征和句子级别的标签信息,BILSTM-CRF模型可以使用将来的输入特征。这里我来补充一下我对句子级别信息的理解。。其实在3.4这个部分的图里也可以看出,即使不要CRF层,LSTM或者BI-LSTM也可以预测标签,那CRF层的作用是什么?

    我在一篇博客中看到一个很好的解释:CRF layer can learn constrains from training data.这里的constrains指的是什么呢,下面举几个例子:

    1. 句子的第一个单词的标签必须是“B-"或者"O"开头,不能是"I-"开头
    2. "B-label1 I-label2 I-label3..",这里的label1,label2和label3必须是同个标签
    3. "O I-label”是不合理的,实体的标签必须以"B-"开头
    4. ……

    简而言之,LSTM或者BI-LSTM可以学习输入到输出的映射关系,而CRF还可以学习标签之间的关系。这里的这些constrains是通过转移分数矩阵来学得的啦~继续继续

    BI-LSTM-CRF的损失函数构建是和LSTM-CRF一样的,只是LSTM-CRF的Emission score是通过LSTM得到的,而在BI-LSTM-CRF网络中是通过BI-LSTM得到的。结构如下:

    8bbd0626f02c383df39e85e6171664e7.png

    文中还介绍了模型的训练过程,其实就是批训练的方式,然后先正向,再反向。。。

    b7819bc0a6edc34f604b6c0c9f3a318e.png

    4. 实验

    4.1 数据集

    作者测试了LSTM、BI-LSTM、CRF、LSTM-CRF和BI-LSTM-CRF模型在3个nlp序列标注任务上的性能,分别选取Penn TreeBank(PTB)为POS数据集,CoNLL 2000为chunking数据集,CoNLL 2003为NER数据集。

    4.2 details

    这里有值得一提的两个小细节:第一个是输入特征,实验并不是只用word embedding后的向量作为网络的输入特征,而是在其基础上加了spelling features和context features。第二个是特征的连接方式,如下图所示,直接将输入特征与输出层连接,这个思路其实和resnet中的residual很像了,并且这种连接方式可以加快网络的训练。

    d4d78d4dc67463c7a8c278f490ea1fac.png

    4.3 Results

    8f29ad0f4d366dc94b4141da13af3940.png

    对于不同的词嵌入方式,BI-LSTM-CRF在三个任务中都获得了最好的成绩(除了Random词嵌入的POS任务上),而且相比Conv-CRF,BI-LSTM-CRF对词嵌入的依赖更小。

    接下来文中还将BI-LSTM-CRF在不同的任务中与已有的模型进行对比:

    POS:

    054eee7b598eb3aa8536b50db2dc2443.png

    chunking:

    8e6cd53f7d8fa3297a0d16341a2e7010.png

    NER:

    080c50596b711bfd6f39fd778ba80085.png

    可以看出BI-LSTM-CRF模型在不同的任务中表现优异

    5. 总结

    CRF这一块的知识点其实还蛮难理解的,这一篇论文也让我对CRF有了更深的理解~很多细节的部分其实文中并没有提到,希望我对模型结合部分的解释大家能够看得懂,有不正确的地方也请大家批评指正

    6. 参考文献

    1. 原文:https://arxiv.org/pdf/1508.01991.pdf
    2. 这篇博客将BI-LSTM-CRF模型原理解释的非常清晰:https://createmomo.github.io/2017/09/12/CRF_Layer_on_the_Top_of_BiLSTM_1/
    展开全文
  • 在以Bert为代表的大规模预训练模型出来之前,BiLSTM+CRF是解决文本序列标注问题(如分词、POS、NER和句法分析等)的baseline之一,其通过BiLSTM提取word/token-level的句法/语义特征输出,后接CRF层保证序列标注转移...

    在以Bert为代表的大规模预训练模型出来之前,BiLSTM+CRF是解决文本序列标注问题(如分词、POS、NER和句法分析等)的baseline之一,其通过BiLSTM提取word/token-level的句法/语义特征输出,后接CRF层保证序列标注转移的合法性和全局最优化。

    论文Empower Sequence Labeling with Task-Aware Neural Language Model提出了一种适用于英文语料的序列标注问题,其在BiLSTM+CRF基础上进一步引入了字符级别(char-level)的语言模型进行联合训练,通过验证,这种ML+BiLSTM+CRF的模型架构在文本序列标注问题上的效果更胜BiLSTM+CRF一筹。

    在这里插入图片描述

    如上图所示,模型的整体结构包括:

    (1)char-level的语言模型,在char-level用BiLSTM搭建LM模型,从而可以从自监督的任务语料中提取潜在特征。不同于单纯的让每个char预测下一个char的做法(可能会导致模型机械的记忆word的拼写顺序),本文在每个word最后一个char后插入一个space标识,在该处预测后一个word。

    (2)word-level的序列标准模型,每个word的embedding由预训练的词向量和上述的space标识处的输出信息进行拼接,之后接入BiLSTM+CRF进行序列的预测。

    LM-BiLSTM+CRF模型的设计和训练非常巧妙,在博主看来可以借鉴的经验和注意事项主要包括:

    (1)不同颗粒度信息的使用。文本序列标注任务原本是word-level的任务,但借助于char-level的语言模型(或者其他联合训练的任务)可以从任务文本中自监督的学习char和word间的结构和语义特征;

    (2)High-way技巧。考虑到上述语言模型与标注任务间较弱的相关性,模型在LM的输出预测以及word-embedding的拼接时,均在char上引入了high-way将char-level的输出映射到不同的语义空间,从而让底层bilstm更专注于char间通用特征的提取(当然也可以保证梯度BP过程中信息的传输),而让high-way的参数学习更偏重于标注任务;

    (3)词向量的融合和fine-tune。考虑到任务语料一般规模不大和计算耗时,论文的词向量直接选择对glove这种基于大量语料训练的词向量finetune,而非直接在任务语料上进行pre-train或者在LM-BiLSTM+CRF中直接随机初始化和联合训练。同时,除了glove,word-level的词向量还充分融合了从char-level得到的信息,从而可以让顶层的BiLSTM+CRF模型可以获取的信息。

    (4)token的对齐。一般使用BiLSTM时,我们都是直接使用token上的输出(双向concat的结果)。但在本文word-level层中进行词向量的融合,要特别注意token的对齐,对于前向的LSTM,其使用的是每个token后的隐层信息;而对于后向的LSTM,使用的则是每个token前(按照绝对位置)的信息。

    (5)训练和推断阶段的差异。模型在训练阶段需要同时考虑char-level LM的交叉熵损失,还需要考虑word-level序列标注任务的Viterbi损失。而在预测阶段,则仅仅需要知道序列标注的输出即可。因此,在char-level LM中的词表和word level中的Embedding词表可以是不相同的,即char-level LM中的词表仅需要覆盖训练样本中的word即可;而为了模型能适用于更多语料的推断,Embedding应当选择更大的词表以克服训练文本上的OOV问题。

    论文指出LM-BiLSTM+CRF模型在各序列标注任务上的效果基本都超越了BiLSTM+CRF、BiLSTM+CNN+CRF等模型。不过略可惜的,因为char-level的任务不太适用于中文任务,因此难以将该模型直接适用于中文语料上。

    展开全文
  • BiLSTM介绍

    万次阅读 2019-06-02 20:24:31
    本文简要介绍了BiLSTM的基本原理,并以句子级情感分类任务为例介绍为什么需要使用LSTM或BiLSTM进行建模。在文章的最后,我们给出在PyTorch下BiLSTM的实现代码,供读者参考。 1.2 情感分类任务 自然语言处理中情感...

    一、介绍

    1.1 文章组织

    本文简要介绍了BiLSTM的基本原理,并以句子级情感分类任务为例介绍为什么需要使用LSTM或BiLSTM进行建模。在文章的最后,我们给出在PyTorch下BiLSTM的实现代码,供读者参考。

    1.2 情感分类任务

    自然语言处理中情感分类任务是对给定文本进行情感倾向分类的任务,粗略来看可以认为其是分类任务中的一类。对于情感分类任务,目前通常的做法是先对词或者短语进行表示,再通过某种组合方式把句子中词的表示组合成句子的表示。最后,利用句子的表示对句子进行情感分类。

    举一个对句子进行褒贬二分类的例子。

    句子:我爱赛尔

    情感标签:褒义

    1.3 什么是LSTM和BiLSTM?

    LSTM的全称是Long Short-Term Memory,它是RNN(Recurrent Neural Network)的一种。LSTM由于其设计的特点,非常适合用于对时序数据的建模,如文本数据。BiLSTM是Bi-directional Long Short-Term Memory的缩写,是由前向LSTM与后向LSTM组合而成。两者在自然语言处理任务中都常被用来建模上下文信息。

    1.4 为什么使用LSTM与BiLSTM?

    将词的表示组合成句子的表示,可以采用相加的方法,即将所有词的表示进行加和,或者取平均等方法,但是这些方法没有考虑到词语在句子中前后顺序。如句子“我不觉得他好”。“不”字是对后面“好”的否定,即该句子的情感极性是贬义。使用LSTM模型可以更好的捕捉到较长距离的依赖关系。因为LSTM通过训练过程可以学到记忆哪些信息和遗忘哪些信息。

    但是利用LSTM对句子进行建模还存在一个问题:无法编码从后到前的信息。在更细粒度的分类时,如对于强程度的褒义、弱程度的褒义、中性、弱程度的贬义、强程度的贬义的五分类任务需要注意情感词、程度词、否定词之间的交互。举一个例子,“这个餐厅脏得不行,没有隔壁好”,这里的“不行”是对“脏”的程度的一种修饰,通过BiLSTM可以更好的捕捉双向的语义依赖。

    二、BiLSTM原理简介

    2.1 LSTM介绍

    2.1.1 总体框架

    LSTM模型是由时刻的输入词,细胞状态 ,临时细胞状态,隐层状态,遗忘门,记忆门,输出门组成。LSTM的计算过程可以概括为,通过对细胞状态中信息遗忘和记忆新的信息使得对后续时刻计算有用的信息得以传递,而无用的信息被丢弃,并在每个时间步都会输出隐层状态,其中遗忘,记忆与输出由通过上个时刻的隐层状态和当前输入计算出来的遗忘门,记忆门,输出门来控制。

    总体框架如图1所示。

    图1. LSTM总体框架

    2.1.2 详细介绍计算过程

    计算遗忘门,选择要遗忘的信息。

    输入:前一时刻的隐层状态,当前时刻的输入词 

    输出:遗忘门的值

    图2. 计算遗忘门

    计算记忆门,选择要记忆的信息。

    输入:前一时刻的隐层状态,当前时刻的输入词 

    输出:记忆门的值,临时细胞状态

    图3. 计算记忆门和临时细胞状态

    计算当前时刻细胞状态

    输入:记忆门的值,遗忘门的值,临时细胞状态,上一刻细胞状态

    输出:当前时刻细胞状态

    图4. 计算当前时刻细胞状态计算输出门和当前时刻隐层状态

    输入:前一时刻的隐层状态,当前时刻的输入词 ,当前时刻细胞状态

    输出:输出门的值,隐层状态

    图5. 计算输出门和当前时刻隐层状态

    最终,我们可以得到与句子长度相同的隐层状态序列{, ..., }。

    2.2 BiLSTM介绍

    前向的LSTM与后向的LSTM结合成BiLSTM。比如,我们对“我爱中国”这句话进行编码,模型如图6所示。

    图6. 双向LSTM编码句子前向的依次输入“我”,“爱”,“中国”得到三个向量{}。后向的依次输入“中国”,“爱”,“我”得到三个向量{}。最后将前向和后向的隐向量进行拼接得到{[], [], []},即{}。

    对于情感分类任务来说,我们采用的句子的表示往往是[]。因为其包含了前向与后向的所有信息,如图7所示。

    图7. 拼接向量用于情感分类

    三、BiLSTM代码实现样例

    3.1 模型搭建

    使用PyTorch搭建BiLSTM样例代码。代码地址为https://github.com/albertwy/BiLSTM/。


     

     

    参考:https://www.jiqizhixin.com/articles/2018-10-24-13

    展开全文
  • 文章目录1.Introduction2 model2.1 LSTM2.2BI-LSTMBPTT2.3 CRF2.4 LSTM-CRF参考文献 本篇论文介绍了LSTM网络、BI-LSTM网络、CRF网络、LSTM-CRF网络、BI-LSTM-CRF网络,比较将它们用于自然语言处理的性能与准确率。...
  • 本文不是RNN系列入门,而是对RNN、LSTM、BiLSTM的内部结构和输入输出做透彻的剖析。 RNN:循环神经网络 LSTM:长短期记忆网络 BiLSTM:双向长短期记忆网络 重要的先验知识: 本质上单个RNN cell是在多个时间步上...
  • 本文结合卷积神经网络(CNN)提取局部特征和双向长短记忆神经网络(BiLSTM)序列化提取全局特征的优势, 在BiLSTM隐藏层引入注意力机制(Attention机制), 提出了针对中文专利文本数据的BiLSTM_ATT_CNN组合模型....
  •  文中主要研究从MOOC课程评论中抽取评价对象和评价词的方法。将MOOC课程评论评价对象和评价词的抽取问题看作序列标注...实验结果表明,文中提出BiLSTM-CRF模型可以有效地从MOOC课程评论中抽取评价对象和评价词。
  • Attention + BiLSTM

    2020-12-20 15:48:19
    Attention + BiLSTM摘要引文基本原理模型原理图模型解释思考参考资料 摘要 暂无 引文 关系抽取从本质上看是一个多分类问题,对于这样一个问题来说最重要的工作无非特征的提取和分类模型的选择。 存在的问题及此...
  • 双向长短记忆网络(BiLSTM

    万次阅读 多人点赞 2018-10-13 17:43:23
    本文着眼于内部计算过程而不是数据原理,分别总结了RNN,BiRNN,LSTM以及BiLSTM等神经网络模型内部结构。
  • NER经典之作,2015年提出BiLSTM-CRF序列标注模型解读。 文章目录AbstractIntroductionModelsTraining procedureExperimentsDataFeaturesResults Abstract 论文以LSTM为基础,对比LSTM、BiLSTM、CRF、LSTM-CRF和Bi...
  • BILSTM-CRF

    2020-11-22 18:24:10
    介绍——在命名实体识别任务中,BiLSTM模型中CRF层的通用思想 详细的实例——通过实例来一步步展示CRF的工作原理 实现——CRF层的一步步实现过程 谁可以读本文——本文适用与NLP初级入门者或者AI其他相关领域 ...
  • BILSTM2.1 BILSTM classify2.2 BILSTM seq encode3. NER应用:NER-BILSTM-CNN4. NER应用:BERT-NER5. 总结6. 参考 Named Entity Recognition 1. NER 1.1 NER定义 命名实体识别(NER): 也称为实体识别、
  • 因此本文针对财产纠纷审判案件,提出了一种基于SVM-BiLSTM-CRF的神经网络模型.首先利用SVM筛选出包含关键命名实体的句子,然后将正确包含此类实体的句子转化为字符级向量作为输入,构建适合财产纠纷裁判文书命名实体...
  • 随着深度学习的引入,当前主流的深度学习解决方案中倾向于embedding层+bilstm层,直接让机器学习到特征,然后将学习到的特征直接输入CRF,这就避免了人工制定特征函数的繁琐。 基于规则的方法已经积累了大量的研究...
  • 本文提出基于注意力机制的双向LSTM用于负荷预测,简称BiLSTM-Attention, 提出了一种基于 Attention 机制的BiLSTM短期电力负荷预测方法,该方法将历史负荷数据作为输入,建模学习特征内部动态变化规律,并引入...
  • 为了充分挖掘气象因素对光伏出力的影响, 并有效利用深度学习技术在非线性拟合方面的优势, 本文提出了一种基于气象因素充分挖掘的双向长短期记忆(Bi-directional Long Short Term Memory, BiLSTM)网络光伏发电短期...
  • BiLSTM介绍及中文命名实体识别应用

    万次阅读 2019-01-04 11:36:48
    What-什么是LSTM和BiLSTM? LSTM:全称Long Short-Term Memory,是RNN(Recurrent Neural Network)的一种。LSTM由于其设计的特点,非常适合用于对时序数据的建模,如文本数据。 BiLSTM:Bi-directional Long ...
  • Attention in Character-Based BiLSTM-CRF for Chinese Named Entity Recognition 概述 作者提出了一种基于字符(区别于词)的中文命名实体识别方法。提取字符级特征和字形特征,字符级特征和字形特征 经过attention...
  • BILSTM-CRF-1

    千次阅读 2018-12-27 15:15:49
    BILSTM-CRF目录1 简介1.1 在我们开始前1.2 BILSTM-CRF模型1.3如果我们没有CRF层怎么办?1.4 CRF层可以从训练数据中学习约束下一节参考 声明:本系列转载自createmomo大神的博客https://createmomo.github.io,并在...
  • BiLSTM顶部的CRF层-1

    2020-06-30 13:25:30
    例如,本文[1]提出了一种BiLSTM-CRF命名实体识别模型,该模型使用词和字符嵌入。我将以本文中的模型为例来说明CRF层如何工作。 如果您不了解BiLSTM和CRF的详细信息,请记住它们是命名实体识别模型中的两个不同层。 ...
  • BiLSTM-CRF 被提出用于NER或者词性标注,效果比单纯的CRF或者lstm或者bilstm效果都要好。 根据pytorch官方指南...
  • BiLSTM-CRF 被提出用于NER或者词性标注,效果比单纯的CRF或者lstm或者bilstm效果都要好。 根据pytorch官方指南...
  • 首先使用BERT语言模型进行文本特征提取获取字粒度向量矩阵, BiLSTM用于上下文信息的提取, 同时结合CRF模型提取全局最优序列, 最终得到景点命名实体. 实验表明, 提出的模型性能提升显著, 在实际旅游领域内景点识别的...
  • 论文《Neural Architectures for Named Entity Recognition》基于词嵌入和字嵌入提出了一种BiLstm-CRF模型,本文将基于这篇论文来举例说明CRF层是如何起作用的。 如果你不知道BiLSTM和CRF,那么你只需要记住他们是...
  • 基于BILSTM-CRF的韵律预测摘要 论文题目:BLSTM-CRF Based End-to-End Prosodic Boundary Prediction with Context ...本文提出了一个与语言无关的韵律预测模型(BILSTM-CRF)。主要包括三个组分:word embedding+bi
  • 站点 小号ELF-细心BiLSTM-ÇRF瓦特第I和T ransferredËmbeddings为因果关系提取。 arXiv论文链接: : ... 在此基础上,我们提出了一种以BiLSTM-CRF模型为骨干的神经因果提取器,称为SCITE(自注意力BiLSTM-CRF传递嵌
  • 基于注意力机制的 Lattice BiLSTM 中文命名实体识别模型,曹晓菲,杨娟,最近被提出的点阵长短期记忆网络(Lattice LSTM)模型致力于将分词信息集成到长短期记忆网络(LSTM)中。然而,该模型只能从词粒度的层�

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,284
精华内容 1,713
关键字:

bilstm提出