头图

从零开始搭建医药领域知识图谱实现智能问答与分析服务(含码源):含Neo4j基于垂直网站数据的医药知识图谱构建、医药知识图谱的自动问答等

项目介绍

关于知识图谱概念性的介绍就不在此赘述。目前知识图谱在各个领域全面开花,如教育、医疗、司法、金融等。本项目立足医药领域,以垂直型医药网站为数据来源,以疾病为核心,构建起一个包含7类规模为4.4万的知识实体,11类规模约30万实体关系的知识图谱。

  • 本项目将包括以下两部分的内容:
    1) 基于垂直网站数据的医药知识图谱构建
    2) 基于医药知识图谱的自动问答

项目效果展示

以下两图是实际问答运行过程中的截图:

  • 项目运行方式

    1. 配置要求:要求配置neo4j数据库及相应的python依赖包。neo4j数据库用户名密码记住,并修改相应文件。
    2. 知识图谱数据导入:python build_medicalgraph.py,导入的数据较多,估计需要几个小时。
    3. 启动问答:python chat_graph.py

1.医疗知识图谱构建

1.1 业务驱动的知识图谱构建框架

1.2 脚本目录

  • prepare_data/datasoider.py:网络资讯采集脚本
  • prepare_data/datasoider.py:网络资讯采集脚本
  • prepare_data/max_cut.py:基于词典的最大向前/向后切分脚本
  • build_medicalgraph.py:知识图谱入库脚本   

1.3 医药领域知识图谱规模

1.3.1 neo4j图数据库存储规模

1.3.2 知识图谱实体类型

实体类型中文含义实体数量举例
Check诊断检查项目3,353支气管造影;关节镜检查
Department医疗科目54整形美容科;烧伤科
Disease疾病8,807血栓闭塞性脉管炎;胸降主动脉动脉瘤
Drug药品3,828京万红痔疮膏;布林佐胺滴眼液
Food食物4,870番茄冲菜牛肉丸汤;竹笋炖羊肉
Producer在售药品17,201通药制药青霉素V钾片;青阳醋酸地塞米松片
Symptom疾病症状5,998乳腺组织肥厚;脑实质深部出血
Total总计44,111约4.4万实体量级

1.3.3 知识图谱实体关系类型

实体关系类型中文含义关系数量举例
belongs_to属于8,844<妇科,属于,妇产科>
common_drug疾病常用药品14,649<阳强,常用,甲磺酸酚妥拉明分散片>
do_eat疾病宜吃食物22,238<胸椎骨折,宜吃,黑鱼>
drugs_of药品在售药品17,315<青霉素V钾片,在售,通药制药青霉素V钾片>
need_check疾病所需检查39,422<单侧肺气肿,所需检查,支气管造影>
no_eat疾病忌吃食物22,247<唇病,忌吃,杏仁>
recommand_drug疾病推荐药品59,467<混合痔,推荐用药,京万红痔疮膏>
recommand_eat疾病推荐食谱40,221<鞘膜积液,推荐食谱,番茄冲菜牛肉丸汤>
has_symptom疾病症状5,998<早期乳腺癌,疾病症状,乳腺组织肥厚>
acompany_with疾病并发疾病12,029<下肢交通静脉瓣膜关闭不全,并发疾病,血栓闭塞性脉管炎>
Total总计294,149约30万关系量级

1.3.4 知识图谱属性类型

属性类型中文含义举例
name疾病名称喘息样支气管炎
desc疾病简介又称哮喘性支气管炎...
cause疾病病因常见的有合胞病毒等...
prevent预防措施注意家族与患儿自身过敏史...
cure_lasttime治疗周期6-12个月
cure_way治疗方式"药物治疗","支持性治疗"
cured_prob治愈概率95%
easy_get疾病易感人群无特定的人群

2、基于医疗知识图谱的自动问答

2.1 技术架构

