草庐IT

Neo4j简单构建知识图谱实例

虾滑枣梨 2023-05-10 原文

目录

 一、需要两组数据

二、提取所需专题数据

三、利用结巴分词将专题数据分词

四、连接并绘制知识图谱

五、消除重复节点及重复关系

六、结果展示


Ps:在使用Neo4j前,需要先在该安装路径文件下cmd运行,输入neo4j console 即可启动,可根据关闭时输入neo4j stop,如下图所示说明已成功启动,此时可打开 http://localhost:7474/进入Neo4j图数据库。

一、需要两组数据

       如下图所示,我们需要筛选出关键字中包含有“图形化编程”的专题数据,并以此构建“图形化编程”与各专题之间的关系。下图以20条数据为例(本文使用的数据库为Mysql数据库):

二、提取所需专题数据

       利用SQL语句提取所需专题数据,即“图形化编程”存在于keywords中的对应专题数据(本文举的例子中,keywords中皆有“图形化编程”,可以不用使用以下模糊语句;该语句适用于关键词中没有我们需要的,即相应专题也不需要,因此可以过滤掉,提高数据准确性)。SQL模糊查询语句的代码如下:

# 使用的是数据库引擎连接数据库,需导入"from sqlalchemy import create_engine",my_date是数据库名
con = create_engine('mysql+pymysql://root:密码@localhost:3306/my_date charset=utf8')

# 获取test表专题字段,使用pandas库中的数据库查询方法
text = pd.read_sql_query(sql="SELECT distinct zhuanti FROM test where zhuanti is not null and keywords like '%%%%%s%%%%'" % '图形化编程', con=con)

三、利用结巴分词将专题数据分词

       由于本文举的例子中,有些专题不止只有一个词汇,同时也有部分数据是存在相同专题的情况,因此需要使用结巴分词进行数据分词。例如最后一行的【职业教育;计算机硬件技术】利用结巴分词提取为【职业教育】、【计算机硬件应用】两个词汇。步骤如下:

# 导入自定义的专题分词词典
data = str(text)  # 需将读取的文档dataframe格式转为str
jieba.load_userdict('专题词典.txt')

# 去除摘要中的空格、换行等不必要的数据
data = data.replace(';', '')
data = data.replace('\n', '')
data = data.replace(' ', '')
data = data.replace(',', '')

# 结巴分词中的精确模式进行分词
seg_list = jieba.lcut(data)

# 导入自定义的停用词词典
with open('stopwords.txt', 'r+', encoding='utf-8')as fp:
    stopwords = fp.read().split('\n')

# 存储过滤停用词后的分词结果
word_list = []

# 如果切出的词不是停用词,则存入列表
for seg in seg_list:
    if seg not in stopwords:
        word_list.append(seg)

       其中自定义的专题分词是为了防止出现,例如【计算机硬件技术】被划分为【计算机】【硬件】【技术】等情况,不满足我们的需求,因此自定义专题分词词典能够提取我们所需的词汇。本文的专题词典【专题词典.text】如下所示:

中等教育
教育理论与教育管理
初等教育
计算机软件及计算机应用
自动化技术
工业通用技术及设备
计算机硬件技术
电信技术
铁路运输
建筑科学与工程
戏剧电影与电视艺术
职业教育

        其中自定义的停用词词典是为了过滤一些例如数字、符号等不需要的数据。本文的停用词词典【stopwords.text】如下所示:

;
1
2
3
4
5
6
7
8
9
10
11
12
zhuanti0

        最终过滤出的分词结果【word_list】如下所示:

['中等教育', '教育理论与教育管理', '计算机软件及计算机应用', '初等教育', '自动化技术', '工业通用技术及设备', '计算机软件及计算机应用', '计算机软件及计算机应用', '自动化技术', '计算机软件及计算机应用', '计算机硬件技术', '电信技术', '计算机软件及计算机应用', '铁路运输', '建筑科学与工程', '自动化技术', '初等教育', '工业通用技术及设备', '戏剧电影与电视艺术', '计算机软件及计算机应用', '职业教育', '计算机硬件技术']

