知识图谱是将知识连接起来形成的一个网络。由节点和边组成,节点是实体,边是两个实体的关系,节点和边都可以有属性。知识图谱除了可以查询实体的属性外,还可以很方便的从一个实体通过遍历关系的方式找到相关的实体及属性信息。
本项目基于医疗方面知识的问答,通过搭建一个医疗领域知识图谱,并以该知识图谱完成自动问答与分析服务。本项目以neo4j作为存储,基于传统规则的方式完成了知识问答,并最终以关键词执行cypher查询,并返回相应结果查询语句作为问答。
该问答系统完全基于规则匹配实现,通过关键词匹配,对问句进行分类,医疗问题本身属于封闭域类场景,对领域问题进行穷举并分类,然后使用cypher的match去匹配查找neo4j,根据返回数据组装问句回答,最后返回结果。
1、Node4j软件的安装和使用。
2、数据预处理方法。
3、Python处理数据方法。
4、能够实现一个知识图谱问答系统。
Neo4j版本:Neo4j Desktop1.4.15;
neo4j里面医疗系统数据库版本:4.4.5;
Pycharm版本:2021;
JDK版本:jdk1.8.0_211;
NongoDB版本:MongoDB-windows-x86_64-5.0.14;
(一)安装JAVA
1.下载java安装包:
官网下载链接:https://www.oracle.com/java/technologies/javase-downloads.html

本人下载的版本为JDK-1.8,JDK版本的选择一定要恰当,版本太高或者太低都可能导致后续的neo4j无法使用。
安装好JDK之后就要开始配置环境变量了。 配置环境变量的步骤如下:
右键单击此电脑—点击属性—点击高级系统设置—点击环境变量

在下方的系统变量区域,新建环境变量,命名为JAVA_HOME,变量值设置为刚才JAVA的安装路径,我这里是C:\Program Files\Java\jdk1.8.0_211

编辑系统变量区的Path,点击新建,然后输入 %JAVA_HOME%\bin

打开命令提示符CMD(WIN+R,输入cmd),输入 java -version,若提示Java的版本信息,则证明环境变量配置成功。

2.安装好JDK之后,就可以安装neo4j了
2.1 下载neo4j
官方下载链接:https://neo4j.com/download-center/#community
也可以直接下载我上传到云盘链接:
Neo4j Desktop Setup 1.4.15.exe
https://www.aliyundrive.com/s/huXS4HXMn9V
提取码: 36vf
打开之后会有一个自己设置默认路径,可以根据自己电脑情况自行设置,然后等待启动就行了

打开之后我们新建一个数据库,名字叫做:“基于医疗领域的问答系统”
详细信息看下图:

数据库所用的是4.4.5版本,其他数据库参数信息如下:

项目结构整体目录:
├── pycache \编译结果保存目录
│ ├── answer_search.cpython-39.pyc
│ ├── question_classifier.cpython-39.pyc
│ └── question_parser.cpython-39.pyc
├── answer_search.py
├── build_medicalgraph.py \知识图谱数据入库脚本
├── chatbot_graph.py \问答程序脚本
├── data
│ └── medical.json \本项目的数据,通过build_medicalgraph.py导neo4j
│ └── medical2.json\本项目的部分数据,通过build_medicalgraph.py导neo4j
├── dict
│ ├── check.txt \诊断检查项目实体库
│ ├── deny.txt \否定词词库
│ ├── department.txt \医疗科目实体库
│ ├── disease.txt \疾病实体库
│ ├── drug.txt \药品实体库
│ ├── food.txt \食物实体库
│ ├── producer.txt \在售药品库
│ └── symptom.txt \疾病症状实体库
├── prepare_data
│ ├──__pycache__
│ ├── build_data.py \数据库操作脚本
│ ├── data_spider.py \网络资讯采集脚本
│ └── max_cut.py \基于词典的最大向前/向后脚本
│ ├── 处理后的medical数据.xlsx
│ ├── MongoDB数据转为json格式数据文件.py
│ ├──从MongoDB导出的medical.csv
│ ├──data.json #从MongoDB导出的json格式数据
├── question_classifier.py \问句类型分类脚本
├── answer_search.py \基于问题答复脚本
├── build_medicalgraph.py \构建医疗图谱脚本
├── chatbot_graph.py \小艺问答系统机器人脚本
├── question_parser.py \基于问句解析脚本
├── 删除所有关系.py
├── 删除关系链.py
├── 两节点新加关系.py
├── 交互 匹配所有节点.py
├── 更新节点.py
这里chatbot_graph.py脚本首先从需要运行的chatbot_graph.py文件开始分析。
该脚本构造了一个问答类ChatBotGraph,定义了QuestionClassifier类型的成员变量classifier、QuestionPase类型的成员变量parser和AnswerSearcher类型的成员变量searcher。
question_classifier.py脚本构造了一个问题分类的类QuestionClassifier,定义了特征词路径、特征词、领域actree、词典、问句疑问词等成员变量。
question_parser.py问句分类后需要对问句进行解析。
该脚本创建一个QuestionPaser类,该类包含三个成员函数。
answer_search.py问句解析之后需要对解析后的结果进行查询。
该脚本创建了一个AnswerSearcher类。与build_medicalgraph.py类似,该类定义了Graph类的成员变量g和返回答案列举的最大个数num_list。
该类的成员函数有两个,一个查询主函数一个回复模块。
问答系统框架的构建是通过chatbot_graph.py、answer_search.py、question_classifier.py、question_parser.py等脚本实现。
1)数据来源,爬取数据来源。
安装MongoDB数据库:
MongoDB官方下载地址:
https://www.mongodb.com/try





