中文命名实体识别 NER BILSTM CRF IDCNN BERT
NER(中文实体命名识别)
关键字: 中文命名实体识别 NER BILSTM CRF IDCNN BERT
摘要:对中文命名实体识别一直处于知道却未曾真正实践过的状态,此次主要是想了解和实践一些主流的中文命名实体识别的神经网络算法。通过对网上博客的阅读了解,中文命名实体识别比较主流的方法是BILSTM+CRF、IDCNN+CRF、BERT+BILSTM+CRF这几种神经网络算法,这个demo也用Keras实现了这几个算法,并且采用几个比较通用的数据集进行训练测试。这个demo是以了解和学习为目的的,所以未得出任何结论
注意:由于算力和时间的问题,对神经网络的参数未进行太多调试,所以模型现在的参数并不是最佳参数
主要库的版本
本项目是基于keras(Using TensorFlow backend)以下是主要库的版本
python = 3.6.8
keras == 2.2.4
keras_contrib == 0.0.2
keras_bert == 0.80.0
tensorflow == 1.14.0
项目目录结构
data 数据目录
具体请查看数据目录文件夹下的README文件
DataProcess 数据处理文件夹
具体请查看数据处理文件夹下的README文件
Pubilc 公共工具
path 定义文件(文件夹)的路径
utils 工具
创建log
keras的callback调类
Model 模型(总共定义了5个模型,具体结构请查看Model文件夹下的README文件)
BERT+BILST+CRF
BILSTM+Attention+CRF
BILSTM+CRF
IDCNN+CRF(1)
IDCNN+CRF(2)
log 记录数据
运行项目
注意:需要用到bert网络的需要提前下载BERT预训练模型解压到data文件夹下
直接在IDE里运行项目
直接运行 train.py文件
命令行
python train.py
运行结果
运行GPU: GeForceRTX2080Ti(GPU显存 10.0G, 算力7.5)
训练周期为15个周期,提前停止条件:2个周期验证集准确率没有提升。
BERT采用batch_size=32 因为值为64的时候所使用GPU内存不够
以下数据基于MSRA数据集,以8:2的拆分(训练集:测试集)。测试结果
模型 准确率 F1 召回率
IDCNN_CRF 0.988 0.860 0.871
IDCNN_CRF_2 0.990 0.872 0.897
BILSTM_Attention_CRF 0.987 0.850 0.848
BILSTMCRF 0.989 0.870 0.863
BERT_BILSTM_CRF 0.996 0.954 0.950
很显然BERT+BILIST+CRF的组合效果会好很多
提示:log文件夹里有每个训练周期记录的数据
数据 处理
数据文件结构
chinese_L-12_H-768_A-12 (bert官方预训练模型, 需要去官方进行下载) 下载地址
bert_config.json
bert_model.ckpt.data-00000-of-00001
bert_model.ckpt.index
bert_model.ckpt.meta
vocab.txt
data (data数据集)
train.txt
test.txt
data2
all.txt (原数据集)
train.txt (预处理分割出来的训练数据集)
test.txt (预处理分割出来的测试数据集)
MSRA 微软亚洲研究院开源数据http://www.pudn.com/Download/item/id/2435241.html
train1.txt (原数据集)
train.txt (预处理分割出来的训练数据集)
test.txt (预处理分割出来的测试数据集)
renMinRiBao 人民日报标注数据集
renmin3.txt (原数据集)
train.txt (预处理分割出来的训练数据集)
test.txt (预处理分割出来的测试数据集)
数据处理模块
此模块主要对数据data、data2、msra、人名日报 4份数据进行处理,可直接提供给模型使用。
文件构成
data2_preprocessing.py data2数据预处理文件
msra_preprocessing.py MSRA数据预处理
process_data.py 数据处理
renminribao_preprocessing.py 人民日报数据处理
vocab.py 词表
提供词表 和 tag 标签表格
词表采用 BERT 预训练文件中vocab.txt
tag 采用 O、B-PER、I-PER、B-LOC、I-LOC、B-ORG、I-ORG
文件简介
data2_preprocessing.py
data2 原文件all.txt 文件中的格式,这便是我们预处理的标准格式,所以这里只需要将文件切分成test.txt和train.txt两份数据即可。
中 B-ORG
共 I-ORG
中 I-ORG
央 I-ORG
致 O
中 B-ORG
国 I-ORG
致 I-ORG
公 I-ORG
党 I-ORG
十 I-ORG
一 I-ORG
大 I-ORG
的 O
贺 O
词 O
msra_preprocessing.py MSRA数据预处理
MAST是微软亚洲研究院开源数据
train1.txt 数据格式:
当/o 希望工程/o 救助/o 的/o 百万/o 儿童/o 成长/o 起来/o ,/o 科教/o 兴/o 国/o 蔚然成风/o 时/o ,/o 今天/o 有/o 收藏/o 价值/o 的/o 书/o 你/o 没/o 买/o ,/o 明日/o 就/o 叫/o 你/o 悔不当初/o !/o
其中需要做几个映射:
人名:
nr -> B-PER、I-PER
地名:
ns -> B-LOC、I-LOC
机构名称:
nt -> B-ORG、I-ORG
我们需要处理成以下格式:
当 O
希 O
望 O
工 O
程 O
救 O
助 O
的 O
百 O
万 O
并且切分成训练和测试数据集
process_data.py 数据处理
数据处理直接提供给模型训练使用。
数据处理有两种一种是一般的模型输入只需要一个2维数组
一般模型
inputs = ids(n_sample x max_len) 只需要一个二维输入
labels = label(n_sample x max_len x one_hot_num) (转化为noe-hot为可选项目) 三维数据
BERT
inputs =[ids(n_sample x max_len) , types(n_sample x max_len) ] 只需要2个二维输入
labels = label(n_sample x max_len x one_hot_num) (转化为noe-hot为可选项目) 三维数据
所以 一般模型的输入和bert数据输入需要进行区分
数据处理 (过程)
data(texts)(一般处理)
获取char to index 字典
把文本转化为index的形式
截取过长的文本、填充长度不够文本
data(texts)(bert数据处理)
获取char to index 字典
ids把文本转化为index的形式 type 全部填充0 因为只有一个句子
截取过长的文本
首尾进行填充(开始填充[CLS] 结尾填充 [SEP])
labels()
获取tag to index 字典
把label处理成Index的形式
截取和填充(bert需要注意填充了[CLS] [SEP])
转化成one-hot(如果需要)
最终输出(以label为one-hot为例子)
一般数据
datas.shape=(n_sample, max_len)
labels.shape=(n_sample, max_len, one_hot_len)
bert数据
datas = [ ids.shape=(n_sample, max_len), types.shape=(n_sample, max_len) ]
lables.shape=(n_sample, max_len, one_hot_len)
bert数据处理
renminribao_preprocessing.py
人名日报标注数据预处理
原数据格式 (其实这个是别人稍稍处理过的-------------- )
迈/O 向/O 充/O 满/O 希/O 望/O 的/O 新/O 世/O 纪/O —/O —/O 一/O 九/O 九/O 八/O 年/O 新/O 年/O 讲/O 话/O (/O 附/O 图/O 片/O 1/O 张/O )/O
中/B_nt 共/M_nt 中/M_nt 央/E_nt 总/O 书/O 记/O 、/O 国/O 家/O 主/O 席/O 江/B_nr 泽/M_nr 民/E_nr
(/O 一/O 九/O 九/O 七/O 年/O 十/O 二/O 月/O 三/O 十/O 一/O 日/O )/O
1/O 2/O 月/O 3/O 1/O 日/O ,/O 中/B_nt 共/M_nt 中/M_nt 央/E_nt 总/O 书/O 记/O 、/O 国/O 家/O 主/O 席/O 江/B_nr 泽/M_nr 民/E_nr 发/O 表/O 1/O 9/O 9/O 8/O 年/O 新/O 年/O 讲/O 话/O 《/O 迈/O 向/O 充/O 满/O 希/O 望/O 的/O 新/O 世/O 纪/O 》/O 。/O (/O 新/B_nt 华/M_nt 社/E_nt 记/O 者/O 兰/B_nr 红/M_nr 光/E_nr 摄/O )/O
需要做的标注映射:
人名:
B_nr -> B-PER
M_nr -> I-PER
E_nr -> I-PER
地名:
B_ns -> B-LOC
M_ns -> I-LOC
E_ns -> I-LOC
机构名称:
B_nt -> B-ORG
M_nt -> I-ORG
E_nt -> I-ORG
处理成通用的格式
迈 O
向 O
充 O
满 O
希 O
望 O
的 O
新 O
世 O
纪 O
— O
— O
vocab.py 词表
提供词表 和 tag 标签表格
词表采用 BERT 预训练文件中vocab.txt
tag 采用 O、B-PER、I-PER、B-LOC、I-LOC、B-ORG、I-ORG
模型介绍和实现
Model
在通过查阅一些博客后,在实体命名识别方面,几大主流的模型就是BILSTM+CRF、IDCNN+CRF、BERT+BILSTM+CRF。所以在此也是搭建了这几种模型分别进行测试。
注意:由于算力和时间原因,并没有对模型进行很好的调参~现在所搭建的模型并没有进行调参对比。
本demo总共采用了5个模型分别是:
BERT+BILSTM+CRF
BILSTM+Attention+CRF
BILSTM+CRF
IDCNN+CRF(1)
IDCNN+CRF(2) 与(1)的CNN的filters数和全连接层会有些区别。
BERT+LSTM+CRF
采用BERT输出直接接上LSTM再接上CRF ,并没有进行太多参数的调整。
但从网络结构上看,LSTM和全连接层和dropout部分是可以做一些调整和尝试的,由于算力和时间的问题实在没办法做太多尝试。等有机会了再做更多尝试吧。
**"""
采用 BERT + BILSTM + CRF 网络进行处理
“”"
from Public.path import path_bert_dir
from keras.models import Model
from keras.layers import Bidirectional, LSTM, Dense, Dropout
from keras.optimizers import Adam
from keras_contrib.layers import CRF
import keras_bert
import os
class BERTBILSTMCRF(object):
def __init__(self,
vocab_size: int,
n_class: int,
max_len: int = 100,
embedding_dim: int = 128,
rnn_units: int = 128,
drop_rate: float = 0.5,
):
self.vocab_size = vocab_size
self.n_class = n_class
self.max_len = max_len
self.embedding_dim = embedding_dim
self.rnn_units = rnn_units
self.drop_rate = drop_rate
self.config_path = os.path.join(path_bert_dir, 'bert_config.json')
self.check_point_path = os.path.join(path_bert_dir, 'bert_model.ckpt')
self.dict_path = os.path.join(path_bert_dir, 'vocab.txt')
def creat_model(self):
print('load bert Model start!')
model = keras_bert.load_trained_model_from_checkpoint(self.config_path,
checkpoint_file=self.check_point_path,
seq_len=self.max_len,
trainable=True)
print('load bert Model end!')
inputs = model.inputs
embedding = model.output
x = Bidirectional(LSTM(units=self.rnn_units, return_sequences=True))(embedding)
x = Dropout(self.drop_rate)(x)
x = Dense(self.n_class)(x)
self.crf = CRF(self.n_class, sparse_target=False)
x = self.crf(x)
self.model = Model(inputs=inputs, outputs=x)
self.model.summary()
self.compile()
return self.model
def compile(self):
self.model.compile(optimizer=Adam(1e-5),
loss=self.crf.loss_function,
metrics=[self.crf.accuracy])
if __name__ == '__main__':
from DataProcess.process_data import DataProcess
from keras.utils.vis_utils import plot_model
dp = DataProcess(data_type='msra', model='bert')
train_data, train_label, test_data, test_label = dp.get_data(one_hot=True)
md = BERTBILSTMCRF(vocab_size=dp.vocab_size, n_class=dp.tag_size)
md.creat_model()
model = md.model
plot_model(model, to_file='picture/BERT_BILSTM_CRF.png', show_shapes=True)
exit()
model.fit(train_data, train_label, batch_size=64, epochs=2,
validation_data=[test_data, test_label])
BILSTM+Attention+CRF
BILSTM接上self attention层在家CRF。
其中AttentionSelf层是根据大神实现的代码实现的
from keras.regularizers import L1L2
from keras.engine.topology import Layer
from keras import backend as K
from keras.models import Model
from keras.layers import Embedding, Bidirectional, LSTM, Dense, Dropout, Input
from keras_contrib.layers import CRF
class AttentionSelf(Layer):
"""
self attention,
codes from: https://mp.weixin.qq.com/s/qmJnyFMkXVjYBwoR_AQLVA
"""
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
super().__init__(**kwargs)
def build(self, input_shape):
# W、K and V
self.kernel = self.add_weight(name='WKV',
shape=(3, input_shape[2], self.output_dim),
initializer='uniform',
regularizer=L1L2(0.0000032),
trainable=True)
super().build(input_shape)
def call(self, x):
WQ = K.dot(x, self.kernel[0])
WK = K.dot(x, self.kernel[1])
WV = K.dot(x, self.kernel[2])
print("WQ.shape",WQ.shape)
print("K.permute_dimensions(WK, [0, 2, 1]).shape",K.permute_dimensions(WK, [0, 2, 1]).shape)
QK = K.batch_dot(WQ,K.permute_dimensions(WK, [0, 2, 1]))
QK = QK / (64**0.5)
QK = K.softmax(QK)
print("QK.shape",QK.shape)
V = K.batch_dot(QK,WV)
return V
def compute_output_shape(self, input_shape):
return (input_shape[0],input_shape[1],self.output_dim)
class BILSTMAttentionCRF(object):
def __init__(self,
vocab_size: int,
n_class: int,
embedding_dim: int = 128,
rnn_units: int = 128,
drop_rate: float = 0.5,
):
self.vocab_size = vocab_size
self.n_class = n_class
self.embedding_dim = embedding_dim
self.rnn_units = rnn_units
self.drop_rate = drop_rate
pass
def creat_model(self):
inputs = Input(shape=(None,))
x = Embedding(input_dim=self.vocab_size, output_dim=self.embedding_dim)(inputs)
x = Bidirectional(LSTM(units=self.rnn_units, return_sequences=True))(x)
x = AttentionSelf(300)(x)
x = Dropout(self.drop_rate)(x)
x = Dense(self.n_class)(x)
self.crf = CRF(self.n_class, sparse_target=False)
x = self.crf(x)
self.model = Model(inputs=inputs, outputs=x)
self.model.summary()
self.compile()
return self.model
def compile(self):
self.model.compile('adam',
loss=self.crf.loss_function,
metrics=[self.crf.accuracy])
if __name__ == '__main__':
from DataProcess.process_data import DataProcess
from sklearn.metrics import f1_score
import numpy as np
from keras.utils.vis_utils import plot_model
dp = DataProcess(data_type='msra')
train_data, train_label, test_data, test_label = dp.get_data(one_hot=True)
model_class = BILSTMAttentionCRF(vocab_size=dp.vocab_size, n_class=7)
model_class.creat_model()
model = model_class.model
plot_model(model, to_file='picture/BILSTM_ATTENTION_CRF.png', show_shapes=True)
exit()
model.fit(train_data, train_label, batch_size=64, epochs=2,
validation_data=[test_data, test_label])
# 对比测试数据的tag
y = model.predict(test_data)
label_indexs = []
pridict_indexs = []
num2tag = dp.num2tag()
i2w = dp.i2w()
texts = []
texts.append(f"字符\t预测tag\t原tag\n")
for i, x_line in enumerate(test_data):
for j, index in enumerate(x_line):
if index != 0:
char = i2w.get(index, ' ')
t_line = y[i]
t_index = np.argmax(t_line[j])
tag = num2tag.get(t_index, 'O')
pridict_indexs.append(t_index)
t_line = test_label[i]
t_index = np.argmax(t_line[j])
org_tag = num2tag.get(t_index, 'O')
label_indexs.append(t_index)
texts.append(f"{char}\t{tag}\t{org_tag}\n")
texts.append('\n')
f1score = f1_score(label_indexs, pridict_indexs, average='macro')
print(f"f1score:{f1score}")
""" epochs=1
- val_loss: 0.1038 - val_crf_viterbi_accuracy: 0.9664
epochs=2
- val_loss: 0.0531 - val_crf_viterbi_accuracy: 0.9819
f1score:0.7481255117004026
epochs=3
epochs=4
epochs=5
"""
exit()
with open('./pre.txt', 'w') as f:
f.write("".join(texts))**
BILSTM+CRF
from keras.models import Model
from keras.layers import Embedding, Bidirectional, LSTM, Dense, Dropout, Input
from keras_contrib.layers import CRF
class BILSTMCRF():
def __init__(self,
vocab_size: int,
n_class: int,
embedding_dim: int = 128,
rnn_units: int = 128,
drop_rate: float = 0.5,
):
self.vocab_size = vocab_size
self.n_class = n_class
self.embedding_dim = embedding_dim
self.rnn_units = rnn_units
self.drop_rate = drop_rate
def creat_model(self):
inputs = Input(shape=(None,))
x = Embedding(input_dim=self.vocab_size, output_dim=self.embedding_dim)(inputs)
x = Bidirectional(LSTM(units=self.rnn_units, return_sequences=True))(x)
x = Dropout(self.drop_rate)(x)
x = Dense(self.n_class)(x)
self.crf = CRF(self.n_class, sparse_target=False)
x = self.crf(x)
self.model = Model(inputs=inputs, outputs=x)
self.model.summary()
self.compile()
return self.model
def compile(self):
self.model.compile('adam',
loss=self.crf.loss_function,
metrics=[self.crf.accuracy])
if __name__ == '__main__':
from DataProcess.process_data import DataProcess
from sklearn.metrics import f1_score
import numpy as np
from keras.utils.vis_utils import plot_model
dp = DataProcess(data_type='msra')
train_data, train_label, test_data, test_label = dp.get_data(one_hot=True)
lstm_crf = BILSTMCRF(vocab_size=dp.vocab_size, n_class=7)
lstm_crf.creat_model()
model = lstm_crf.model
plot_model(model, to_file='picture/BILSTM_CRF.png', show_shapes=True)
exit()
model.fit(train_data, train_label, batch_size=64, epochs=2,
validation_data=[test_data, test_label])
# 对比测试数据的tag
y = model.predict(test_data)
label_indexs =[]
pridict_indexs = []
num2tag = dp.num2tag()
i2w = dp.i2w()
texts = []
texts.append(f"字符\t预测tag\t原tag\n")
for i, x_line in enumerate(test_data):
for j, index in enumerate(x_line):
if index != 0:
char = i2w.get(index, ' ')
t_line = y[i]
t_index = np.argmax(t_line[j])
tag = num2tag.get(t_index, 'O')
pridict_indexs.append(t_index)
t_line = test_label[i]
t_index = np.argmax(t_line[j])
org_tag = num2tag.get(t_index, 'O')
label_indexs.append(t_index)
texts.append(f"{char}\t{tag}\t{org_tag}\n")
texts.append('\n')
f1score = f1_score(label_indexs, pridict_indexs, average='macro')
print(f"f1score:{f1score}")
""" epochs=2
- val_loss: 0.0422 - val_crf_viterbi_accuracy: 0.9852
f1score:0.8070982542924598
"""
exit()
with open('./pre.txt', 'w') as f:
f.write("".join(texts))
IDCNN+CRF(1)
"""
IDCNN(空洞CNN) 当卷积Conv1D的参数dilation_rate>1的时候,便是空洞CNN的操作
"""
from keras.models import Model
from keras.layers import Embedding, Dense, Dropout, Input
from keras.layers import Conv1D
from keras_contrib.layers import CRF
class IDCNNCRF(object):
def __init__(self,
vocab_size: int, # 词的数量(词表的大小)
n_class: int, # 分类的类别(本demo中包括小类别定义了7个类别)
max_len: int = 100, # 最长的句子最长长度
embedding_dim: int = 128, # 词向量编码长度
drop_rate: float = 0.5, # dropout比例
):
self.vocab_size = vocab_size
self.n_class = n_class
self.max_len = max_len
self.embedding_dim = embedding_dim
self.drop_rate = drop_rate
pass
def creat_model(self):
"""
本网络的机构采用的是,
Embedding
直接进行2个常规一维卷积操作
接上一个空洞卷积操作
连接全连接层
最后连接CRF层
kernel_size 采用2、3、4
cnn 特征层数: 64、128、128
"""
inputs = Input(shape=(self.max_len,))
x = Embedding(input_dim=self.vocab_size, output_dim=self.embedding_dim)(inputs)
x = Conv1D(filters=64,
kernel_size=3,
activation='relu',
padding='same',
dilation_rate=1)(x)
x = Conv1D(filters=128,
kernel_size=3,
activation='relu',
padding='same',
dilation_rate=1)(x)
x = Conv1D(filters=128,
kernel_size=3,
activation='relu',
padding='same',
dilation_rate=2)(x)
x = Dropout(self.drop_rate)(x)
x = Dense(self.n_class)(x)
self.crf = CRF(self.n_class, sparse_target=False)
x = self.crf(x)
self.model = Model(inputs=inputs, outputs=x)
self.model.summary()
self.compile()
return self.model
def compile(self):
self.model.compile('adam',
loss=self.crf.loss_function,
metrics=[self.crf.accuracy])
if __name__ == '__main__':
from DataProcess.process_data import DataProcess
from sklearn.metrics import f1_score
import numpy as np
from keras.utils.vis_utils import plot_model
dp = DataProcess(max_len=100, data_type='msra')
train_data, train_label, test_data, test_label = dp.get_data(one_hot=True)
model_class = IDCNNCRF(vocab_size=dp.vocab_size, n_class=7, max_len=100)
model_class.creat_model()
model = model_class.model
plot_model(model, to_file='picture/IDCNN_CRF.png', show_shapes=True)
exit()
model.fit(train_data, train_label, batch_size=64, epochs=5,
validation_data=[test_data, test_label])
# 对比测试数据的tag
y = model.predict(test_data)
label_indexs = []
pridict_indexs = []
num2tag = dp.num2tag()
i2w = dp.i2w()
texts = []
texts.append(f"字符\t预测tag\t原tag\n")
for i, x_line in enumerate(test_data):
for j, index in enumerate(x_line):
if index != 0:
char = i2w.get(index, ' ')
t_line = y[i]
t_index = np.argmax(t_line[j])
tag = num2tag.get(t_index, 'O')
pridict_indexs.append(t_index)
t_line = test_label[i]
t_index = np.argmax(t_line[j])
org_tag = num2tag.get(t_index, 'O')
label_indexs.append(t_index)
texts.append(f"{char}\t{tag}\t{org_tag}\n")
texts.append('\n')
f1score = f1_score(label_indexs, pridict_indexs, average='macro')
print(f"f1score:{f1score}")
""" epochs=1
- val_loss: 0.0518 - val_crf_viterbi_accuracy: 0.9830
epochs=2
- val_loss: 0.0386 - val_crf_viterbi_accuracy: 0.9867
epochs=3
- val_loss: 0.0338 - val_crf_viterbi_accuracy: 0.9880
epochs=4
- val_loss: 0.0304 - val_crf_viterbi_accuracy: 0.9889
epochs=5
- val_loss: 0.0283 - val_crf_viterbi_accuracy: 0.9890
f1score:0.8564147211248077
"""
exit()
with open('./pre.txt', 'w') as f:
f.write("".join(texts))
IDCNN+CRF(2)
"""
IDCNN(空洞CNN) 当卷积Conv1D的参数dilation_rate>1的时候,便是空洞CNN的操作
"""
from keras.models import Model
from keras.layers import Embedding, Dense, Dropout, Input, Conv1D
from keras_contrib.layers import CRF
class IDCNNCRF2():
def __init__(self,
vocab_size: int, # 词的数量(词表的大小)
n_class: int, # 分类的类别(本demo中包括小类别定义了7个类别)
max_len: int = 100, # 最长的句子最长长度
embedding_dim: int = 128, # 词向量编码长度
drop_rate: float = 0.5, # dropout比例
):
self.vocab_size = vocab_size
self.n_class = n_class
self.max_len = max_len
self.embedding_dim = embedding_dim
self.drop_rate = drop_rate
def creat_model(self):
"""
本网络的机构采用的是,
Embedding
直接进行2个常规一维卷积操作
接上一个空洞卷积操作
连接2个全连接层
最后连接CRF层
kernel_size 采用2、3、4
cnn 特征层数: 256、256、512
"""
inputs = Input(shape=(self.max_len,))
x = Embedding(input_dim=self.vocab_size, output_dim=self.embedding_dim)(inputs)
x = Conv1D(filters=256,
kernel_size=2,
activation='relu',
padding='same',
dilation_rate=1)(x)
x = Conv1D(filters=256,
kernel_size=3,
activation='relu',
padding='same',
dilation_rate=1)(x)
x = Conv1D(filters=512,
kernel_size=4,
activation='relu',
padding='same',
dilation_rate=2)(x)
x = Dropout(self.drop_rate)(x)
x = Dense(1024)(x)
x = Dropout(self.drop_rate)(x)
x = Dense(self.n_class)(x)
self.crf = CRF(self.n_class, sparse_target=False)
x = self.crf(x)
self.model = Model(inputs=inputs, outputs=x)
self.model.summary()
self.compile()
return self.model
def compile(self):
self.model.compile('adam',
loss=self.crf.loss_function,
metrics=[self.crf.accuracy])
if __name__ == '__main__':
from DataProcess.process_data import DataProcess
from sklearn.metrics import f1_score
import numpy as np
from keras.utils.vis_utils import plot_model
dp = DataProcess(max_len=100, data_type='msra')
train_data, train_label, test_data, test_label = dp.get_data(one_hot=True)
lstm_crf = IDCNNCRF2(vocab_size=dp.vocab_size, n_class=7, max_len=100)
lstm_crf.creat_model()
model = lstm_crf.model
plot_model(model, to_file='picture/IDCNN_CRF_2.png', show_shapes=True)
exit()
model.fit(train_data, train_label, batch_size=64, epochs=5,
validation_data=[test_data, test_label])
# 对比测试数据的tag
y = model.predict(test_data)
label_indexs = []
pridict_indexs = []
num2tag = dp.num2tag()
i2w = dp.i2w()
texts = []
texts.append(f"字符\t预测tag\t原tag\n")
for i, x_line in enumerate(test_data):
for j, index in enumerate(x_line):
if index != 0:
char = i2w.get(index, ' ')
t_line = y[i]
t_index = np.argmax(t_line[j])
tag = num2tag.get(t_index, 'O')
pridict_indexs.append(t_index)
t_line = test_label[i]
t_index = np.argmax(t_line[j])
org_tag = num2tag.get(t_index, 'O')
label_indexs.append(t_index)
texts.append(f"{char}\t{tag}\t{org_tag}\n")
texts.append('\n')
f1score = f1_score(label_indexs, pridict_indexs, average='macro')
print(f"f1score:{f1score}")
""" epochs=1
- val_loss: 0.0421 - val_crf_viterbi_accuracy: 0.9858
epochs=2
- val_loss: 0.0304 - val_crf_viterbi_accuracy: 0.9892
epochs=3
- val_loss: 0.0269 - val_crf_viterbi_accuracy: 0.9898
epochs=4
- val_loss: 0.0267 - val_crf_viterbi_accuracy: 0.9899
epochs=5
- val_loss: 0.0231 - val_crf_viterbi_accuracy: 0.9898
f1score:0.871357911057253
"""
exit()
with open('./pre.txt', 'w') as f:
f.write("".join(texts))
- 点赞
- 收藏
- 关注作者
评论(0)