【问题标题】:obtain the matrix in protege获取 protege 中的矩阵
【发布时间】:2013-07-29 13:04:00
【问题描述】:

我的工作是关于推荐系统的图书馆书籍。作为输入,我需要书籍分类本体。在我的本体中对图书馆书籍进行分类。此分类有 14 个类别,除了兄弟类 Author、book、Isbn。 book 类的个人是 book 的主题(约 600 个主题),author 类的个人是 name 的作者,也是 isbn 类。我用 protege 4.1 设计了这个本体。

我也手动收集并获得了部分属于书籍的类别。对象属性是名称“hasSubject”与类别相关的单个书籍类。示例书“A”具有主题类别“S”和“F”,并且...结果我想获得属于图书类别的矩阵。这就是如果这本书属于某个类别则取 1,否则取值为 0 的方式。像这样:

     cat1   cat2   cat3   
book1   1      0      0   
book2   1      0      1   
book3   1      1      0  

在此示例中表示 book1 属于类别 1 并且不属于类别 2 和 3。如何在 protege 中使用 sparql 完成这项工作?

【问题讨论】:

    标签: sparql ontology owl protege


    【解决方案1】:

    处理固定数量的类别

    给定数据

    @prefix : <http://example.org/books/> .
    
    :book1 a :Book, :Cat1 .
    :book2 a :Book, :Cat1, :Cat3 .
    :book3 a :Book, :Cat1, :Cat2 .
    

    你可以使用类似的查询

    prefix : <http://example.org/books/>
    
    select ?individual
           (if(bound(?cat1),1,0) as ?Cat1)
           (if(bound(?cat2),1,0) as ?Cat2)
           (if(bound(?cat3),1,0) as ?Cat3)
    where {
      ?individual a :Book .
      OPTIONAL { ?individual a :Cat1 . bind( ?individual as ?cat1 ) } 
      OPTIONAL { ?individual a :Cat2 . bind( ?individual as ?cat2 ) }
      OPTIONAL { ?individual a :Cat3 . bind( ?individual as ?cat3 ) }
    }
    order by ?book
    

    根据是否存在某些三元组来获得以下结果,绑定某些变量(尽管它们绑定的特定值并不重要):

    $ arq --data data.n3 --query matrix.sparql
    -----------------------------------
    | individual | Cat1 | Cat2 | Cat3 |
    ===================================
    | :book1     | 1    | 0    | 0    |
    | :book2     | 1    | 0    | 1    |
    | :book3     | 1    | 1    | 0    |
    -----------------------------------
    

    处理任意数量的类别

    这是一个似乎适用于耶拿的解决方案,但我不确定具体结果是否得到保证。 (更新:基于此answers.semanticweb.com question and answer,SPARQL 规范似乎保证此行为。)如果我们有更多数据,例如,关于哪些是类别,哪些是书籍,例如,

    @prefix : <http://example.org/books/> .
    
    :book1 a :Book, :Cat1 .
    :book2 a :Book, :Cat1, :Cat3 .
    :book3 a :Book, :Cat1, :Cat2 .
    
    :Cat1 a :Category .
    :Cat2 a :Category .
    :Cat3 a :Category .
    

    然后我们可以运行一个子查询,按顺序选择所有类别,然后为每本书计算一个字符串,指示该书是否属于每个类别。

    prefix : <http://example.org/books/>
    
    select ?book (group_concat(?isCat) as ?matrix) where { 
      { 
        select ?category where { 
          ?category a :Category 
        }
        order by ?category 
      }
      ?book a :Book .
      OPTIONAL { bind( 1 as ?isCat )              ?book a ?category . }
      OPTIONAL { bind( 0 as ?isCat ) NOT EXISTS { ?book a ?category } }
    }
    group by ?book
    order by ?book
    

    这有输出:

    $ arq --data data.n3 --query matrix2.query
    --------------------
    | book   | matrix  |
    ====================
    | :book1 | "1 0 0" |
    | :book2 | "1 0 1" |
    | :book3 | "1 1 0" |
    --------------------
    

    它更接近问题中的输出,并且可以处理任意数量的类别。但是,这取决于每个?book 以相同的顺序处理?category 的值,我不确定这是否得到保证。

    我们甚至可以使用这种方法为表格生成标题行。同样,这取决于每个?book 以相同顺序处理的?category 值,这可能无法保证,但似乎在耶拿有效。要获取类别标题,我们需要做的就是创建一个未绑定?book 的行,?isCat 的值表示特定类别:

    prefix : <http://example.org/books/>
    
    select ?book (group_concat(?isCat) as ?matrix) where { 
      { 
        select ?category where { 
          ?category a :Category 
        }
        order by ?category 
      }
    
      # This generates the header row where ?isCat is just
      # the category, so the group_concat gives headers.
      { 
        bind(?category as ?isCat) 
      }
      UNION 
      # This is the table as before
      {
        ?book a :Book .
        OPTIONAL { bind( 1 as ?isCat )              ?book a ?category . }
        OPTIONAL { bind( 0 as ?isCat ) NOT EXISTS { ?book a ?category } }
      }
    }
    group by ?book
    order by ?book
    

    我们得到这个输出:

    --------------------------------------------------------------------------------------------------------
    | book   | matrix                                                                                      |
    ========================================================================================================
    |        | "http://example.org/books/Cat1 http://example.org/books/Cat2 http://example.org/books/Cat3" |
    | :book1 | "1 0 0"                                                                                     |
    | :book2 | "1 0 1"                                                                                     |
    | :book3 | "1 1 0"                                                                                     |
    --------------------------------------------------------------------------------------------------------
    

    使用一些字符串操作,您可以缩短用于类别的 URI,或加宽数组条目以获得正确对齐。一种可能性是:

    prefix : <http://example.org/books/>
    
    select ?book (group_concat(?isCat) as ?categories) where { 
      { 
        select ?category
               (strafter(str(?category),"http://example.org/books/") as ?name)
         where { 
          ?category a :Category 
        }
        order by ?category 
      }
    
      { 
        bind(?name as ?isCat)
      }
      UNION 
      {
        ?book a :Book .
        # The string manipulation here takes the name of the category (which should
        # be at least two character), trims off the first character (string indexing
        # in XPath functions starts at 1), and replaces the rest with " ". The resulting
        # spaces are concatenated with "1" or "0" depending on whether the book is a
        # member of the category.  The resulting string has the same width as the
        #  category name, and makes for a nice table.
        OPTIONAL { bind( concat(replace(substr(?name,2),"."," "),"1") as ?isCat )              ?book a ?category . }
        OPTIONAL { bind( concat(replace(substr(?name,2),"."," "),"0") as ?isCat ) NOT EXISTS { ?book a ?category } }
      }
    }
    group by ?book
    order by ?book
    

    产生这个输出:

    $ arq --data data.n3 --query matrix3.query
    -----------------------------
    | book   | categories       |
    =============================
    |        | "Cat1 Cat2 Cat3" |
    | :book1 | "   1    0    0" |
    | :book2 | "   1    0    1" |
    | :book3 | "   1    1    0" |
    -----------------------------
    

    这几乎正是您在问题中所遇到的。

    【讨论】:

    • 谢谢贾舒亚·泰勒。但是如果我有大量书籍和类别,那么我应该为每个书籍和类别都做这项工作吗?
    • @sima412 如果你有大量的书籍和分类,这种查询会变得很乏味,你最好手动做一些事情。例如,您可以先选择所有类别,然后针对每个类别,检查图书是否在该类别中,然后根据该数据创建表。 SPARQL 可以帮助您获取数据,但您可能仍需要处理一些表示方面的问题。
    • @sima412 我认为我之前的评论是错误的。尽管在 SPARQL 之外进行更高级的格式化可能仍然是一个好主意,但实际上为任意数量的类别获得一些格式良好的输出并不是那么难。结果几乎与您在问题中所得到的完全一样。我已经相应地更新了我的答案。
    • 好的。非常感谢 Taylor 先生。你知道我想取矩阵,然后应用余弦相似度公式。
    • @sima412 我不知道余弦相似度公式是什么,无论如何,这可能最好作为一个单独的问题提出。如果它作为一个单独的问题发布;这样会得到更多关注,并有助于保持每个问题的独立性。
    猜你喜欢
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多