2.2 脚本结构

  • question_classifier.py:问句类型分类脚本
  • question_parser.py:问句解析脚本
  • chatbot_graph.py:问答程序脚本

2.3 支持问答类型

问句类型中文含义问句举例
disease_symptom疾病症状乳腺癌的症状有哪些?
symptom_disease已知症状找可能疾病最近老流鼻涕怎么办?
disease_cause疾病病因为什么有的人会失眠?
disease_acompany疾病的并发症失眠有哪些并发症?
disease_not_food疾病需要忌口的食物失眠的人不要吃啥?
disease_do_food疾病建议吃什么食物耳鸣了吃点啥?
food_not_disease什么病最好不要吃某事物哪些人最好不好吃蜂蜜?
food_do_disease食物对什么病有好处鹅肉有什么好处?
disease_drug啥病要吃啥药肝病要吃啥药?
drug_disease药品能治啥病板蓝根颗粒能治啥病?
disease_check疾病需要做什么检查脑膜炎怎么才能查出来?
check_disease 检查能查什么病全血细胞计数能查出啥来?
disease_prevent预防措施怎样才能预防肾虚?
disease_lasttime治疗周期感冒要多久才能好?
disease_cureway治疗方式高血压要怎么治?
disease_cureprob治愈概率白血病能治好吗?
disease_easyget疾病易感人群什么人容易得高血压?
disease_desc疾病描述糖尿病

2.4问答结果展示