PS:突然发现该方法其实不是很必要,就是其实我们上述最终过滤出的数据,结合后面消除重复节点,得到的就是我们定义的专题词典,所以可以针对自己的数据情况酌情使用,这里也是展示一下如何进行结巴分词提取所需数据。

四、连接并绘制知识图谱

       分词后便得到了我们绘制图谱的数据,连接Neo4j图数据库,以“图形化编程”为中心节点,将之前分词并清洗后的数据【word_list】用for循环逐个添加,创建节点和关系,并为节点添加属性,最后实例化。打开网址便能看到绘制好的图谱。

# 连接Neo4j
graph = Graph("http://localhost:7474", auth=("neo4j", "密码"))
graph.delete_all()  # 清除neo4j中原有的结点

# 创建节点
for i in range(1,len(word_list)):
    node = Node('title',name="图形化编程")
    relation = Node('zhuanti',name=word_list[i])
    graph.create(node)
    graph.create(relation)
   
# 给节点添加属性(两者间的关系)
    zhuanti = Relationship(node, '应用于', relation)

# 节点实例化,并显示在neo4j中
    graph.create(zhuanti)

       打开网址,此时绘制的图谱如下图所示:

       但由图可以发现,图谱显示的是构建每个“图形化编程”与各专题节点关系,联系分散了,不是我们想要的只有一个父节点“图形化编程”,拥有多个专题子节点的关系。因此我们需要消除重复节点。

五、消除重复节点及重复关系

1.消除重复节点:在Neo4j上输入以下语句(注意:不是写在python的代码中,是网址的运行框)

 # 删除专题重复的节点
   graph.run('MATCH (n:zhuanti) WITH n.name AS name, COLLECT(n) AS nodelist, COUNT(*) AS count WHERE count > 1 CALL apoc.refactor.mergeNodes(nodelist) YIELD node RETURN node')

 # 删除“图形化编程”重复的节点
   graph.run('MATCH (n:title) WITH n.name AS name, COLLECT(n) AS nodelist, COUNT(*) AS count WHERE count > 1 CALL apoc.refactor.mergeNodes(nodelist) YIELD node RETURN node') 

消除专题重复节点,运行结果如下图所示:

消除“图形化编程”重复节点,运行结果如下图所示:

 此时绘制的图谱如下图所示:

  2.消除重复关系:如上图所示图谱中出现了许多重复关系,因此需要消除。同理在Neo4j上输入以下语句

# 删除重复关系
  graph.run('MATCH (a)-[r:应用于]- >(b) WITH a,b,TAIL (COLLECT(r)) as rr WHERE size(rr)>0 FOREACH (r IN rr | DELETE r)')

六、结果展示

有关Neo4j简单构建知识图谱实例的更多相关文章

  1. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  2. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  3. ruby - 简单获取法拉第超时 - 2

    有没有办法在这个简单的get方法中添加超时选项?我正在使用法拉第3.3。Faraday.get(url)四处寻找,我只能先发起连接后应用超时选项,然后应用超时选项。或者有什么简单的方法?这就是我现在正在做的:conn=Faraday.newresponse=conn.getdo|req|req.urlurlreq.options.timeout=2#2secondsend 最佳答案 试试这个:conn=Faraday.newdo|conn|conn.options.timeout=20endresponse=conn.get(url

  4. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  5. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  6. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  7. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

  8. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

  9. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

    我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

  10. ruby - 在 Ruby 中构建长字符串的简洁方法 - 2

    在编写Ruby(客户端脚本)时,我看到了三种构建更长字符串的方法,包括行尾,所有这些对我来说“闻起来”有点难看。有没有更干净、更好的方法?变量递增。ifrender_quote?quote="NowthatthereistheTec-9,acrappyspraygunfromSouthMiami."quote+="ThisgunisadvertisedasthemostpopularguninAmericancrime.Doyoubelievethatshit?"quote+="Itactuallysaysthatinthelittlebookthatcomeswithit:themo

随机推荐