浅谈知识图谱------天池下的瑞金医院MMC人工智能辅助构建知识图谱

  • 前言
  • 数据说明
  • 问题
  • 网络模型和效果展示
  • 代码
    • 实体的定义和处理
    • 句子的切分和处理
    • 代码和数据集:

前言

知识图谱是个很大的概念,可惜我没数据,借用瑞金医院的数据集,来谈下命名识别。

数据说明


数据使用 brat 进行标注,每个 .txt 文件对应一个 .ann 标注文件。
txt文件对应一篇糖尿病下的论文
ann文件有3列,以 \t 分隔,第一列为实体编号,第二列为实体类别,第三列为实体位置信息。实体位置信息共3列, 以空格分隔,分别代表实体的开始位置,结束位置,实体文本

问题

这里我引用冠军队伍的代码,他们当时所面临的问题如下:
(1)他们是对一篇文章去做实体标注,文章的字数可能很长(几千到上万字),不可能直接输入到一个 RNN 中;
(2)样本中文章可能由于格式转换的一些原因,没有一个很好的句子边界,甚至一个词汇当中存在换行符 \n 或者句号 的情况,因此用换行 符或者句号去切割句子不一定合适。
(3)如果按照固定窗口大小的滑动窗口去切句子,刚好把一个实体切分成2个部分怎么办?
中文文本,面临是否要分词的选择;
下面是他们的解决方案:


网络模型和效果展示

网络模型为了便于上下文的关联采用了双向的lstm,为了使滑动的时候不丢到相关联的词语采用了一层CRF,作为最后最后一层的预测。

代码

代码主要分为三个部分,实体的定义和处理、句子的切分和处理、模型的搭建,除此之外还有预测评估的部分

实体的定义和处理

class Entity(object):def __init__(self, ent_id, category, start_pos, end_pos, text):self.ent_id = ent_idself.category = categoryself.start_pos = start_posself.end_pos = end_posself.text = textdef __gt__(self, other):return self.start_pos > other.start_posdef offset(self, offset_val):return Entity(self.ent_id,self.category,self.start_pos + offset_val,self.end_pos + offset_val,self.text)def __repr__(self):return '({}, {}, ({}, {}), {})'.format(self.ent_id,self.category,self.start_pos,self.end_pos,self.text)
class Entities(object):def __init__(self, ents):self.ents = sorted(ents)self.ent_dict = dict(zip([ent.ent_id for ent in ents], ents))def __getitem__(self, key):if isinstance(key, int) or isinstance(key, slice):return self.ents[key]else:return self.ent_dict.get(key, None)def offset(self, offset_val):ents = [ent.offset(offset_val) for ent in self.ents]return Entities(ents)def vectorize(self, vec_len, cate2idx):res_vec = np.zeros(vec_len, dtype=int)for ent in self.ents:res_vec[ent.start_pos: ent.end_pos] = cate2idx[ent.category]return res_vecdef find_entities(self, start_pos, end_pos):res = []for ent in self.ents:if ent.start_pos > end_pos:breaksp, ep = (max(start_pos, ent.start_pos), min(end_pos, ent.end_pos))if ep > sp:new_ent = Entity(ent.ent_id, ent.category, sp, ep, ent.text[:(ep - sp)])res.append(new_ent)return Entities(res)def merge(self):merged_ents = []for ent in self.ents:if len(merged_ents) == 0:merged_ents.append(ent)elif (merged_ents[-1].end_pos == ent.start_pos andmerged_ents[-1].category == ent.category):merged_ent = Entity(ent_id=merged_ents[-1].ent_id,category=ent.category,start_pos=merged_ents[-1].start_pos,end_pos=ent.end_pos,text=merged_ents[-1].text + ent.text)merged_ents[-1] = merged_entelse:merged_ents.append(ent)return Entities(merged_ents)

句子的切分和处理