部分代码展示:

    '''针对不同的问题,分开进行处理'''
    def sql_transfer(self, question_type, entities):
        if not entities:
            return []

        # 查询语句
        sql = []
        # 查询疾病的原因
        if question_type == 'disease_cause':
            sql = ["MATCH (m:Disease) where m.name = '{0}' return m.name, m.cause".format(i) for i in entities]

        # 查询疾病的防御措施
        elif question_type == 'disease_prevent':
            sql = ["MATCH (m:Disease) where m.name = '{0}' return m.name, m.prevent".format(i) for i in entities]

        # 查询疾病的持续时间
        elif question_type == 'disease_lasttime':
            sql = ["MATCH (m:Disease) where m.name = '{0}' return m.name, m.cure_lasttime".format(i) for i in entities]

        # 查询疾病的治愈概率
        elif question_type == 'disease_cureprob':
            sql = ["MATCH (m:Disease) where m.name = '{0}' return m.name, m.cured_prob".format(i) for i in entities]

        # 查询疾病的治疗方式
        elif question_type == 'disease_cureway':
            sql = ["MATCH (m:Disease) where m.name = '{0}' return m.name, m.cure_way".format(i) for i in entities]

        # 查询疾病的易发人群
        elif question_type == 'disease_easyget':
            sql = ["MATCH (m:Disease) where m.name = '{0}' return m.name, m.easy_get".format(i) for i in entities]

        # 查询疾病的相关介绍
        elif question_type == 'disease_desc':
            sql = ["MATCH (m:Disease) where m.name = '{0}' return m.name, m.desc".format(i) for i in entities]

        # 查询疾病有哪些症状
        elif question_type == 'disease_symptom':
            sql = ["MATCH (m:Disease)-[r:has_symptom]->(n:Symptom) where m.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]

        # 查询症状会导致哪些疾病
        elif question_type == 'symptom_disease':
            sql = ["MATCH (m:Disease)-[r:has_symptom]->(n:Symptom) where n.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]

        # 查询疾病的并发症
        elif question_type == 'disease_acompany':
            sql1 = ["MATCH (m:Disease)-[r:acompany_with]->(n:Disease) where m.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql2 = ["MATCH (m:Disease)-[r:acompany_with]->(n:Disease) where n.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql = sql1 + sql2
        # 查询疾病的忌口
        elif question_type == 'disease_not_food':
            sql = ["MATCH (m:Disease)-[r:no_eat]->(n:Food) where m.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]

        # 查询疾病建议吃的东西
        elif question_type == 'disease_do_food':
            sql1 = ["MATCH (m:Disease)-[r:do_eat]->(n:Food) where m.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql2 = ["MATCH (m:Disease)-[r:recommand_eat]->(n:Food) where m.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql = sql1 + sql2

        # 已知忌口查疾病
        elif question_type == 'food_not_disease':
            sql = ["MATCH (m:Disease)-[r:no_eat]->(n:Food) where n.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]

        # 已知推荐查疾病
        elif question_type == 'food_do_disease':
            sql1 = ["MATCH (m:Disease)-[r:do_eat]->(n:Food) where n.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql2 = ["MATCH (m:Disease)-[r:recommand_eat]->(n:Food) where n.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql = sql1 + sql2

        # 查询疾病常用药品-药品别名记得扩充
        elif question_type == 'disease_drug':
            sql1 = ["MATCH (m:Disease)-[r:common_drug]->(n:Drug) where m.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql2 = ["MATCH (m:Disease)-[r:recommand_drug]->(n:Drug) where m.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql = sql1 + sql2

        # 已知药品查询能够治疗的疾病
        elif question_type == 'drug_disease':
            sql1 = ["MATCH (m:Disease)-[r:common_drug]->(n:Drug) where n.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql2 = ["MATCH (m:Disease)-[r:recommand_drug]->(n:Drug) where n.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]
            sql = sql1 + sql2
        # 查询疾病应该进行的检查
        elif question_type == 'disease_check':
            sql = ["MATCH (m:Disease)-[r:need_check]->(n:Check) where m.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]

        # 已知检查查询疾病
        elif question_type == 'check_disease':
            sql = ["MATCH (m:Disease)-[r:need_check]->(n:Check) where n.name = '{0}' return m.name, r.name, n.name".format(i) for i in entities]

        return sql



if __name__ == '__main__':
    handler = QuestionPaser()
from question_classifier import *
from question_parser import *
from answer_search import *

'''问答类'''
class ChatBotGraph:
    def __init__(self):
        self.classifier = QuestionClassifier()
        self.parser = QuestionPaser()
        self.searcher = AnswerSearcher()

    def chat_main(self, sent):
        answer = '您好,我是小勇医药智能助理,希望可以帮到您。如果没答上来,可联系https://liuhuanyong.github.io/。祝您身体棒棒!'
        res_classify = self.classifier.classify(sent)
        if not res_classify:
            return answer
        res_sql = self.parser.parser_main(res_classify)
        final_answers = self.searcher.search_main(res_sql)
        if not final_answers:
            return answer
        else:
            return '\n'.join(final_answers)

if __name__ == '__main__':
    handler = ChatBotGraph()
    while 1:
        question = input('用户:')
        answer = handler.chat_main(question)
        print('小勇:', answer)
    用户:乳腺癌的症状有哪些?
    小勇: 乳腺癌的症状包括:乳腺癌的远处转移;胸痛;乳头溢液;乳头破碎;肝肿大;泌乳障碍;乳头内陷;乳房肿块;剧痛
    ******************************************************************************************
    用户:最近老流鼻涕怎么办?
    小勇: 症状流鼻涕可能染上的疾病有:枯草热;副流行性感冒;急性上呼吸道感染;硫化氢中毒;小儿衣原体肺炎;风寒感冒;慢性额窦炎;鼻源性头痛;人禽流行性感冒;小儿流行性喘憋性肺炎;病毒性感冒;慢性鼻炎;风热犯肺;感冒;顿呛;小儿急性上呼吸道感染;嗜酸细胞增多性非变态反应性鼻炎;干酪性鼻窦炎;下呼吸道感染;麻疹
    ******************************************************************************************
    用户:为什么有的人会失眠?
    小勇: 失眠可能的成因有:躯体疾病和服用药物可以影响睡眠,如消化不良,头痛,背痛,关节炎,心脏病,糖尿病,哮喘,鼻窦炎,溃疡病,或服用某些影响中枢神经的药物。
    由于生活方式引起睡眠问题也很常见,如饮用咖啡或茶叶,晚间饮酒,睡前进食或晚饭较晚造成满腹食物尚未消化,大量吸烟,睡前剧烈的体力活动,睡前过度的精神活动,夜班工作,白天小睡,上床时间不规律,起床时间不规律。
    可能的原因有压力很大,过度忧虑,紧张或焦虑,悲伤或抑郁,生气,容易出现睡眠问题。
    吵闹的睡眠环境,睡眠环境过于明亮,污染,过度拥挤。
    ******************************************************************************************
    用户:失眠有哪些并发症?
    小勇: 失眠的症状包括:心肾不交;神经性耳鸣;咽鼓管异常开放症;偏执狂;十二指肠胃反流及胆汁反流性胃炎;腋臭;黧黑斑;巨细胞动脉炎;Stargardt病;抑郁症;腔隙性脑梗死;甲状腺功能亢进伴发的精神障碍;紧张性头痛;胃下垂;心血虚;迷路震荡;口腔结核性溃疡;痰饮;游走性结节性脂膜炎;小儿脑震荡
    ******************************************************************************************
    用户:失眠的人不要吃啥?
    小勇: 失眠忌食的食物包括有:油条;河蚌;猪油(板油);淡菜(鲜)
    ******************************************************************************************
    用户:耳鸣了吃点啥?
    小勇: 耳鸣宜食的食物包括有:南瓜子仁;鸡翅;芝麻;腰果
    推荐食谱包括有:紫菜芙蓉汤;羊肉汤面;油豆腐油菜;紫菜鸡蛋莲草汤;乌药羊肉汤;可乐鸡翅;栗子鸡翅;冬菇油菜心
    ******************************************************************************************
    用户:哪些人最好不好吃蜂蜜?
    小勇: 患有散发性脑炎伴发的精神障碍;情感性心境障碍;蝎螫伤;四肢淋巴水肿;农药中毒所致的精神障碍;肝错构瘤;细菌性肺炎;急性高原病;小儿颅后窝室管膜瘤;柯萨奇病毒疹;眼眶静脉性血管瘤;乙脑伴发的精神障碍;晚期产后出血;吸入性肺炎;腓总神经损伤;铍及其化合物引起的皮肤病;猝死型冠心病;彼得异常;过敏性急性小管间质性肾炎;小儿腹胀的人最好不要吃蜂蜜
    ******************************************************************************************
    用户:鹅肉有什么好处?
    小勇: 患有子宫内膜厚;呼吸疾病;肛肠病;闭经;丧偶后适应性障碍;宫颈外翻;巨球蛋白血症;急性颌下腺炎;锥体外系损害;腺样体炎;咳嗽;错构瘤;牙科病;子宫内膜炎;闭锁综合征;结膜炎;恶性淋巴瘤;足外翻;神经炎;病理性近视的人建议多试试鹅肉
    ******************************************************************************************
    用户:肝病要吃啥药?
    小勇: 肝病宜食的食物包括有:鹅肉;鸡肉;鸡肝;鸡腿
    推荐食谱包括有:小米红糖粥;小米蛋奶粥;扁豆小米粥;黄豆小米粥;人参小米粥;小米粉粥;鲜菇小米粥;芝麻小米粥
    肝病通常的使用的药品包括:恩替卡韦分散片;维生素C片;二十五味松石丸;拉米夫定胶囊;阿德福韦酯片
    ******************************************************************************************
    用户:板蓝根颗粒能治啥病?
    小勇: 板蓝根颗粒主治的疾病有流行性腮腺炎;喉痹;喉炎;咽部异感症;急性单纯性咽炎;腮腺隙感染;过敏性咽炎;咽囊炎;急性鼻咽炎;喉水肿;慢性化脓性腮腺炎;慢性咽炎;急性喉炎;咽异感症;鼻咽炎;锁喉痈;小儿咽喉炎;喉返神经损伤;化脓性腮腺炎;喉血管瘤,可以试试
    ******************************************************************************************
    用户:脑膜炎怎么才能查出来?
    小勇: 脑膜炎通常可以通过以下方式检查出来:脑脊液钠;尿常规;Fisher手指试验;颈项强直;脑脊液细菌培养;尿谷氨酰胺;脑脊液钾;脑脊液天门冬氨酸氨基转移酶;脑脊液病原体检查;硝酸盐还原试验
    ******************************************************************************************
    用户:怎样才能预防肾虚?
    小勇: 肾虚可能的成因有:1、多因房劳过度,或少年频繁手淫。2、思虑忧郁,损伤心脾,则病及阳明冲脉。3、恐惧伤肾,恐则伤肾。4、肝主筋,阴器为宗筋之汇,若情志不遂,忧思郁怒,肝失疏泄条达,则宗筋所聚无能。5、湿热下注,宗筋弛纵。
    肾虚是肾脏精气阴阳不足所产生的诸如精神疲乏、头晕耳鸣、健忘脱发、腰脊酸痛、遗精阳痿、男子不育、女子不孕、更年期综合征等多种病证的一个综合概念。关于肾虚形成的原因,可归结为两个方面,一为先天禀赋不足,二为后天因素引起。
    从引起肾虚的先天因素来看,首先是先天禀赋薄弱。《灵枢.寿天刚柔》篇说:“人之生也,有刚有柔,有弱有强。”由于父母体弱多病,精血亏虚时怀孕;或酒后房事怀孕;或年过五十精气力量大减之时怀孕;或男女双方年龄不够,身体发育不完全结婚,也就是早婚时怀孕,或生育过多,精血过度耗损;或妊娠期中失于调养,胎气不足等等都可导致肾的精气亏虚成为肾虚证形成的重要原因;其次,如果肾藏精功能失常就会导致性功能异常,生殖功能下降,影响生殖能力,便会引起下一代形体虚衰,或先天畸形、痴呆、缺陷、男子出现精少不育、早泄,女子出现闭经不孕、小产、习惯性流产等等。
    肾虚的预防措施包括:肾虚日常预防
    在预防方面,因起病与恣情纵欲有关的,应清心寡欲,戒除手淫;如与全身衰弱、营养不良或身心过劳有关的,应适当增加营养或注意劳逸结合,节制性欲。
    1、性生活要适度,不勉强,不放纵。
    2、饮食方面:无力疲乏时多吃含铁、蛋白质的食物,如木耳、大枣、乌鸡等;消化不良者多喝酸奶,吃山楂;平日护肾要多吃韭菜、海参、人参、乌鸡、家鸽等。
    3、经常进行腰部活动,这些运动可以健运命门,补肾纳气。还可多做一些刺激脚心的按摩,中医认为,脚心的涌泉穴是浊气下降的地方,经常按摩涌泉穴,可益精补肾、强身健体、防止早衰,并能舒肝明目,清喉定心,促进睡眠,增进食欲。
    4、充足的睡眠也是恢复精气神的重要保障,工作再紧张,家里的烦心事再多,到了该睡觉的时候也要按时休息。
    健康教育
    1、过度苦寒、冰凉的食物易伤肾,如芦荟、苦瓜、雪糕、鹅肉、啤酒进食过多都伤肾,应该多食黑色素含量高和温补性中药如黑米黑豆等。
    2、男性接触过多的洗涤剂也伤肾,家庭应少用洗涤剂清洗餐具及蔬果,以免洗涤剂残留物被过多摄入。
    3、适当运动可延缓衰老,但强度不宜太大,应选能力所及的运动项目,以促进血液循环,可改善血淤、气损等情况。散步、慢跑、快步走,或在鹅卵石上赤足适当行走,都会促进血液循环,对肾虚有辅助治疗作用。
    4、保持良好的作息习惯,尽量避免熬夜。
    5、积极参加户外运动,放松心情。
    6、不要给自己太大的压力,学会合理减压。
    ******************************************************************************************
    用户:感冒要多久才能好?
    小勇: 感冒治疗可能持续的周期为:7-14天
    ******************************************************************************************
    用户:高血压要怎么治?
    小勇: 高血压可以尝试如下治疗:药物治疗;手术治疗;支持性治疗
    ******************************************************************************************
    用户:白血病能治好吗?
    小勇: 白血病治愈的概率为(仅供参考):50%-70%
    ******************************************************************************************
    用户:什么人容易得高血压?
    小勇: 高血压的易感人群包括:有高血压家族史,不良的生活习惯,缺乏运动的人群
    ******************************************************************************************
    用户:糖尿病
    小勇: 糖尿病,熟悉一下:糖尿病是一种比较常见的内分泌代谢性疾病。该病发病原因主要是由于胰岛素分泌不足,以及胰升高血糖素不适当地分泌过多所引起。多见于40岁以上喜食甜食而肥胖的病人,城市多于农村,常有家族史,故与遗传有关。少数病人与病毒感染和自身免疫反应有关。主要表现为烦渴、多饮、多尿、多食、乏力、消瘦等症状。生命的常见病,伴发高血压、冠心病、高脂血症等,严重时危及生命。
    中医学认为,肝主疏泄,关系人体接收机的升降与调畅,肝气郁滞则气机升降输布紊乱,肝失疏泄则血糖等精微物质不能随清阳之气输布于周身而郁滞于血中,出现高血糖或精微物质的输布紊乱,反见血糖升高,进一步导致血脂、蛋白等其它精微物质紊乱,引起其他合并症,治疗以疏肝调气为主,顺肝条达之性以恢复其生理功能,肝气条达,气机调畅,精微得以输布,糖被利用而血糖自然下降。
    另外,因糖尿病的发生和饮食有关,饮食控制的好坏直接影响着治疗的效果。再就是配合运动,注意调摄情志,再适当的配合中药治疗会取得良好的治疗效果。 
    ******************************************************************************************
    用户:全血细胞计数能查出啥来
    小勇: 通常可以通过全血细胞计数检查出来的疾病有成人类风湿性关节炎性巩膜炎;外阴-阴道-牙龈综合征;电击伤;老年收缩期高血压;小儿肝硬化;异常血红蛋白病;痴呆综合征;高血压病伴发的精神障碍;睾丸淋巴瘤;叶酸缺乏所致贫血;眼球内炎;不稳定血红蛋白病;类癌综合征;老年痴呆;急性淋巴管炎;宫颈妊娠;蚕食性角膜溃疡;低增生性急性白血病;交感性眼炎;原发性免疫缺陷病
    

3.总结

1、本项目完成了从无到有,以垂直网站为数据来源,构建起以疾病为中心的医疗知识图谱,实体规模4.4万,实体关系规模30万。并基于此,搭建起了一个可以回答18类问题的自动问答小系统,总共耗时3天。其中,数据采集与整理1天,知识图谱构建与入库0.5天,问答系统组件1.5天。总的来说,还是比较快速。
2、本项目以业务驱动,构建医疗知识图谱,知识schema设计基于所采集的结构化数据生成(对网页结构化数据进行xpath解析)。
3、本项目以neo4j作为存储,并基于传统规则的方式完成了知识问答,并最终以cypher查询语句作为问答搜索sql,支持了问答服务。
4、本项目可以快速部署,数据已经放在data/medical.json当中,本项目的数据,在本项目中的部署上,可以遵循项目运行步骤,完成数据库搭建,并提供搜索服务。

项目链接:

链接跳转

更多优质内容请关注公号:汀丶人工智能;会提供一些相关的资源和优质文章,免费获取阅读。


汀丶
84 声望62 粉丝