该项目是我的一次课程设计,开发的语言是python。从网上学习了各种相关知识后写出的一个KBQA系统,希望这个系统的搭建过程也能给读者一些有用的经验。
一,数据获取
知识图谱的数据一般是非结构性的,获得的渠道有多种,如利用爬虫工具爬取相关的文本等等。
这里,我们构建图谱所需的疫情数据从OpenKg中文开放知识图谱获取
图谱中涉及到的知识有医生,救护人员以及他们的信息,履历,事迹。虽然样本量不大,但是对于数据所需的处理也比较繁琐。
JSON文件中存储了所需要的数据,这些数据是结构化的
数据说明
通过下载得来的schema文件可以发现,JSON文件中的数据包括22个类别,和48个属性节点。
概念:21个
实例:747个
数值属性:291个
对象属性:1160个
类别Class: people,school,institutions,battle,countries,field…
属性Property: nativePlace,gender,deathTime,birthDate,national…
二,关系抽取
要获得构建制图图谱系统所需的三元组数据,需要对以获取的数据,进行节点和关系边的提取。在这里,主要建立类别与属性之间的关系边。
提取节点和属性用的代码,由于这部分代码的重复性片段较多,因此展示了具有代表性操作的代码片段:
with open(filename, encoding='utf-8') as f:
#用于存储节点的列表的定义
characterjson = json.load(f)
characterlist=[]
articlelist=[]
institutionlist=[]
teamlist=[]
for data in characterjson['@graph']:
#team_dict 救援队类节点的提取
if (data['@type'] == "http://www.openkg.cn/COVID-19/character/class/C548"):
team.append(data['label']['@value'])
team_dict = {}
team_dict['team'] = data['label']['@value']
teamlist.append(team_dict)
if 'P45' in data:
team_dict['supportSite'] = data['P45']
if 'P49' in data:
team_dict['departureDate'] = data['P49']
departureDate.append([data['label']['@value'], data['P49']])
#institution dict 救助机构类节点的提取
if (data['@type'] == "http://www.openkg.cn/COVID-19/character/class/C3"):
institutions.append(data['label']['@value'])
institution_dict = {}
institution_dict['institution'] = data['label']['@value']
institutionlist.append(institution_dict)
if 'P24' in data:
institution_dict['cities'] = data['P24']
if 'P25' in data:
institution_dict['To_enact'] = data['P25']
if 'P26' in data:
institution_dict['publish'] = data['P26']
#相关关系边的提取
for data in characterjson['@graph']:
if (data['@type'] == "http://www.openkg.cn/COVID-19/character/class/C1"):
for i in characterlist:
if 'colleagues' in i:
if type(i['colleagues']) is list:
for j in range(len(i['colleagues'])):
if(data['@id']==i['colleagues'][j]):
i['colleagues'][j]=data['label']['@value']
colleagues.append([i['people'],data['label']['@value']])
break
else :
if (data['@id'] == i['colleagues']):
i['colleagues'] = data['label']['@value']
colleagues.append([i['people'], data['label']['@value']])
break
将所有的节点和关系边提取到列表后,可以用set()函数来去除重复的节点后将其存储起来。
三,数据库连接与使用
Neo4j 数据库
Neo4j数据库是存储图数据最常用的数据库之一,他的优点很明显。
1.与Python交互方便
2.容易上手,应用方便。
3.数据存储容量大,可输出结构化数据文件。
通过py2neo来链接与操作数据库
from py2neo import Graph,Node
class CharacterGraph:
def __init__(self):
self.data_path = './data/character-covid-19-v0.2.json'
self.g = Graph(
host="127.0.0.1",
http_port=7474,
user="neo4j",
password="123456")
def create_node(self, label, nodes):
for node_name in nodes:
node = Node(label, name=node_name)
self.g.create(node)
return
def create_relationship(self, start_node, end_node, edges, rel_type, rel_name):
set_edges = []
for edge in edges:
set_edges.append('###'.join(edge))
for edge in set(set_edges):
edge = edge.split('###')
p = edge[0]
q = edge[1]
query = "match(p:%s),(q:%s) where p.name='%s'and q.name='%s' create (p)-[rel:%s{name:'%s'}]->(q)" % (start_node, end_node, p, q, rel_type, rel_name)
try:
self.g.run(query)
except Exception as e:
print(e)
return
Neo4j生成相应的节点和关系边
至此,我们已经完成了对数据的处理与存储了,对于搭建一个KBQA系统来说,工作已经完成了一半了,在下一篇文章,我将会展示问答系统的搭建流程。