data_dir = 'ruijin_round1_train2_20181022/'
ent2idx = dict(zip(ENTITIES, range(1, len(ENTITIES) + 1)))
idx2ent = dict([(v, k) for k, v in ent2idx.items()])
# print(idx2ent)
docs = Documents(data_dir=data_dir)
# ShuffleSplit() 随机排列交叉验证,生成一个用户给定数量的独立的训练/测试数据划分。样例首先被打散然后划分为一对训练测试集合。
# n_splits:划分训练集、测试集的次数,默认为10
# test_size: 测试集比例或样本数量,
# random_state:随机种子值,默认为None,可以通过设定明确的random_state,使得伪随机生成器的结果可以重复。rs = ShuffleSplit(n_splits=1, test_size=20, random_state=2018)
train_doc_ids, test_doc_ids = next(rs.split(docs))
train_docs, test_docs = docs[train_doc_ids], docs[test_doc_ids]num_cates = max(ent2idx.values()) + 1
sent_len = 64
vocab_size = 3000
emb_size = 100
sent_pad = 10
sent_extrator = SentenceExtractor(window_size=sent_len, pad_size=sent_pad)
train_sents = sent_extrator(train_docs)
test_sents = sent_extrator(test_docs)train_data = Dataset(train_sents, cate2idx=ent2idx)
train_data.build_vocab_dict(vocab_size=vocab_size)test_data = Dataset(test_sents, word2idx=train_data.word2idx, cate2idx=ent2idx)
class Sentence(object):"""定义被切分的句子的类:text:句子的文本doc_id:句子所述文档idoffset:句子相对文档的偏移距离ents:句子包含的实体列表"""def __init__(self, doc_id, offset, text, ents):self.text = textself.doc_id = doc_idself.offset = offsetself.ents = entsdef __repr__(self):"""内部魔法函数:以text显示类:return:"""return self.textdef __gt__(self, other):#内部魔法函数:按类的offset偏移距离对类进行排序return self.offset > other.offsetdef __getitem__(self, key):"""内部魔法函数:预测结果评估时,去除句子两端延申的部分:param key::return:"""if isinstance(key, int):return self.text[key]if isinstance(key, slice):text = self.text[key]start = key.start or 0stop = key.stop or len(self.text)if start < 0:start += len(self.text)if stop < 0:stop += len(self.text)#改变实体相对于句子的偏移距离ents = self.ents.find_entities(start, stop).offset(-start)#改变句子相对于文档的偏移距离offset = self.offset + startreturn Sentence(self.doc_id, offset, text, ents)def _repr_html_(self):"""内部函数:网页显示不同的实体以不同的颜色区分:return:"""ents = []for ent in self.ents:ents.append({'start': ent.start_pos,'end': ent.end_pos,'label': ent.category})ex = {'text': self.text, 'ents': ents, 'title': None, 'settings': {}}return displacy.render(ex,style='ent',options={'colors': COLOR_MAP},manual=True,minify=True)class SentenceExtractor(object):#句子切分器,窗口为windows,两端分别延申pad_sizedef __init__(self, window_size=50, pad_size=10):self.window_size = window_sizeself.pad_size = pad_sizedef extract_doc(self, doc):#句子切分函数,切分的时候注意每个切分的句子相对于文档的偏移距离,预测的时候还需要还原num_sents = math.ceil(len(doc.text) / self.window_size)doc = doc.pad(pad_left=self.pad_size, pad_right=num_sents * self.window_size - len(doc.text) + self.pad_size)sents = []for cur_idx in range(self.pad_size, len(doc.text) - self.pad_size, self.window_size):sent_text = doc.text[cur_idx - self.pad_size: cur_idx + self.window_size + self.pad_size]ents = []for ent in doc.ents.find_entities(start_pos=cur_idx - self.pad_size,end_pos=cur_idx + self.window_size + self.pad_size):ents.append(ent.offset(-cur_idx + self.pad_size))sent = Sentence(doc.doc_id,offset=cur_idx - 2 * self.pad_size,text=sent_text,ents=Entities(ents))sents.append(sent)return sentsdef __call__(self, docs):#内部函数:将类当成函数形式的调用sents = []for doc in docs:sents += self.extract_doc(doc)return sents

模型的构建

def build_lstm_crf_model(num_cates, seq_len, vocab_size, model_opts=dict()):opts = {'emb_size': 256,'emb_trainable': True,'emb_matrix': None,'lstm_units': 256,'optimizer': keras.optimizers.Adam()}opts.update(model_opts)input_seq = Input(shape=(seq_len,), dtype='int32')if opts.get('emb_matrix') is not None:embedding = Embedding(vocab_size, opts['emb_size'], weights=[opts['emb_matrix']],trainable=opts['emb_trainable'])else:embedding = Embedding(vocab_size, opts['emb_size'])x = embedding(input_seq)lstm = LSTM(opts['lstm_units'], return_sequences=True)x = Bidirectional(lstm)(x)crf = CRF(num_cates, sparse_target=True)output = crf(x)model = Model(input_seq, output)model.compile(opts['optimizer'], loss=crf.loss_function, metrics=[crf.accuracy])return model

代码和数据集:

我把代码和数据集打包了
链接:https://pan.baidu.com/s/1mvjPuoGRChTpIqCYrLB6VA
提取码:z9tz
复制这段内容后打开百度网盘手机App,操作更方便哦–来自百度网盘超级会员V3的分享

