你可以计算这种使用SPARQL的度量标准,虽然它有点难看。让我们假设一些这样的数据:
prefix dcterms: <http://purl.org/dc/terms/>
prefix : <http://example.org/books/>
:book1 a :Book ; dcterms:subject :subject1 , :subject2, :subject3 .
:book2 a :Book ; dcterms:subject :subject2 , :subject3, :subject4 .
:book3 a :Book ; dcterms:subject :subject4 , :subject5 .
有三本书。书籍1和2有两个共同的主题,另一个没有共同的主题。书2和3有一个共同的主题,但书2有2书3没有,而书3只有书2没有,书1和3没有共同的主题。
这里的技巧是使用一些嵌套的子查询,并在嵌套中获取不同级别的不同值(C10,C01和C11)。最深处的查询是
select ?book1 ?book2 (count(?left) as ?c10) where {
:Book ^a ?book1, ?book2 .
FILTER(!sameTerm(?book1,?book2))
OPTIONAL {
?book1 dcterms:subject ?left .
FILTER NOT EXISTS { ?book2 dcterms:subject ?left }
}
}
group by ?book1 ?book2
它抓住每一对不同的书,并计算左书的权利数量没有。通过将其包含在另一个查询中,我们可以获取正确的书中左侧没有的主题数量。这使得查询:
select ?book1 ?book2 (count(?right) as ?c01x) (sample(?c10) as ?c10x) where {
{
select ?book1 ?book2 (count(?left) as ?c10) where {
:Book ^a ?book1, ?book2 .
FILTER(!sameTerm(?book1,?book2))
OPTIONAL {
?book1 dcterms:subject ?left .
FILTER NOT EXISTS { ?book2 dcterms:subject ?left }
}
}
group by ?book1 ?book2
}
OPTIONAL {
?book2 dcterms:subject ?right .
FILTER NOT EXISTS { ?book1 dcterms:subject ?right }
}
}
group by ?book1 ?book2
注意,我们仍然以向外传递值来选择?book1
和?book2
和sample(?c10) as ?c10x
。 (我们必须使用?c10x
,因为名称?c10
已在此范围内使用。最后,我们在一个多个查询包裹这得到共同科目,并做了计算,这给了我们:
prefix dcterms: <http://purl.org/dc/terms/>
prefix : <http://example.org/books/>
select ?book1 ?book2
(count(?both) as ?c11)
(sample(?c10x) as ?c10)
(sample(?c01x) as ?c01)
(count(?both)/(count(?both) + sample(?c10x) + sample(?c01x)) as ?sim)
where {
{
select ?book1 ?book2 (count(?right) as ?c01x) (sample(?c10) as ?c10x) where {
{
select ?book1 ?book2 (count(?left) as ?c10) where {
:Book ^a ?book1, ?book2 .
FILTER(!sameTerm(?book1,?book2))
OPTIONAL {
?book1 dcterms:subject ?left .
FILTER NOT EXISTS { ?book2 dcterms:subject ?left }
}
}
group by ?book1 ?book2
}
OPTIONAL {
?book2 dcterms:subject ?right .
FILTER NOT EXISTS { ?book1 dcterms:subject ?right }
}
}
group by ?book1 ?book2
}
OPTIONAL {
?both ^dcterms:subject ?book1, ?book2 .
}
}
group by ?book1 ?book2
order by ?book1 ?book2
这个相当可怕的查询,应用到我们的数据,计算的结果:
$ arq --data data.n3 --query similarity.sparql
--------------------------------------------
| book1 | book2 | c11 | c10 | c01 | sim |
============================================
| :book1 | :book2 | 2 | 1 | 1 | 0.5 |
| :book1 | :book3 | 0 | 3 | 2 | 0.0 |
| :book2 | :book1 | 2 | 1 | 1 | 0.5 |
| :book2 | :book3 | 1 | 2 | 1 | 0.25 |
| :book3 | :book1 | 0 | 2 | 3 | 0.0 |
| :book3 | :book2 | 1 | 1 | 2 | 0.25 |
--------------------------------------------
如果FILTER(!sameTerm(?book1,?book2))
行被删除,所以每本书本身的这种相似也被计算,我们看到正确的值(1.0):
$ arq --data data.n3 --query similarity.sparql
--------------------------------------------
| book1 | book2 | c11 | c10 | c01 | sim |
============================================
| :book1 | :book1 | 3 | 0 | 0 | 1.0 |
| :book1 | :book2 | 2 | 1 | 1 | 0.5 |
| :book1 | :book3 | 0 | 3 | 2 | 0.0 |
| :book2 | :book1 | 2 | 1 | 1 | 0.5 |
| :book2 | :book2 | 3 | 0 | 0 | 1.0 |
| :book2 | :book3 | 1 | 2 | 1 | 0.25 |
| :book3 | :book1 | 0 | 2 | 3 | 0.0 |
| :book3 | :book2 | 1 | 1 | 2 | 0.25 |
| :book3 | :book3 | 2 | 0 | 0 | 1.0 |
--------------------------------------------
如果你并不需要保存各种Cmn值,那么你可能能够优化这个,例如,通过计算最内层查询中的C01和中间查询旁边的C10,但是不是单独向上投影,而是产品只是它们的总和(C10 + C01),以便在计算C11的最外层查询中,可以执行(C11 /(C11 +(C10 + C01)))。
这是不是很清楚你问什么。您可以在不使用Netbeans的情况下使用Protégé和SPARQL。如果我明白你对X和Y之间的相似度度量的问题,那么你可以在SPARQL中这样做,因为SPARQL包含了一些数学运算。对于评估数学公式,有一个[答案](http://stackoverflow.com/a/17319546/1281433),涉及评估一些序列公式,如果你需要做一些棘手的操作,可能会有一些帮助。不过,你的情况可能会更简单。 –
我不知道你什么时候想要使用NetBeans。我倾向于使用Eclipse,但我有很多命令行工具可用于处理SPARQL,所以实际上我可以在不使用任何IDE的情况下做很多事情。我添加了一个答案,显示了如何使用SPARQL查询(我使用Jena的命令行工具执行的)来计算这些相似性度量标准。 –
是的我想计算X和Y之间的相似度。但我也适用于所有书籍的这个公式。例如X和Y,再次X和Z再次X和S ,,,,,和Y和Z,...所以我不知道如何在sparql中实现计算成对。 – sima412