ai命名实体识别模型_命名实体识别(医疗文本)
命名实体识别(医疗文本)
LSTM
最后更新 2020-09-02 10:34
阅读 356
最后更新 2020-09-02 10:34
阅读 356
LSTM
#简介
医疗文本是nlp处理下的一个细分方向,本文介绍了基于tensorflow 1.14.0以及使用bilstm+crf的模型来处理医疗文本的方法。全文从数据预处理开始到最终如何评估都有较为详细的介绍。
##1.数据预处理
###1.1文本获取
获取disease NER原始文献,登录全球最著名的生物医疗文献数据库pubmed:
https://pubmed.ncbi.nlm.nih.gov/term=disease[Title%2FAbstract]
用“disease [Title/Abstract]”为搜索条件,得到将近300w篇摘要,先取其中500篇尝试。
###1.2文本处理
将下载好后的文本进行预处理,因为下载好的文本里保存有作者信息等其他无关紧要的信息,我们需要使用re匹配去找到所有的摘要内容。以“PMID:”为唯一标识来匹配出所有文献的摘要信息并为每篇摘要保存为单独的list。
###1.3one-hot编码
采用onr-hot对数据集编码,首先我们需要建立word2id,也就是单词和id相匹配的字典:
python
def read_dictionary(vocab_path):
"""
:param vocab_path:
:return:
"""
vocab_path = os.path.join(vocab_path)
with open(vocab_path, 'rb') as fr:
word2id = pickle.load(fr)
print('vocab_size:', len(word2id))
fff = open('./data_path/a.txt','w',encoding='utf-8')
for i in word2id.keys():
fff.write(i+'\n')
return word2id
传入的vocab_path就是自己建立的vocab.txt。对于得到的word2id我们用来匹配所有的数据集从而生成每句话的ont-hot向量,对标签也是做类似处理得到向量,最终我们得到的格式应该是想下面一样的tuple。
eg:words:[我头疼。]
label:[O B-DIS I-DIS]
最终tuple([[0 1 2][0 1 2]])
##2.构造模型
###2.1tensorflow构造lstm+crf
因为tensorflow有构造好的crf模型,可以直接使用,那我们的工作就是建立图(从初始化开始到词嵌入到lstm到crf到解码层到计算损失并进行反向传播),图的构建如下:
```python
def build_graph(self):
self.add_placeholders_op()
self.lookup_layer_op()
self.biLSTM_layer_op()
self.softmax_pred_op()
self.loss_op()
self.trainstep_op()
self.init_op()
接下来是对各层的定义,重点关注一下lstm层的定义,需要额外的w和b参数。
python
def biLSTM_layer_op(self):
with tf.variable_scope("bi-lstm"):
cell_fw = LSTMCell(self.hidden_dim)
cell_bw = LSTMCell(self.hidden_dim)
(output_fw_seq, output_bw_seq), _ = tf.nn.bidirectional_dynamic_rnn(
cell_fw=cell_fw,
cell_bw=cell_bw,
inputs=self.word_embeddings,
sequence_length=self.sequence_lengths,
dtype=tf.float32
)
output = tf.concat([output_fw_seq, output_bw_seq], axis=-1)
output = tf.nn.dropout(output, self.dropout_pl)
with tf.variable_scope("proj"):
W = tf.get_variable(name='W',
shape=[2 * self.hidden_dim, self.num_tags],
initializer=tf.contrib.layers.xavier_initializer(),
dtype=tf.float32
)
b = tf.get_variable(name="b",
shape=[self.num_tags],
initializer=tf.zeros_initializer(),
dtype=tf.float32
)
s = tf.shape(output)
output = tf.reshape(output, [-1, 2 * self.hidden_dim])
pred = tf.matmul(output, W) + b
self.logits = tf.reshape(pred, [-1, s[1], self.num_tags])
###2.2嵌入数据
和pytorch不同的是tensorflow需要先自己定义数据的格式,然后通过相关函数来嵌入到模型里去。
数据定义如下:
def add_placeholders_op(self):
self.word_ids = tf.placeholder(tf.int32, shape=[None, None], name="word_ids")
self.labels = tf.placeholder(tf.int32, shape=[None, None], name="label")
self.sequence_lengths = tf.placeholder(tf.int32, shape=[None], name="sequence_lengths")
self.dropout_pl = tf.placeholder(tf.float32, shape=[], name="dropout")
self.lr_pl = tf.placeholder(tf.float32, shape=[], name="lr")
通过以下函数来完成词嵌入:
python
def get_feed_dict(self, seqs, labels = None, lr = None, dropout = None):
word_ids, seq_len_list = pad_sequences(seqs, pad_mark=0)
feed_dict = {self.word_ids:word_ids,
self.sequence_lengths : seq_len_list}
if labels is not None:
labels_, _ = pad_sequences(labels, pad_mark=0)
feed_dict[self.labels] = labels_
if lr is not None:
feed_dict[self.lr_pl] = lr
if dropout is not None:
feed_dict[self.dropout_pl] = dropout
return feed_dict, seq_len_list
之后就可以正常训练了。
##3.评估
###3.1评估工具
我们使用谷歌的官方文件conlleval.pl文件来进行评估,这就需要我们下载相应的pl工具软件。我们可以在 Perl 的官网下载对应平台的安装包:https://www.perl.org/get.html
下载完成后在本机命令行工具里输入perl --version
出现正确的版本号就说明可以使用了。
###3.2如果使用评估文件
首先我们要将预测的结果保存为评估软件可以识别的格式。具体的格式为
我 0 0
也就是单词 标签 预测标签的格式,只有这样才可以使用评估文件进行正确评估。
#总结
我们发现最终的f1值能够在76%左右,说明一层双向的lstm+crf在命名实体识别上还是有一定的效果,虽然效果不是特别突出,但是相较于以往已经有了很大的提升,同时本文的做法十分粗糙还有相当多的改进方法,这里提供几个思路供大家参考。
1.词向量可以做进一步的提升,如加入char embedding或者词性特征
2.模型上可以加入bert,但效果可能不一定会那么好
3.构建专业领域的字典以提高识别率
以上只是一些小的考量,如有更好的方法,欢迎大家一起来讨论的呀!
赞
讨论
500字
表情
每日优质讨论奖励 20FAI发送
每日优质讨论奖励 20FAI
删除确认
是否删除该条评论?
取消
删除