天池下的瑞金医院MMC人工智能辅助构建知识图谱相关推荐

  1. C.3 知识图谱项目实战(一):瑞金医院MMC人工智能辅助构建知识图谱--初赛实体识别

    NLP专栏简介:数据增强.智能标注.意图识别算法|多分类算法.文本信息抽取.多模态信息抽取.可解释性分析.性能调优.模型压缩算法等 专栏详细介绍:[NLP专栏简介:数据增强.智能标注.意图识别算法|多 ...

  2. 阿里云天池大赛赛题(深度学习)——人工智能辅助构建知识图谱(完整代码)

    # 导入所需文件 import numpy as np from sklearn.model_selection import ShuffleSplit from data_utils import ...

  3. AI辅助构建知识图谱:关系抽取

    向AI转型的程序员都关注了这个号

  4. 中医与人工智能-基于Protégé构建知识图谱

    文章目录 中医与人工智能-基于Protégé构建知识图谱 本文内容 中医数据获取 中医数据处理 Protégé介绍与基本使用 基于Protégé构建知识图谱 通过protégé创建类的层次关系 通过p ...

  5. 研讨会 | “人工智能与行业知识图谱技术实战”研讨会

    人工智能时代 2017年7月,国务院<新一代人工智能发展规划>明确提出"建立新一代人工智能关键共性技术体系"的重点任务和设立"新一代人工智能重大科技项目以及& ...

  6. 【知识图谱】Neo4j的基本使用及思知1.4亿三元组数据构建知识图谱

    目录 0.前言 1.Neo4j的基本使用 1.1 下载和安装Neo4j 1.2 Neo4j配置 1.2.1 核心数据文件的位置 1.2.2 安全验证,默认是启用的 1.2.3 配置JAVA 堆内存的大 ...

  7. 当可解释人工智能遇上知识图谱

    来源:知乎-机器学习小谈地址:https://zhuanlan.zhihu.com/p/386458680本文约6100字,建议阅读10分钟 可解释人工智能遇上知识图谱. 在科学研究中,从方法论上来讲 ...

  8. 自底向上构建知识图谱全过程

    http://www.sohu.com/a/245246344_160850 阿里妹导读:知识图谱的构建技术主要有自顶向下和自底向上两种.其中自顶向下构建是指借助百科类网站等结构化数据源,从高质量数据 ...

  9. 通俗讲解自底向上构建知识图谱全过程

    知识图谱的基础介绍,供学习参考. 转载自:https://mp.weixin.qq.com/s/7cBbtqvPQUVrLZUNDx8XDQ 知识图谱的构建技术主要有自顶向下和自底向上两种.其中自顶向 ...

最新文章

  1. php用命令查mysql_phpMySQL命令大全总结
  2. Timer 和TimerTask 的定时任务入门
  3. 19-6/24作业:求四位会员卡号之和
  4. Spring @Autowired 注入为 null
  5. thinkphp 5 stdClass Call to undefined
  6. vue使用Google Map
  7. Windows 7 完美安装 Visual C++ 6.0
  8. objective-c 编写规范_Objective-c成员变量的定义方式?如何写才规范?
  9. NOIP模拟测试26「嚎叫响彻在贪婪的机房·主仆见证了 Hobo 的离别·征途堆积出友情的永恒」...
  10. 测试是否支持跨域_浅谈跨域威胁与安全
  11. 15个著名的设计心理学原理以及在设计中的应用
  12. Joseph_Circle(约瑟夫环)
  13. 阿里战微信!20 亿元扶持小程序开发者
  14. Codeforces Round #366 (Div. 1):Ant Man(贪心)
  15. 专访当当网张亮:深度解读分布式作业调度框架elastic-job
  16. xss.haozi.me练习通关
  17. 动漫制作要学计算机吗,学习动漫制作需要掌握哪些电脑软件?
  18. Word如何对齐冒号,想把几行的冒号对齐该怎么设置?
  19. NOKOV度量动捕软件教程(5):数据处理
  20. Linux系统中rpm命令用法详解

热门文章

  1. 阿里云国际版ECS,虚拟主机和VPS托管之间有什么区别呢?
  2. JavaScript数组去重方法整理
  3. 重构数据-Self Encapsulate Field自封装值域一
  4. 我的新浪技术博客地址
  5. 【第六弹】经典移植至IOS端、经典合集
  6. 英伟达显卡 NVIDIA
  7. 帝国CMS备份出现数据恢复不完整的问题
  8. centos7利用yum安装mondb4.0
  9. jQuery Validate密码验证的基本使用
  10. 华为ultrapath命令linux,华为UltraPath多路径软件配置ASM磁盘