BiLSTM+CRF(Keras)

数据集为玻森命名实体数据。

目前代码流程跑通了,后续再进行优化。

项目地址:https://github.com/cyandn/practice/tree/master/NER

步骤:

数据预处理:

def data_process():
    zh_punctuation = [‘,‘, ‘。‘, ‘?‘, ‘;‘, ‘!‘, ‘……‘]

    with open(‘data/BosonNLP_NER_6C_process.txt‘, ‘w‘, encoding=‘utf8‘) as fw:
        with open(‘data/BosonNLP_NER_6C.txt‘, encoding=‘utf8‘) as fr:
            for line in fr.readlines():
                line = ‘‘.join(line.split()).replace(‘\\n‘, ‘‘)  # 去除文本中的空字符

                i = 0
                while i < len(line):
                    word = line[i]

                    if word in zh_punctuation:
                        fw.write(word + ‘/O‘)
                        fw.write(‘\n‘)
                        i += 1
                        continue

                    if word == ‘{‘:
                        i += 2
                        temp = ‘‘
                        while line[i] != ‘}‘:
                            temp += line[i]
                            i += 1
                        i += 2

                        type_ne = temp.split(‘:‘)
                        etype = type_ne[0]
                        entity = type_ne[1]
                        fw.write(entity[0] + ‘/B_‘ + etype + ‘ ‘)
                        for item in entity[1:]:
                            fw.write(item + ‘/I_‘ + etype + ‘ ‘)
                    else:
                        fw.write(word + ‘/O ‘)
                        i += 1

加载数据:

def load_data(self):
    maxlen = 0

    with open(‘data/BosonNLP_NER_6C_process.txt‘, encoding=‘utf8‘) as f:
        for line in f.readlines():
            word_list = line.strip().split()
            one_sample, one_label = zip(
                *[word.rsplit(‘/‘, 1) for word in word_list])
            one_sample_len = len(one_sample)
            if one_sample_len > maxlen:
                maxlen = one_sample_len
            one_sample = ‘ ‘.join(one_sample)
            one_label = [config.classes[label] for label in one_label]
            self.total_sample.append(one_sample)
            self.total_label.append(one_label)

    tok = Tokenizer()
    tok.fit_on_texts(self.total_sample)
    self.vocabulary = len(tok.word_index) + 1
    self.total_sample = tok.texts_to_sequences(self.total_sample)

    self.total_sample = np.array(pad_sequences(
        self.total_sample, maxlen=maxlen, padding=‘post‘, truncating=‘post‘))
    self.total_label = np.array(pad_sequences(
        self.total_label, maxlen=maxlen, padding=‘post‘, truncating=‘post‘))[:, :, None]

    print(‘total_sample shape:‘, self.total_sample.shape)
    print(‘total_label shape:‘, self.total_label.shape)

    X_train, self.X_test, y_train, self.y_test = train_test_split(
        self.total_sample, self.total_label, test_size=config.proportion[‘test‘], random_state=666)
    self.X_train, self.X_val, self.y_train, self.y_val = train_test_split(
        X_train, y_train, test_size=config.proportion[‘val‘], random_state=666)

    print(‘X_train shape:‘, self.X_train.shape)
    print(‘y_train shape:‘, self.y_train.shape)
    print(‘X_val shape:‘, self.X_val.shape)
    print(‘y_val shape:‘, self.y_val.shape)
    print(‘X_test shape:‘, self.X_test.shape)
    print(‘y_test shape:‘, self.y_test.shape)

    del self.total_sample
    del self.total_label

构建模型:

def build_model(self):
    model = Sequential()

    model.add(Embedding(self.vocabulary, 100, mask_zero=True))
    model.add(Bidirectional(LSTM(64, return_sequences=True)))
    model.add(CRF(len(config.classes), sparse_target=True))
    model.summary()

    opt = Adam(lr=config.hyperparameter[‘learning_rate‘])
    model.compile(opt, loss=crf_loss, metrics=[crf_viterbi_accuracy])

    self.model = model

训练:

def train(self):
    save_dir = os.path.join(os.getcwd(), ‘saved_models‘)
    model_name = ‘{epoch:03d}_{val_crf_viterbi_accuracy:.4f}.h5‘
    if not os.path.isdir(save_dir):
        os.makedirs(save_dir)

    tensorboard = TensorBoard()
    checkpoint = ModelCheckpoint(os.path.join(save_dir, model_name),
                                    monitor=‘val_crf_viterbi_accuracy‘,
                                    save_best_only=True)
    lr_reduce = ReduceLROnPlateau(
        monitor=‘val_crf_viterbi_accuracy‘, factor=0.2, patience=10)

    self.model.fit(self.X_train, self.y_train,
                    batch_size=config.hyperparameter[‘batch_size‘],
                    epochs=config.hyperparameter[‘epochs‘],
                    callbacks=[tensorboard, checkpoint, lr_reduce],
                    validation_data=[self.X_val, self.y_val])

预测:

def evaluate(self):
    best_model_name = sorted(os.listdir(‘saved_models‘)).pop()
    self.best_model = load_model(os.path.join(‘saved_models‘, best_model_name),
                                    custom_objects={‘CRF‘: CRF,
                                                    ‘crf_loss‘: crf_loss,
                                                    ‘crf_viterbi_accuracy‘: crf_viterbi_accuracy})
    scores = self.best_model.evaluate(self.X_test, self.y_test)
    print(‘test loss:‘, scores[0])
    print(‘test accuracy:‘, scores[1])