安装完成:


进行MongoDB环境配置:
在变量Path里加入E:\MongoDB\bin

打开终端(cmd)输入mongod --dbpath E:\MongoDB\data\db

在浏览器输入
127.0.0.1:27017
查看MongoDB服务是否启动成功:

安装好MongoDB之后开始爬取数据:
数据来源于寻医问药网:http://jib.xywy.com/

具体的疾病详情页面如下:
首先对网址上的疾病链接进行分析,以感冒为例:
感冒的链接:http://jib.xywy.com/il_sii_38.htm

可以看到,上面包含了疾病的简介、病因、预防、症状、检查、治疗、并发症、饮食保健等详情页的内容。下面我们要使用爬虫把信息收集起来。
通过观察可以看出,链接部分 http://jib.xywy.com/il_sii_ 都是相同的,是通过数字的叠加来组成不同的病例。通过string类型的拼接进行循环后可以得到我们需要的内容。
数据收集模块放在/prepare_data文件夹下面。
要收集 url 下面对应的数据,具体爬虫代码如下:





需要爬取的信息包括疾病名、所属目录、症状、治疗方案等等,都可以从页面上获取。



然后我们可以在MongoDB数据库中查看我们爬取到的疾病链接和解析出的网页内容:


2)原始数据的处理。
定义一个max_cut.py文件来进行词语的切分,其中包含了最大向前匹配,最大向后匹配,双向最大向前匹配。



然后通过collect_medical函数完成数据的收集整理工作。
再将整理好的数据重新存入数据库中。
在init文件里配置数据库连接,找到当前文件所在的目录,指定连接的数据库及其下面的collection。




再利用python脚本导出爬出的医疗数据并设置格式为data.json格式文件:


处理数据后对应的图谱系统数据关键词:

将从MongoDB导出的data.json数据格式处理之后保存为medical.json和medical2.json文件,其中medical2.json为medical.json中的部分数据。
考虑到构建全部知识图谱需要很久,所以取出一部分数据(medical2.json)先进行构建图谱。


处理后结构化的数据保存到excel文件:

3)所搭建的系统框架,包括知识图谱实体类型,实体关系类型,知识图谱属性类型等。
知识图谱实体类型:

一般来说,一个医疗知识图谱问答系统Schema包括以下几个部分:
实体:指代医疗领域中的具体概念或对象,如药品、疾病、症状等。
属性:指代实体的特征或描述,如药品的成分、剂型、适应症等。
关系:指代实体之间的联系或影响,如疾病与药物的治疗关系、食物的忌吃关系等。
问题:指代用户对医疗领域的信息需求,如“高血压应该吃什么药?”、“感冒有哪些常见的症状?”等。
答案:指代针对问题的回复或解释,如“高血压可以服用降压药物,如氨氯地平片、硝苯地平片等。”、“感冒常见的症状有发热、咳嗽、流鼻涕等。”等。
departments = [] #科室
diseases = [] # 疾病
drugs = [] # 药品
foods = [] # 食物
producers = [] #药品大类
symptoms = []#症状

