Neo4j:带密码的TF / IDF(和变体)

几周前,我写了一篇博客文章,介绍了如何使用scikit-learn在HIMYM成绩单上运行TF / IDF,以按情节找到最重要的短语,然后我很好奇在Neo4j中很难做到。

我首先将Wikipedia的TF / IDF示例之一翻译为cypher,以查看该算法的外观:

WITH 3 as termFrequency, 2 AS numberOfDocuments, 1 as numberOfDocumentsWithTerm
WITH termFrequency, log10(numberOfDocuments / numberOfDocumentsWithTerm) AS inverseDocumentFrequency
return termFrequency * inverseDocumentFrequency0.9030899869919435

接下来,我需要检查HIMYM情节成绩单,并提取每个情节中的短语及其对应的计数。 我使用scikit-learn的CountVectorizer进行了此操作,并将结果写入了CSV文件。

这是该文件的预览:

$ head -n 10 data/import/words_scikit.csv
EpisodeId,Phrase,Count
1,2005,1
1,2005 seven,1
1,2005 seven just,1
1,2030,3
1,2030 kids,1
1,2030 kids intently,1
1,2030 narrator,1
1,2030 narrator kids,1
1,2030 son,1

现在,使用LOAD CSV工具将其导入Neo4j:

// phrases
USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:///Users/markneedham/projects/neo4j-himym/data/import/words_scikit.csv" AS row
MERGE (phrase:Phrase {value: row.Phrase});
// episode -> phrase
USING PERIODIC COMMIT 1000
LOAD CSV WITH HEADERS FROM "file:///Users/markneedham/projects/neo4j-himym/data/import/words_scikit.csv" AS row
MATCH (phrase:Phrase {value: row.Phrase})
MATCH (episode:Episode {id: TOINT(row.EpisodeId)})
MERGE (episode)-[:CONTAINED_PHRASE {times:TOINT(row.Count)}]->(phrase);

现在,所有数据都可以转换为TF / IDF查询,以利用我们的图表。 我们将从第1集开始:

match (e:Episode)
WITH COUNT(e) AS numberOfDocuments
match (p:Phrase)<-[r:CONTAINED_PHRASE]-(e:Episode {id: 1})
WITH numberOfDocuments, p, r.times AS termFrequency
MATCH (p)<-[:CONTAINED_PHRASE]->(otherEpisode)
WITH p, COUNT(otherEpisode) AS numberOfDocumentsWithTerm, numberOfDocuments, termFrequency
WITH p, numberOfDocumentsWithTerm,  log10(numberOfDocuments / numberOfDocumentsWithTerm) AS inverseDocumentFrequency, termFrequency, numberOfDocuments
RETURN p.value, termFrequency, numberOfDocumentsWithTerm, inverseDocumentFrequency, termFrequency * inverseDocumentFrequency AS score
ORDER BY score DESC
LIMIT 10==> +-----------------------------------------------------------------------------------+
==> | p.value                | termFrequency | numberOfDocumentsWithTerm | inverseDocumentFrequency | score              |
==> +-----------------------------------------------------------------------------------+
==> | "olives"               | 18            | 2                         | 2.0170333392987803       | 36.306600107378046 |
==> | "yasmine"              | 13            | 1                         | 2.3180633349627615       | 30.1348233545159   |
==> | "signal"               | 11            | 5                         | 1.6127838567197355       | 17.740622423917088 |
==> | "goanna"               | 10            | 4                         | 1.7160033436347992       | 17.16003343634799  |
==> | "flashback date"       | 6             | 1                         | 2.3180633349627615       | 13.908380009776568 |
==> | "scene"                | 17            | 37                        | 0.6989700043360189       | 11.88249007371232  |
==> | "flashback date robin" | 5             | 1                         | 2.3180633349627615       | 11.590316674813808 |
==> | "ted yasmine"          | 5             | 1                         | 2.3180633349627615       | 11.590316674813808 |
==> | "smurf pen1s"          | 5             | 2                         | 2.0170333392987803       | 10.085166696493902 |
==> | "eye patch"            | 5             | 2                         | 2.0170333392987803       | 10.085166696493902 |
==> +-----------------------------------------------------------------------------------+
==> 10 rows

我们计算出的分数不同于scikit-learn的分数,但是相对顺序似乎不错,所以很好。 在Neo4j中计算这一点的整洁之处在于,我们现在可以更改等式的“逆文档”部分,例如,找出一个季节而不是一个情节中最重要的短语:

match (:Season) 
WITH COUNT(*) AS numberOfDocuments
match (p:Phrase)<-[r:CONTAINED_PHRASE]-(:Episode)-[:IN_SEASON]->(s:Season {number: "1"})
WITH p, SUM(r.times) AS termFrequency, numberOfDocuments
MATCH (p)<-[:CONTAINED_PHRASE]->(otherEpisode)-[:IN_SEASON]->(s:Season)
WITH p, COUNT(DISTINCT s) AS numberOfDocumentsWithTerm, termFrequency, numberOfDocuments
WITH p, numberOfDocumentsWithTerm,  log10(numberOfDocuments / numberOfDocumentsWithTerm) AS inverseDocumentFrequency, termFrequency, numberOfDocuments
RETURN p.value, termFrequency, numberOfDocumentsWithTerm, inverseDocumentFrequency, termFrequency * inverseDocumentFrequency AS score
ORDER BY score DESC
LIMIT 10==> +-----------------------------------------------------------------------------------+
==> | p.value         | termFrequency | numberOfDocumentsWithTerm | inverseDocumentFrequency | score              |
==> +-----------------------------------------------------------------------------------+
==> | "moby"          | 46            | 1                         | 0.9542425094393249       | 43.895155434208945 |
==> | "int"           | 71            | 3                         | 0.47712125471966244      | 33.87560908509603  |
==> | "ellen"         | 53            | 2                         | 0.6020599913279624       | 31.909179540382006 |
==> | "claudia"       | 104           | 4                         | 0.3010299956639812       | 31.307119549054043 |
==> | "ericksen"      | 59            | 3                         | 0.47712125471966244      | 28.150154028460083 |
==> | "party number"  | 29            | 1                         | 0.9542425094393249       | 27.67303277374042  |
==> | "subtitle"      | 27            | 1                         | 0.9542425094393249       | 25.76454775486177  |
==> | "vo"            | 47            | 3                         | 0.47712125471966244      | 22.424698971824135 |
==> | "ted vo"        | 47            | 3                         | 0.47712125471966244      | 22.424698971824135 |
==> | "future ted vo" | 45            | 3                         | 0.47712125471966244      | 21.47045646238481  |
==> +-----------------------------------------------------------------------------------+
==> 10 rows

从该查询中我们了解到,“ Moby”在整个系列中仅被提及一次,实际上所有提及都在同一集中 。 “ int”的出现似乎更多是数据问题–在某些情节中,成绩单描述了位置,但在许多情节中却没有:

$ ack -iw "int" data/import/sentences.csv
2361,8,1,8,"INT. LIVING ROOM, YEAR 2030"
2377,8,1,8,INT. CHINESE RESTAURANT
2395,8,1,8,INT. APARTMENT
2412,8,1,8,INT. APARTMENT
2419,8,1,8,INT. BAR
2472,8,1,8,INT. APARTMENT
2489,8,1,8,INT. BAR
2495,8,1,8,INT. APARTMENT
2506,8,1,8,INT. BAR
2584,8,1,8,INT. APARTMENT
2629,8,1,8,INT. RESTAURANT
2654,8,1,8,INT. APARTMENT
2682,8,1,8,INT. RESTAURANT
2689,8,1,8,(Robin gets up and leaves restaurant) INT. HOSPITAL WAITING AREA

“ vo”代表语音,应该在停用词中删除它,因为它不会带来太多价值。 之所以显示在这里,是因为这些笔录在表示Future Ted说话时的方式不一致。

让我们看一下最后一个赛季,看看票价如何:

match (:Season)
WITH COUNT(*) AS numberOfDocuments
match (p:Phrase)<-[r:CONTAINED_PHRASE]-(:Episode)-[:IN_SEASON]->(s:Season {number: "9"})
WITH p, SUM(r.times) AS termFrequency, numberOfDocuments
MATCH (p)<-[:CONTAINED_PHRASE]->(otherEpisode:Episode)-[:IN_SEASON]->(s:Season)
WITH p, COUNT(DISTINCT s) AS numberOfDocumentsWithTerm, termFrequency, numberOfDocuments
WITH p, numberOfDocumentsWithTerm,  log10(numberOfDocuments / numberOfDocumentsWithTerm) AS inverseDocumentFrequency, termFrequency, numberOfDocuments
RETURN p.value, termFrequency, numberOfDocumentsWithTerm, inverseDocumentFrequency, termFrequency * inverseDocumentFrequency AS score
ORDER BY score DESC
LIMIT 10==> +-----------------------------------------------------------------------------------+
==> | p.value              | termFrequency | numberOfDocumentsWithTerm | inverseDocumentFrequency | score              |
==> +-----------------------------------------------------------------------------------+
==> | "ring bear"          | 28            | 1                         | 0.9542425094393249       | 26.718790264301095 |
==> | "click options"      | 26            | 1                         | 0.9542425094393249       | 24.810305245422448 |
==> | "thank linus"        | 26            | 1                         | 0.9542425094393249       | 24.810305245422448 |
==> | "vow"                | 39            | 2                         | 0.6020599913279624       | 23.480339661790534 |
==> | "just click"         | 24            | 1                         | 0.9542425094393249       | 22.901820226543798 |
==> | "rehearsal dinner"   | 23            | 1                         | 0.9542425094393249       | 21.947577717104473 |
==> | "linus"              | 36            | 2                         | 0.6020599913279624       | 21.674159687806647 |
==> | "just click options" | 22            | 1                         | 0.9542425094393249       | 20.993335207665147 |
==> | "locket"             | 32            | 2                         | 0.6020599913279624       | 19.265919722494797 |
==> | "cassie"             | 19            | 1                         | 0.9542425094393249       | 18.13060767934717  |
==> +-----------------------------------------------------------------------------------+

