本体,OWL,Sparql:建模 "something is not there" 和性能考虑

Ontologies, OWL, Sparql: Modelling that "something is not there" and performance considerations

我们想要建模 "something is not there" 而不是缺失信息,例如"a patient did not get chemotherapy" 或 "a patient does not have dyspnea" 的明确陈述不同于关于患者是否有呼吸困难的缺失信息。

我们考虑了几种方法,例如

我们觉得第三个选项是最 "ontologically correct" 的表达方式。然而,在使用它的过程中,我们在简单的场景中遇到了严重的性能问题。

我们将 Sesame 与 OWLIM-Lite 商店一起使用,并将 NCI 同义词库(280MB,大约 80,000 个概念)和另一个非常小的 ontology 导入商店并添加了两个人,其中一个拥有 complementOf/restriction class.

以下查询一直执行,我在 15 分钟后终止了它:

select *
where {
  ?s a [ rdf:type owl:Class;
                      owl:complementOf [
                        rdf:type owl:Restriction ;
                        owl:onProperty roo:has_finding;
                        owl:someValuesFrom nci:Dyspnea;
                  ]
                ] .
} Limit 100

有人知道为什么吗?我会假设这种方法会创建很多空白节点,并且查询引擎必须遍历整个 NCI 词库并将所有空白节点与这个节点进行比较?

如果我将这个三元组放在一个单独的图中并且只查询该图,查询 returns 即时结果。

总结一下。两个基本问题是:

编辑 1

我们讨论了提议的选项。它实际上帮助我们阐明了我们真正想要实现的目标:

我们试过选项:

这样,编写 Sparql 查询的人只需知道:

我们非常感谢对这些结论的一些反馈!

关于建模问题,我想提供第四种选择,实际上是您的选项 1 和 2 的混合:为这些引入单独的 class(层次结构) 'excluded/missing' 症状、疾病或治疗,并有特定的排除作为实例:

 :Exclusion a owl:Class .
 :ExcludedSymptom rdfs:subClassOf :Exclusion .
 :ExcludedTreatment rdfs:subClassOf :Exclusion .

 :excludedDyspnea a :ExcludedSymptom .
 :excludedChemo a :ExcludedTreatment .

 :Patient a owl:Class ;
          owl:equivalentClass [ a owl:Restriction ;
                                owl:onProperty :excluded ;
                                owl:allValuesFrom :Exclusion ] .

 // john is a patient without Dyspnea 
 :john a :Patient ;
       :excluded :excludedDyspnea .

可选地,您可以 link 语义排除实例 treatment/symptom/diseases:

  :excludedDyspnea :ofSymptom :Dyspnea . 

在我看来,这与您的其他选择一样 "ontologically correct"(老实说,这种事情非常主观),并且可能更容易维护、查询和推理。

至于你的第二个问题:虽然我不能代表你正在使用的特定推理器的行为,但一般来说,任何涉及 complementOf 的构造在计算上都非常繁重,但也许更重要的是,它可能无法捕捉到您的意图。

OWL 有一个开放世界假设,这(从广义上讲)意味着我们不能仅仅因为某个事实目前未知就断定某个事实是不真实的。您的 complementOf 构造在逻辑上将是空的 class,因为对于任何人 X,即使我们目前不知道 X 已被诊断出患有呼吸困难,也存在将来该事实可能会为人所知,因此 X 不会出现在补语 class 中。

编辑

针对您的编辑,建议使用单个 :hasFinding 属性,我认为总体上看起来不错,但我可能会稍微修改一下:

   :patient1 a :Patient;
             :hasFinding :dyspneaFinding1 .

   :dyspneaFinding1 a :Finding ;
                    :of :Dyspnea ;
                    :conclusion false .

您现在已经更清楚地将 'finding' 作为一个概念与 symptom/treatment 分开,后者是 的发现。此外,结果是肯定的还是否定的是明确建模的(而不是由 'excluded' 属性 或 'Exclusion' 类型的 presence/absense 暗示)。

(顺便说一句:因为我们 link 一个人在这里通过非打字关系(... :of :Dyspnea)具有 class,所以我们必须依赖 OWL 2 punning使其在 OWL DL 中有效)

查询有呼吸困难发现(无论是阳性还是阴性)的患者:

 SELECT ?x 
 WHERE {
    ?x a :Patient; 
       :hasFinding [ :of :Dyspnea ] .
 }

并查询确认没有呼吸困难的患者:

 SELECT ?x 
 WHERE {
    ?x a :Patient; 
       :hasFinding [ :of :Dyspnea ;
                     :conclusion false ] .
 }

如果您的疾病被表示为个体,那么您可以使用否定对象 属性 断言从字面上说,例如

¬hasFinding(约翰,呼吸困难)

NegativeObjectPropertyAssertion(hasFinding john Dyspnea)

当然,如果你有很多事情不是这样的,那么这可能会有点牵扯。不过,它可能是语义上最正确的。这也意味着您的查询可以直接匹配 ontology 中的数据,这可能会更快获得结果。 (当然,当负对象 属性 成立时,您仍然会遇到尝试 推断 的问题。)

不过,如果疾病表示为 classes,这将不起作用。如果疾病由 classes 表示,那么您可以使用 class 表达式,类似于您的建议。例如,

(∀ hasFinding.¬呼吸困难)(约翰)

ClassAssertion(ObjectAllValuesFrom(hasFinding ObjectComplementOf(呼吸困难))约翰)

这与您的第三个选项类似,但我想知道它的性能是否更好。这似乎是表达您想说的内容的一种更直接的方式(即,如果某人患有某种疾病,则它不是这些疾病中的一种)。

不过我同意 ;这里有很多主观性,要获得它 "right" 实际上只是找到一些可以合理使用、对你来说表现足够好的东西,而且这似乎并不完全不自然。