实体关系类型:

# 构建节点实体关系,共11类,medical2做出来的只有10类,因为数据量少
rels_department = []
rels_noteat = [] # 疾病-忌吃食物关系
rels_doeat = [] # 疾病-宜吃食物关系
rels_recommandeat = [] # 疾病-推荐吃食物关系
rels_commonddrug = [] # 疾病-通用药品关系
rels_recommanddrug = [] # 疾病-热门药品关系
rels_check = [] # 疾病-检查关系
rels_drug_producer = [] # 厂商-药物关系
rels_symptom = [] #疾病症状关系
rels_acompany = [] # 疾病并发关系
rels_category = [] # 疾病与科室之间的关系
知识图谱属性类型:



4)导入Neo4j数据库,生成图谱。
新建一个数据库:基于医疗领域的问答系统
开启Node4j数据库:


连接我们所建的neo4j数据库:

知识图谱数据入库:
根据字典形式的数据创建结点,以疾病为中心定义关系形成三元组表示的知识,将结点和关系导入neo4j数据库形成知识图谱,通过运行build_medicalgraph.py脚本构建图谱:

建立实体关系类型:




该脚本构建了一个MedicalGraph类,定义了Graph类的成员变量g和json数据路径成员变量data_path。
建立的图谱实体关系和属性类型数量有点多,需要等待一会。
脚本运行完之后查看neo4j数据库中构建的知识图谱:
match (n) return n



提示:Not all return nodes are being displayed due to Initial Node Display setting. Only 3000 of 44112 nodes are being displayed
由于“初始节点显示”设置,并非所有返回节点都显示。44112个节点中仅显示3000个
这里因为我设置的参数只显示前3000个,4万多个节点只显示了一部分。
对于单个节点分析是先建一个label为disease、name为疾病名称的node,property方面包括prevent、cure_way、cause等等,另外,对于症状、科室、检查方法等信息都建立单独的node,同时通过has_symptom、belongs_to、need_check等关联把它们和疾病名称关联起来,因为疾病之间存在并发关系,疾病之间也可以通过症状串联起来,所以最后我们利用大量的
医疗数据,就能构建一个大型的医疗知识图谱:


提示:Started streaming 44112 records in less than 1 ms and completed in less than 1 ms.
在不到1毫秒内开始流式传输44112条记录,并在不到1秒内完成。
5)Python 与Neo4j的交互实现。
连接Node4j数据库:
from py2neo import Graph
class AnswerSearcher:
def __init__(self):#调用数据库进行查询
# self.g = Graph("bolt://localhost:7687", username="neo4j", password="123456")#老版本neo4j
self.g = Graph("bolt://localhost:7687", auth=("neo4j", "123456"))#输入自己修改的用户名,密码
self.num_limit = 20#最多显示字符数量

创建图对象:
class MedicalGraph:
def __init__(self):
cur_dir = '/'.join(os.path.abspath(__file__).split('/')[:-1])
self.data_path = os.path.join(cur_dir, 'data/medical.json')
# self.g = Graph("http://localhost:7474", username="neo4j", password="123456")
self.g = Graph("bolt://localhost:7687", auth=("neo4j", "123456"))

增加node节点:
def create_node(self, label, nodes):
count = 0
for node_name in nodes:
node = Node(label, name=node_name)
self.g.create(node)
count += 1
print(count, len(nodes))
return