Barney&Robin的婚礼有几个特定的​​短语(“誓言”,“圆环熊”,“排练晚宴”),因此将这些放在首位是有道理的。 这里的“ linus”主要是指酒吧中与Lily进行交互的服务器,尽管对笔录进行了快速搜索后发现她还有一个Linus叔叔!

$ ack -iw "linus" data/import/sentences.csv  | head -n 5
18649,61,3,17,Lily: Why don't we just call Duluth Mental Hospital and say my Uncle Linus can live with us?
59822,185,9,1,Linus.
59826,185,9,1,"Are you my guy, Linus?"
59832,185,9,1,Thank you Linus.
59985,185,9,1,"Thank you, Linus."
...

通过执行此练习,我认为TF / IDF是探索非结构化数据的一种有趣方式,但是对于一个对我们来说真的很有趣的短语,它应该出现在多个情节/季节中。

实现该目标的一种方法是对这些功能进行更多加权,因此我将在下一步进行尝试。

  • 如果您想看看并加以改进,则本文中的所有代码都位于github上 。

翻译自: https://www.javacodegeeks.com/2015/03/neo4j-tfidf-and-variants-with-cypher.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

验证码的设计,随机数的生成

只要将charNum改变就可以自定义设计生成随机数的个数。 //获取验证码的代码 void GetValidateCode() { validStr ""; Random rd new Random(); //创建随机数对象 //产生由 charNum 个字母或数字组成的一个字符串 …

There are multiple modules with names that only differ in ca

react antd 警告错误 原因&#xff1a;引用组件的大小写 // 原代码&#xff1a; import AddOrEditFrom from /components/Process/AddOrEditFrom; // 修改后代码 import AddOrEditFrom from /components/Process/AddOrEditFrom;

每个人都必须阅读的10篇Java文章

一个月前&#xff0c;我们发布了每个人都必须阅读的10篇SQL文章列表。 我们相信jOOQ博客上的文章列表将为我们的读者带来非凡的价值。 jOOQ博客是同时关注Java和SQL的博客&#xff0c;因此&#xff0c;一个月后的今天&#xff0c;我们发布了同样令人兴奋的10条Java文章列表&…

LeetCode: Longest Common Prefix

string.erase没掌握好&#xff0c;悲了个剧&#xff0c;2次过 1 class Solution {2 public:3 string longestCommonPrefix(vector<string> &strs) {4 // Start typing your C/C solution below5 // DO NOT write int main() function6 s…

React antd Descriptions span属性无效问题

label“Status” span{3}&#xff0c;但是span为3无效 <Descriptions title"User Info" layout"vertical" bordered><Descriptions.Item label"Product">Cloud Database</Descriptions.Item><Descriptions.Item label&quo…

如何在生产中检测和诊断慢速代码

开发人员面临的最困难的任务之一是查找和诊断生产中运行缓慢的代码。 首先&#xff0c;您如何监控生产代码而不放慢速度&#xff1f; 当然&#xff0c;您无法通过分析器运行生产代码。 即使您具有计时代码的机制&#xff0c;那么如何诊断问题呢&#xff1f; 如果您无法在开发环…

uni-app动态绑定class和style

目录动态绑定calss动态绑定style动态绑定calss class"[{‘类名’:条件},{‘类名’:条件},{‘类名’:条件}]" 为不同条件的image绑定不同的样式 <image class"img1" :class"[{img1:index 0},{img2:index 1},{img3:index 2}]":src"avt…

移动小球

