NLTagger:一次枚举多种类型的标签

Posted

技术标签:

【中文标题】NLTagger:一次枚举多种类型的标签【英文标题】:NLTagger: enumerating tags of multiple types in one pass 【发布时间】:2020-12-06 21:47:12 【问题描述】:

使用NLTagger 类,我想知道是否有人可以推荐最直接的方法来枚举给定文本中的标记标记,但每个标记提取多个标记类型。例如,要枚举给定文本中的单词,为每个单词提取(引理,词汇类别)。

似乎 enumerateTags() 方法和关联的 NLTag 类具有每次枚举仅报告一种特定标签类型的限制。所以我可以通过对文本进行多次传递来实现我想要的,例如在第一遍中提取与给定条件匹配的字符串范围,然后在以后的遍中进行匹配。例如,我可以像这样对所有的名词和动词进行词形还原:

let tagger = NLTagger(tagSchemes: [.lemma, .nameTypeOrLexicalClass])
tagger.string = //some text
let keyWordCategories: [NLTag] = [.noun, .verb]
let options: NLTagger.Options = [.omitPunctuation, .omitWhitespace, .joinNames]

// In the first pass, we're going to record which ranges are of categories we're interested in
var keywordRanges = Set<Range<String.Index>>(minimumCapacity: 200)

// First pass: which are the nouns and verbs?
tagger.enumerateTags(in: text.startIndex..<text.endIndex, unit: .word, scheme: .nameTypeOrLexicalClass, options: options)  tag, tokenRange in
    if let tag = tag 
        if (keyWordCategories.contains(tag)) 
            keywordRanges.insert(tokenRange)
        
    
    return true


// Second pass: lemmatise, filtering on just the nouns and verbs
tagger.enumerateTags(in: text.startIndex..<text.endIndex, unit: .word, scheme: .lemma, options: options)  tag, tokenRange in
    if let tag = tag 
        if (keywordRanges.contains(tokenRange)) 
            lemmas.insert(tag.rawValue)
        
    
    return true

这种机制实现了所需的功能,但让我觉得这是一种有点笨拙且可能效率低下的处理方式。我本来希望能够一次性枚举(引理,词汇类别)。我假设 NLTagger 实例在幕后缓存了一些东西,因此它在效率方面并不像看起来那么糟糕。但就代码的简单性而言,它仍然远非理想。任何更熟悉此 API 的人能否就这是否真的是预期模式提出建议?

【问题讨论】:

【参考方案1】:

您可以使用tags(in:unit:scheme:options:) 来获取具体范围内的引理,而不是遍历标记器的每个引理:

let tagger = NLTagger(tagSchemes: [.lemma, .nameTypeOrLexicalClass])
tagger.string = text
let options: NLTagger.Options = [.omitPunctuation, .omitWhitespace, .joinNames]

let keyWordCategories = Set<NLTag>(arrayLiteral: .noun, .verb)
var lemmas = Set<String>()
let unit: NLTokenUnit = .word
tagger.enumerateTags(in: text.startIndex..<text.endIndex, unit: unit, scheme: .nameTypeOrLexicalClass, options: options)  tag, tokenRange in
    if tag.map(keyWordCategories.contains) == true 
        if let lemma = tagger.tags(in: tokenRange, unit: unit, scheme: .lemma, options: options).first?.0?.rawValue 
            lemmas.insert(lemma)
        
    
    return true

【讨论】:

以上是关于NLTagger:一次枚举多种类型的标签的主要内容,如果未能解决你的问题,请参考以下文章

获取值类型标签的父枚举

在java中如何将emun枚举类型作为参数传入函数中?

前端1-----块级标签(独占一行),排版标签(样式排版),其他标签,form表单(input的多种类型)

枚举类型位标致[Flags]特性的使用以及为枚举类型添加方法

结构体(一次过)

一次获取字符串并与多个枚举类型进行比较[重复]