创建实体关系:
def create_graphrels(self):
Drugs, Foods, Checks, Departments, Producers, Symptoms, Diseases, disease_infos, rels_check, rels_recommandeat, rels_noteat, rels_doeat, rels_department, rels_commonddrug, rels_drug_producer, rels_recommanddrug,rels_symptom, rels_acompany, rels_category = self.read_nodes()
self.create_relationship('Disease', 'Food', rels_recommandeat, 'recommand_eat', '推荐食谱')#调用下面的关系边创建函数
self.create_relationship('Disease', 'Food', rels_noteat, 'no_eat', '忌吃')
self.create_relationship('Disease', 'Food', rels_doeat, 'do_eat', '宜吃')
self.create_relationship('Department', 'Department', rels_department, 'belongs_to', '属于')
self.create_relationship('Disease', 'Drug', rels_commonddrug, 'common_drug', '常用药品')
self.create_relationship('Producer', 'Drug', rels_drug_producer, 'drugs_of', '生产药品')
self.create_relationship('Disease', 'Drug', rels_recommanddrug, 'recommand_drug', '好评药品')
self.create_relationship('Disease', 'Check', rels_check, 'need_check', '诊断检查')
self.create_relationship('Disease', 'Symptom', rels_symptom, 'has_symptom', '症状')
self.create_relationship('Disease', 'Disease', rels_acompany, 'acompany_with', '并发症')
self.create_relationship('Disease', 'Department', rels_category, 'belongs_to', '所属科室')

更新节点:
更新先要找出Nodes,再使用事务的push更新
from py2neo import Graph, Node, Relationship, NodeMatcher, Subgraph
g = Graph('http://localhost:7687', auth=("neo4j", "123456"))
from py2neo import Graph, NodeMatcher
tx = g.begin()# 找到要找的Nodes
matcher = NodeMatcher(g)
init_node = matcher.match("Person", name="节点名称")
new_node = init_node.first()
new_node['name'] = "新的节点名称"
sub = Subgraph(nodes=[new_node])
tx.push(sub)
g.commit(tx)
from py2neo import Graph, Node, Relationship, NodeMatcher, Subgraph
g = Graph('http://localhost:7687', auth=("neo4j", "123456"))
from py2neo import Graph, NodeMatcher
tx = g.begin() # 找到要找的Nodes
matcher = NodeMatcher(g)
init_node = matcher.match("Person", name="节点名称")
new_node = init_node.first()
new_node['name'] = "新的节点名称"
sub = Subgraph(nodes=[new_node])
tx.push(sub)
g.commit(tx)

删除关系链(节点也会删除):
from py2neo import Graph, Node, Relationship, NodeMatcher, Subgraph, RelationshipMatcher
g = Graph('http://localhost:7687', auth=("neo4j", "123456"))
matcher = NodeMatcher(g)
r_matcher = RelationshipMatcher(g)
fugui = matcher.match('Person', name='name1').first()
youqian = matcher.match('Person', name='name2').first()
relation = r_matcher.match(nodes=[fugui, youqian]).first() #也可以是none,表示任意节点
print(relation)
g.delete(relation)

两个节点新加关系:
from py2neo import Graph, Node, Relationship, NodeMatcher, Subgraph
g = Graph('http://localhost:7687', auth=("neo4j", "123456"))
matcher = NodeMatcher(g)
fugui = matcher.match('Person', name='节点名称1').first()
youqian = matcher.match('Person', name='节点名称2').first()
relation = Relationship(节点名称1, '所要建立的关系', 节点名称2)
g.create(relation)

6)问答系统的实现与测试,包括问答系统·支持的问答类型,实现方法与步骤。
本项目问答对话系统的分析思路,整体上接近一个基于规则的对话系统,首先我们需要对用户输入进行分类,其实就是分析用户输入涉及到的实体及问题类型,也就是Neo4j中的node、property、relationship,然后我们利用分析出的信息,转化成Neo4j的查询语句,最后再把查询的结果返回给用户,就完成了一次问答。
本项目问答系统支持的问答类型:
问答系统整体上涉及到三个模块,问题的分类、问题的解析以及回答的搜索。
对于property和relationship,我们先预设定一系列的问句疑问词,从而对问句的每个词进行对比分析,判断出问句的类型
然后,根据问句的类型和之前识别出来的实体,基于规则推断出property和relationship:
把问题转化为Neo4j的Cypher语句,其实也是预先写好Cypher语句的模板,根据实际的情况把之前分析得到的node、property、relationship填入Cypher语句中进行查询。
得到了Cypher语句,我们就能连接Neo4j数据库进行查询,得到结果之后,还需要对语句进行一点微调,根据对应的qustion_type,调用相应的回复模板:

