基于Neo4j的个性化Pagerank算法文章推荐系统实践
新版的Neo4j图形算法库(algo)中增加了个性化Pagerank的支持,我一直想找个有意思的应用来验证一下此算法效果。最近我看Peter Lofgren的一篇论文《高效个性化Pagerank算法》(Efficient Algorithms for Personalized PageRank)(https://arxiv.org/pdf/1512.04633.pdf),在论文中,有一个比较有趣的示例:
我们想在论文引用网络中进行个性化搜索的尝试,但是要怎样设置个性化PageRank的参数,才能得到不同的排序结果?论文引用数据采用Citeseer检索中开放的。我们计划创建一个论文查询应用,用户输入一个关键词和一个作者名称,得到所有包含此关键词的论文,排序是从输入作者的角度去考虑。对于每一位作者,其所有论文都给以相同的权重,然后再使用个性化PageRank对关键词搜索出来的论文进行排序。例如,关键词“entropy”对于不同的作者有不同的含义,这样,我们就可以从不同的角度去比较关键词“entropy”搜索出来的结果。
接下来,我们就使用Neo4j来重建这个场景
前提
- Neo4j
- Neo4j图像库(algo)
- Neo4jAPOC库
- Graphaware的NLP插件
我们需要下载所有插件并做如下配置:
- dbms.unmanaged_extension_classes=com.graphaware.server=/graphaware
com.graphaware.runtime.enabled=true
com.graphaware.module.NLP.1=com.graphaware.nlp.module.NLPBootstrapper
dbms.security.procedures.whitelist=ga.nlp.*,algo.*,apoc.*
dbms.security.procedures.unrestricted=apoc.*,algo.*
apoc.import.file.enabled=true
图模型
从上图可见,我们的模型很简单,模型里的结点分为两类,标签分别为Author和Article,每个Author节点有一个或多个到Article节点的AUTHOR关系,同时,Article节点与其他Article节点还有REFERENCE关系。
为了优化请求,此图模型还需要定义一些索引。分别在Article节点的index属性和Author节点的name属性上建立唯一约束。
- CALL apoc.schema.assert(
{},
{Article:['index'],Author:['name']})
数据导入
我们使用aminer.org网站上提供的论文引用数据(https://static.aminer.cn/lab-datasets/citation/dblp.v10.zip),这是此数据的最新版本,最重要的是他以json方式存储的。
关于此数据库的更多信息可以看这篇论文《ArnetMiner:学术社交网络的提取与挖掘》(http://keg.cs.tsinghua.edu.cn/jietang/publications/KDD08-Tang-et-al-ArnetMiner.pdf)
译者言:《ArnetMiner:学术社交网络的提取与挖掘》一文的第一作者是清华大学唐杰教授
将数据导入到Neo4j中分为两步,第一步导入所有论文及他们的作者,第二步建立这些论文的引用关系。
导入数据我们使用 apoc.periodic.iterate 进行批量导入。
导入论文及作者
- CALL apoc.periodic.iterate(
'UNWIND ["dblp-ref-0.json","dblp-ref-1.json","dblp-ref-2.json","dblp-ref-3.json"] as file
CALL apoc.load.json("file:///neo4j/import/" + file)
yield value return value',
'MERGE (a:Article{index:value.id})
ON CREATE SET a += apoc.map.clean(value,["id","authors","references"],[0])
WITH a,value.authors as authors
UNWIND authors as author
MERGE (b:Author{name:author})
MERGE (b)-[:AUTHOR]->(a)'
,{batchSize: 10000, iterateList: true})
建立引用关系
- CALL apoc.periodic.iterate(
'UNWIND ["dblp-ref-0.json","dblp-ref-1.json","dblp-ref-2.json","dblp-ref-3.json"] as file
CALL apoc.load.json("file:///neo4j/import/" + file)
yield value return value',
'MERGE (a:Article{index:value.id})
WITH a,value.references as references
UNWIND references as reference
MERGE (b:Article{index:reference})
MERGE (a)-[:REFERENCES]->(b)'
,{batchSize: 10000, iterateList: true})
PageRank算法
PageRank设计之初是用来分析网页重要性的。它主要考虑的是网站拥有的连接个数和质量,如一网站,从reddit首页有一个链接到它,和从我的blog有一个链接到它,那么这两个链接的结果就完全不同了。
而这样一过程很容易应用到论文的引用网络上,论文的引用可以视为一篇文章对另一篇文章投了一个“赞成”票,而哪篇文章的“赞成”票最多?这正是PageRank最擅长解决的问题。
使用PageRank算法在全球论文引用网络上可以找到在图中最重要的文章和最有影响力的文章。
运行PageRank并把结果存储到结点的属性中
- CALL algo.pageRank('Article', 'REFERENCES')
通过pagerank得到最重要的文章
- MATCH (a:Article)
RETURN a.title as article,
a.pagerank as score
ORDER BY score DESC
LIMIT 10
运行结果如下:
自然语言处理(NLP)
如果我们要通过关键词来推荐文件,那么就需要从图中提取关键词。这里要感谢Graphaware的NLP插件,让这一过程非常简单,即使你完全不了解NLP算法也可以做NLP相关工作。
NLP过程将会在我们的图模型上增加一些节点和关系,具体如下图所示:
定义NLP模型
为了优化NLP处理,这里需要定义一些特殊的约束和索引。
- CALL ga.nlp.createSchema()
增加处理管道
定义一些处理管道的配置,关于处理管道的更多信息见这里(https://github.com/graphaware/neo4j-nlp#pipelines-and-components)
- CALL ga.nlp.processor.addPipeline({
textProcessor: 'com.graphaware.nlp.processor.stanford.StanfordTextProcessor',
name: 'defaultPipeline',
threadNumber: 4
processingSteps: {tokenize: true,
ner: true,
dependency: false}})
设置默认管道
- CALL ga.nlp.processor.pipeline.default('defaultPipeline')
文本标注
原始的文本被拆成了单词、段落和函数。这里对文本的分析还仅仅只是一个开始。
如果想了解更多关于文本标注,推荐你看Christophe Willemsen写的这篇文章《用Neo4j和NLP插件逆向工程书籍存储》(https://graphaware.com/neo4j/2017/07/24/reverse-engineering-book-stories-nlp.html)
- CALL apoc.periodic.iterate(
"MATCH (n:Article) WHERE exists (n.title) RETURN n",
"CALL ga.nlp.annotate({text: n.title, id: id(n)})
YIELD result MERGE (n)-[:HAS_ANNOTATED_TEXT]->(result)",
{batchSize:1, iterateList:true})
关键词提取
TextRank算法是一种相对简单、无监督的文本摘要方法,其可以直接进行主题提取。它的目标就是运用检索关键词及构建词共现关系图,得到对文档具有描述性的关键短语,而PageRank算法则对词的重要性进行排序。
---取之《使用图进行高效无监督关键词提取》(https://graphaware.com/neo4j/2017/10/03/efficient-unsupervised-topic-extraction-nlp-neo4j.html)
- CALL apoc.periodic.iterate(
"MATCH (a:AnnotatedText) RETURN a",
"CALL ga.nlp.ml.textRank({annotatedText: a}) YIELD result
RETURN distinct 'done' ",
{batchSize:1,iterateList:true}
获取文章标题中出现次数最多的10个关键词
- MATCH (k:Keyword)-[:DESCRIBES]->()
WHERE k.numTerms > 1
RETURN k.value as Keyphrase,
count(*) AS n_articles
ORDER BY n_articles DESC
LIMIT 10
结果如下:
最基本的文章推荐
如果你跟着本文一步一步执行下来,那么你现在已经有了一个最基本的基于PageRank分数和NLP关键词提取的文章推荐系统。
关键词“social networks”的前十推荐文章
- MATCH (k:Keyword)-[:DESCRIBES]->()<-[:HAS_ANNOTATED_TEXT]-(a:Article)
WHERE k.value = "social networks"
RETURN a.title as title, a.pagerank as p
ORDER BY p DESC
LIMIT 10
结果如下:
个性化PageRank算法
个性化PageRank是从一个或多个源节点的视角给出其他节点的pagerank分。
我们再计算一次pagerank分数,但这次我们把描述中带有关键词“social networks”的文章作为源节点。
- MATCH (k:Keyword)-[:DESCRIBES]->()<-[:HAS_ANNOTATED_TEXT]-(a:Article)
WHERE k.value = "social networks"
WITH collect(a) as articles
CALL algo.pageRank.stream('Article', 'REFERENCES', {sourceNodes: articles})
YIELD nodeId, score
WITH nodeId,score order by score desc limit 10
MATCH (n) where id(n) = nodeId
RETURN n.title as article, score
可以看到Sergey Brin和Larry Page所著的《大型超文本搜索引擎解析》(http://infolab.stanford.edu/pub/papers/google.pdf) 排在第一位。因此,可以看出,谷歌早期在图和PageRank方面的研究对社交网络方面有着巨大的影响。
个性化的推荐系统
需要再次重申,本文的目标是要重现这个场景
关键词“entropy”对于不同的人意味着不同的东西,我们希望从不同的角度还比较关键词“entropy"的结果。
首先我们找到某一作者的所有文章,这些文章将会作为个性化Pagerank的源节点。接着,我们运行pagerank算法并投影关键词”entropy“描述的文章节点,同时也投影这些文章节点之间的REFERENCES关系。
我们可以通过cypher投影语句过滤掉不需要的关系
只有在源节点和目标节点都被节点查询语句中所描述时,其在关系查询语句的关系才会被投影。源节点和目标节点任一个不在节点查询语句中描述时,则此关系会被忽略。
推荐示例
下面给出的是Jose C. Principe视角下搜索关键词“entropy”所得到的推荐文章。
- MATCH (a:Article)<-[:AUTHOR]-(author:Author)
WHERE author.name="Jose C. Principe"
WITH collect(a) as articles
CALL algo.pageRank.stream(
'MATCH (a:Article)-[:HAS_ANNOTATED_TEXT]->()<-[:DESCRIBES]-(k:Keyword)
WHERE k.value contains "entropy" RETURN distinct id(a) as id',
'MATCH (a1:Article)-[:REFERENCES]->(a2:Article)
RETURN id(a1) as source,id(a2) as target',
{sourceNodes: articles,graph:'cypher'})
YIELD nodeId, score
WITH nodeId,score order by score desc limit 10
MATCH (n) where id(n) = nodeId
RETURN n.title as article, score
HongWang视角下搜索关键词“entropy”所得到的推荐文章
- MATCH (a:Article)<-[:AUTHOR]-(author:Author)
WHERE author.name="Hong Wang"
WITH collect(a) as articles
CALL algo.pageRank.stream(
'MATCH (a:Article)-[:HAS_ANNOTATED_TEXT]->()<-[:DESCRIBES]-(k:Keyword)
WHERE k.value contains "entropy" RETURN distinct id(a) as id',
'MATCH (a1:Article)-[:REFERENCES]->(a2:Article)
RETURN id(a1) as source,id(a2) as target',
{sourceNodes: articles,graph:'cypher'})
YIELD nodeId, score
WITH nodeId,score order by score desc limit 10
MATCH (n) where id(n) = nodeId
RETURN n.title as article, score
结论
正如我们所料,从两位作者的不同视角进行搜索,得到的推荐结果也是不一样的。
Neo4j本身很强大,在特定的领域内使用相应的插件时,他会变的更强大。
基于Neo4j的个性化Pagerank算法文章推荐系统实践的更多相关文章
- elasticsearch算法之推荐系统的相似度算法(一)
一.推荐系统简介 推荐系统主要基于对用户历史的行为数据分析处理,寻找得到用户可能感兴趣的内容,从而实现主动向用户推荐其可能感兴趣的内容: 从物品的长尾理论来看,推荐系统通过发掘用户的行为,找到用户的个 ...
- 推荐系统实践 0x06 基于邻域的算法(1)
基于邻域的算法(1) 基于邻域的算法主要分为两类,一类是基于用户的协同过滤算法,另一类是基于物品的协同过滤算法.我们首先介绍基于用户的协同过滤算法. 基于用户的协同过滤算法(UserCF) 基于用户的 ...
- 推荐系统实践 0x07 基于邻域的算法(2)
基于邻域的算法(2) 上一篇我们讲了基于用户的协同过滤算法,基本流程就是寻找与目标用户兴趣相似的用户,按照他们对物品喜好的对目标用户进行推荐,其中哪些相似用户的评分要带上目标用户与相似用户的相似度作为 ...
- 14、RALM: 实时 look-alike 算法在推荐系统中的应用
转载:https://zhuanlan.zhihu.com/p/71951411 RALM: 实时 look-alike 算法在推荐系统中的应用 0. 导语 本论文题为<Real-time At ...
- 张洋:浅析PageRank算法
本文引自http://blog.jobbole.com/23286/ 很早就对Google的PageRank算法很感兴趣,但一直没有深究,只有个轮廓性的概念.前几天趁团队outing的机会,在动车上看 ...
- 浅析PageRank算法
很早就对Google的PageRank算法很感兴趣,但一直没有深究,只有个轮廓性的概念.前几天趁团队outing的机会,在动车上看了一些相关的资料(PS:在动车上看看书真是一种享受),趁热打铁,将所看 ...
- PageRank算法第一篇
摘要by crazyhacking: 一 搜索引擎的核心问题就是3个:1.建立资料库,通过爬虫系统实现:2.建立一种数据结构,可以根据关键词找到含有这个词的页面.通过索引系统(倒排索引)实现.3排序系 ...
- (转载)Google的PageRank算法
本文由张洋(敲代码的张洋)投稿于伯乐在线. 本文转载于:http://blog.jobbole.com/23286/ 很早就对Google的PageRank算法很感兴趣,但一直没有深究,只有个轮廓性的 ...
- PageRank算法和谷歌搜索讲解
PageRank算法和谷歌搜索讲解 吴裕雄 PageRank算法实际上就是Google使用它来计算每个网页价值的算法. Google每次的搜索结果都有成百上千万甚至上亿个相关的查询网页链接.如果将所有 ...
随机推荐
- OpenCV-Python 使用OCR手写数据集运行KNN | 五十四
目标 在本章中 我们将使用我们在kNN上的知识来构建基本的OCR应用程序. 我们将尝试使用OpenCV自带的数字和字母数据集. 手写数字的OCR 我们的目标是构建一个可以读取手写数字的应用程序.为此, ...
- 一文上手Tensorflow2.0(四)
系列文章目录: Tensorflow2.0 介绍 Tensorflow 常见基本概念 从1.x 到2.0 的变化 Tensorflow2.0 的架构 Tensorflow2.0 的安装(CPU和GPU ...
- Kaggle竞赛入门(二):如何验证机器学习模型
本文翻译自kaggle learn,也就是kaggle官方最快入门kaggle竞赛的教程,强调python编程实践和数学思想(而没有涉及数学细节),笔者在不影响算法和程序理解的基础上删除了一些不必要的 ...
- 解决ASP.NET MVC返回的JsonResult 中 日期类型数据格式问题,和返回的属性名称转为“驼峰命名法”和循环引用问题
DateTime类型数据格式问题 问题 在使用ASP.NET MVC 在写项目的时候发现,返回给前端的JSON数据,日期类型是 Date(121454578784541) 的格式,需要前端来转换一下才 ...
- memcached-tool 工具
perl memcached-tool server_ip:port stats 输出说明: pid memcache服务器的进程ID uptime 服务器已经运行的秒数 time 服务器当前的uni ...
- pycharm 秘籍:快捷键技巧等
Pycharm基本使用 安装 下载地址:https://www.jetbrains.com/pycharm/download 选择Professional 专业版 Comunnity社区版是免费的,但 ...
- python学习之由
2019python之年: 2019是个挫折之年,但又是幸运之年,这一年创业遭遇滑铁卢,几与破产,充满着迷茫,路在何方?? 开始接触python是在微信朋友圈,结缘于广告,觉得很有意思,但一直没有深入 ...
- Html 慕课园编程练习9-22
题目要求: 制作一个表格,显示班级的学生信息. 要求: 1. 鼠标移到不同行上时背景色改为色值为 #f2f2f2,移开鼠标时则恢复为原背景色 #fff 2. 点击添加按钮,能动态在最后添加一行 3. ...
- PTA数据结构与算法题目集(中文) 7-11
PTA数据结构与算法题目集(中文) 7-11 7-11 关键活动 (30 分) 假定一个工程项目由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其它一些子任务后才能执行.“任务调度 ...
- HDU1074:Doing Homework(状压DP)
Doing Homework Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)To ...