描述 你有一些小球&#xff0c;从左到右依次编号为1&#xff0c;2&#xff0c;3&#xff0c;…&#xff0c;n&#xff0c; 你可以执行两种指令。其中A X Y表示把小球X移动到小球Y左边&#xff0c;B X Y表示把小球X移动到小球Y右边。指令保证合法&#xff0c;即X不等于Y。 输入 …

流式传输大数据:Storm,Spark和Samza

有许多分布式计算系统可以实时或近实时处理大数据。 本文将从对三个Apache框架的简短描述开始&#xff0c;并试图对它们之间的某些相似之处和不同之处提供一个快速的高级概述。 阿帕奇风暴 在风暴 &#xff0c;你设计要求的T opology实时计算的图&#xff0c;然后喂到集群&…

那天有个小孩跟我说LINQ(四)

小孩LINQ系列导航&#xff1a;&#xff08;一&#xff09; &#xff08;二&#xff09; &#xff08;三&#xff09; &#xff08;四&#xff09; &#xff08;五&#xff09; &#xff08;六&#xff09; &#xff08;七&#xff09; &#xff08;八&#xff09; 转载于:http…

uniapp使用阿里云多色图标

下载&#xff0c;然后解压 输入cmd&#xff0c;然后enter 输入 npm install -g iconfont-tools 再输入 iconfont-tools&#xff0c;然后一直enter&#xff0c;直到结束 目录会多了个iconfont-weapp文件&#xff0c;点击去找到 iconfont-weapp-icon.css 导入和使用 t-icon开头 接…

针对Java中的XSD验证XML

有许多工具可用于根据XSD 验证XML文档 。 其中包括操作系统脚本和工具&#xff0c;例如xmllint &#xff0c;XML编辑器和IDE&#xff0c;甚至是在线验证器。 由于前面提到的方法的局限性或问题&#xff0c;我发现拥有自己的易于使用的XML验证工具很有用。 Java使编写这样的工具…

细学PHP 09 MySql

1:mysql是什么&#xff1f;答&#xff1a;mysql是一种开源的&#xff0c;小型的数据库和&#xff30;&#xff28;&#xff30;结合的非常紧密 比较流行的LAMP组合 指 linux apache mysql php 2:我怎么样用Mysql&#xff1f;答&#xff1a;下载mysql并安装&#xff0c;装完之后…

修改 this 指向

文章目录前言一、new关键字改变this指向二、 call&#xff08;&#xff09;三、apply&#xff08;&#xff09;四 、bind&#xff08;&#xff09;五、总结前言 修改 this 指向,四种方法 一、new关键字改变this指向 //构造函数版this function Fn(){this.user "追梦子…

默认方法和多重继承

最近卢卡斯JOOQ埃德尔发布和文章有关嵌套类及其使用。 这是一个有趣的话题&#xff0c;他的文章一如既往地有趣并且值得一读。 我只同意一个简短的声明&#xff0c;我们有一个简短的回复链&#xff0c;导致默认方法&#xff0c;以及为什么不能有类似的东西 class Outer {<n…

uniapp uni.request GET方式请求,不能直接传数组解决方法

这里写目录标题目录遇到的问题 GET请求方法传数组解决方案目录 遇到的问题 GET请求方法传数组 想传一个数组&#xff0c;但是后台接受到的数据与浏览器中显示的数据和前台代码传的不一样&#xff1b; 前台代码打印 浏览器显示数据 其中HerbalNameList &#xff0c;变成了字…

休眠CascadeType.LOCK陷阱

介绍 引入了Hibernate 显式锁定支持以及Cascade Types之后 &#xff0c;就该分析CascadeType.LOCK行为了。 休眠锁定请求触发内部LockEvent 。 关联的DefaultLockEventListener可以将锁定请求级联到锁定实体子级。 由于CascadeType.ALL也包括CascadeType.LOCK &#xff0c;因…

c++中在堆和栈中申请空间的差别

堆中和栈中申请的空间的比较, 我找到了下面的比较: 栈的情况&#xff1a;栈上分配空间的好处是快&#xff0c;而且对象生存期是自动的&#xff0c;离开当前域之后就自动析构回收。坏处就是栈空间有限&#xff0c;而且不能人为控制对象的生存期&#xff0c;比如你无法将一个函数…

推销自己的海盗猫王运营商

因此&#xff0c;Java没有Elvis运算符&#xff08;或者更正式的名称是null合并运算符或null安全成员选择&#xff09;……虽然我个人不太在意它&#xff0c;但有些人似乎很喜欢它。 当一位同事需要几天后&#xff0c;我坐下来探讨了我们的选择。 而且你知道什么&#xff01; 您…