问答框架包含问句分类、问句解析、查询结果三个步骤,具体一步步分析。
首先是问句分类,是通过question_classifier.py脚本实现的。
再通过question_parser.py脚本进行问句分类后对问句进行解析。
然后通过answer_search.py脚本对解析后的结果进行查询
最后通过chatbot_graph.py脚本进行问答实测。
执行chatbot_graph.py脚本后出现:
“请输入您所要咨询的问题小艺会帮您解决:”
我们输入一个简单的问题:感冒应该怎么治疗?
问答系统返回的结果如下:

再试试其它的问题:比如什么是苯中毒等等
问答系统返回结果如下:

经过测试本问答系统能回答的问题有很多,基于问句中存在的关键词回答效果表现很好。做出来的基于知识图谱的医疗知识问答系统能够根据用户提出的问题很好的进行解答。

做出来的问答系统还是很Nice的。

基于知识图谱的自动问答拆分为2 个主要步骤:命名实体识别步骤和属性映射步骤。其中,实体识别步骤的目的是找到问句中询问的实体名称,而属性映射步骤的目的在于找到问句中询问的相关属性。你说这个实体识别就是识别出文本中表示医疗实体的词语,如疾病、药物等。这个实体关系抽取是从医疗文本中识别出实体对,并标注它们之间的语义关系,从而构建知识图谱的三元组。
本项目问答系统的主要特征是知识图谱,系统依赖一个或多个领域的实体,并基于图谱进行推理或演绎,深度回答用户的问题,更擅长回答知识性问题,与基于模板的聊天机器人有所不同的是它更直接、直观的给用户答案。本项目问答系统没有复杂的算法,一般采用模板匹配的方式寻找匹配度最高的答案,可以直接给出答案。
各位有兴趣的小伙伴可以私信我要详细的项目文档和项目完整系统源码,欢迎各位小伙伴的来访!
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?
我正在根据Rakefile中的现有测试文件动态生成测试任务。假设您有各种以模式命名的单元测试文件test_.rb.所以我正在做的是创建一个以“测试”命名空间内的文件名命名的任务。使用下面的代码,我可以用raketest:调用所有测试require'rake/testtask'task:default=>'test:all'namespace:testdodesc"Runalltests"Rake::TestTask.new(:all)do|t|t.test_files=FileList['test_*.rb']endFileList['test_*.rb'].eachdo|task|n
我想要像“嘿那里”这样的东西变成,例如,#316583。我希望将任意长度的字符串“归结”为十六进制颜色。我不知道从哪里开始。我在想,每个字符串的MD5散列都是不同的-但如何将该散列转换为十六进制颜色数字? 最佳答案 你可以只取几位前几位:require'digest/md5'color=Digest::MD5.hexdigest('Mytext')[0..5] 关于ruby-如何使用Ruby基于字母数字字符串生成颜色?,我们在StackOverflow上找到一个类似的问题:
1.问题描述使用Python的turtle(海龟绘图)模块提供的函数绘制直线。2.问题分析一幅复杂的图形通常都可以由点、直线、三角形、矩形、平行四边形、圆、椭圆和圆弧等基本图形组成。其中的三角形、矩形、平行四边形又可以由直线组成,而直线又是由两个点确定的。我们使用Python的turtle模块所提供的函数来绘制直线。在使用之前我们先介绍一下turtle模块的相关知识点。turtle模块提供面向对象和面向过程两种形式的海龟绘图基本组件。面向对象的接口类如下:1)TurtleScreen类:定义图形窗口作为绘图海龟的运动场。它的构造器需要一个tkinter.Canvas或ScrolledCanva
文章目录1.自动驾驶实战:基于Paddle3D的点云障碍物检测1.1环境信息1.2准备点云数据1.3安装Paddle3D1.4模型训练1.5模型评估1.6模型导出1.7模型部署效果附录show_lidar_pred_on_image.py1.自动驾驶实战:基于Paddle3D的点云障碍物检测项目地址——自动驾驶实战:基于Paddle3D的点云障碍物检测课程地址——自动驾驶感知系统揭秘1.1环境信息硬件信息CPU:2核AI加速卡:v100总显存:16GB总内存:16GB总硬盘:100GB环境配置Python:3.7.4框架信息框架版本:PaddlePaddle2.4.0(项目默认框架版本为2.3