参考:

https://zhuanlan.zhihu.com/p/44042528

https://blog.csdn.net/buppt/article/details/81180361

https://github.com/stephen-v/zh-NER-keras

http://www.voidcn.com/article/p-pykfinyn-bro.html

原文地址:https://www.cnblogs.com/cyandn/p/11075076.html

时间: 2024-10-17 19:44:53

BiLSTM+CRF(Keras)的相关文章

转:TensorFlow入门(六) 双端 LSTM 实现序列标注(分词)

http://blog.csdn.net/Jerr__y/article/details/70471066 欢迎转载,但请务必注明原文出处及作者信息. @author: huangyongye @creat_date: 2017-04-19 前言 本例子主要介绍如何使用 TensorFlow 来一步一步构建双端 LSTM 网络(听名字就感觉好腻害的样子),并完成序列标注的问题.先声明一下,本文中采用的方法主要参考了[中文分词系列] 4. 基于双向LSTM的seq2seq字标注这篇文章.该文章用

数据挖掘笔试面试(9)

[校招面经]机器学习与数据挖掘常见面试题整理 part4 2018年07月25日 12:43:21 稻蛙 阅读数:149 五十一.Hinge loss Hinge loss 的叫法来源于其损失函数的图形,为一个折线,通用的函数表达式为: L(mi)=max(0,1−mi(w)) 表示如果被正确分类,损失是0,否则损失就是 1−mi(w) . 在机器学习中,Hing 可以用来解 间距最大化 的问题,最有代表性的就是SVM 问题,最初的SVM 优化函数如下:argminw,ζ12||w||2+C∑i

NLP —— 图模型(二)条件随机场(Conditional random field,CRF)

本文简单整理了以下内容: (一)马尔可夫随机场(Markov random field,无向图模型)简单回顾 (二)条件随机场(Conditional random field,CRF) 这篇写的非常浅,基于 [1] 和 [5] 梳理.感觉 [1] 的讲解很适合完全不知道什么是CRF的人来入门.如果有需要深入理解CRF的需求的话,还是应该仔细读一下几个英文的tutorial,比如 [4] . (一)马尔可夫随机场简单回顾 概率图模型(Probabilistic graphical model,P

DeepLearning tutorial(7)深度学习框架Keras的使用-进阶

上一篇文章总结了Keras的基本使用方法,相信用过的同学都会觉得不可思议,太简洁了.十多天前,我在github上发现这个框架的时候,关注Keras的人还比较少,这两天无论是github还是微薄,都看到越来越多的人关注和使用Keras.所以这篇文章就简单地再介绍一下Keras的使用,方便各位入门. 主要包括以下三个内容: 训练CNN并保存训练好的模型. 将CNN用于特征提取,用提取出来的特征训练SVM. 可视化CNN卷积层后的特征图. 仍然以Mnist为例,代码中用的Mnist数据到这里下载 ht

Keras 学习之旅(一)

软件环境(Windows): Visual Studio Anaconda CUDA MinGW-w64 conda install -c anaconda mingw libpython CNTK TensorFlow-gpu Keras-gpu Theano MKL CuDNN 参考书籍:谢梁 , 鲁颖 , 劳虹岚.Keras快速上手:基于Python的深度学习实战 Keras 简介 Keras 这个名字来源于希腊古典史诗<奥德赛>的牛角之门(Gate of Horn):Those tha

深度学习(六)基Tensorflow、Theano的keras常用函数学习

原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9769301.html Keras是什么? Keras:基于Theano和TensorFlow的深度学习库 Keras是一个高层神经网络API,Keras由纯Python编写而成并基Tensorflow.Theano以及CNTK后端.Keras 为支持快速实验而生,能够把你的idea迅速转换为结果,如果你有如下需求,请选择Keras: 简易和快速的原型设计(keras具有高度模块化,极简,和可

keras 序贯(Sequential)模型 常见设置

最近看了一些例子,keras在预测方面,Sequential 常见搭配如下 情感分析 embedding -> lstm -> dense embedding 主要用于词的one-hot 编码, lstm 主要用于长距离记忆, dense 是全连接. CTR 预测或者序列预测 lstm -> dense 就足够了, 当然前面可以多个lstm. loss (目标函数)方面 loss='mean_squared_error' (均方误差), 或者 loss='mae'(绝对值均差) 两者选择

文本分类实战(五)—— Bi-LSTM + Attention模型

1 大纲概述 文本分类这个系列将会有十篇左右,包括基于word2vec预训练的文本分类,与及基于最新的预训练模型(ELMo,BERT等)的文本分类.总共有以下系列: word2vec预训练词向量 textCNN 模型 charCNN 模型 Bi-LSTM 模型 Bi-LSTM + Attention 模型 RCNN 模型 Adversarial LSTM 模型 Transformer 模型 ELMo 预训练模型 BERT 预训练模型 所有代码均在textClassifier仓库中,觉得有帮助,请

NLP入门(八)使用CRF++实现命名实体识别(NER)

CRF与NER简介 ??CRF,英文全称为conditional random field, 中文名为条件随机场,是给定一组输入随机变量条件下另一组输出随机变量的条件概率分布模型,其特点是假设输出随机变量构成马尔可夫(Markov)随机场. ??较为简单的条件随机场是定义在线性链上的条件随机场,称为线性链条件随机场(linear chain conditional random field). 线性链条件随机场可以用于序列标注等问题,而本文需要解决的命名实体识别(NER)任务正好可通过序列标注方