NSLinguisticTaggerMattt Croath Liu 🚩🌱

NSLinguisticTagger 在语言学功能上来讲是一把名副其实的瑞士军刀,它可以讲自然语言的字符串标记为单词、确定词性和词根、划分出人名地名和组织名称、告诉你字符串使用的语言和语系

对于我们大多数人来说,这其中蕴含着意义远超过我们所知道的,但或许也只是我们没有合适的机会使用而已。但是,几乎所有使用某种方式来处理自然语言的应用如果能够用上 NSLinguisticTagger ,或许就会润色不少,没准会催生一批新特性呢。


NSLinguisticTagger 和Siri同时出现于iOS 5上,所以可以推测这可能是苹果在私人助理方向开发时候的副产品。

回想一下我们经常问Siri的一个问题:

旧金山的天气怎么样?(What is the weather in San Francisco?)

电脑不可能通过逐字翻译"理解"问题的含义,不过我们耍一点儿小花招就可以合理地理解这个问题的_含义_:

NSString *question = @"What is the weather in San Francisco?";
NSLinguisticTaggerOptions options = NSLinguisticTaggerOmitWhitespace | NSLinguisticTaggerOmitPunctuation | NSLinguisticTaggerJoinNames;
NSLinguisticTagger *tagger = [[NSLinguisticTagger alloc] initWithTagSchemes: [NSLinguisticTagger availableTagSchemesForLanguage:@"en"] options:options];
tagger.string = question;
[tagger enumerateTagsInRange:NSMakeRange(0, [question length]) scheme:NSLinguisticTagSchemeNameTypeOrLexicalClass options:options usingBlock:^(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop) {
    NSString *token = [question substringWithRange:tokenRange];
    NSLog(@"%@: %@", token, tag);
}];

输出如下:

What: Pronoun(代词) is: Verb(动词) the: Determiner(限定词) weather: Noun(名词) in: Preposition(介词) San Francisco: PlaceName(地名)

如果我们过滤名词、动词、地名,就会得到结果:[is, weather, San Francisco]

仅以来这个结果,或者配合潜在语义映射(Latent Semantic Mapping)库,我们就可以推断出合理解释,然后就可以通过调用相关API去获取旧金山此时此刻的天气状况了。

特征标记方案

我们可以通过给 NSLinguisticTagger 设置下列scheme来标记不同类型的信息:

这里有一个不同短语类型和每一个分词方案之间关系的表:(NSLinguisticTagSchemeNameTypeOrLexicalClass表示NSLinguisticTagSchemeNameTypeNSLinguisticTagSchemeLexicalClass的组合关系):

NSLinguisticTagSchemeTokenTypeNSLinguisticTagSchemeLexicalClassNSLinguisticTagSchemeNameType
  • NSLinguisticTagWord
  • NSLinguisticTagPunctuation
  • NSLinguisticTagWhitespace
  • NSLinguisticTagOther
  • NSLinguisticTagNoun
  • NSLinguisticTagVerb
  • NSLinguisticTagAdjective
  • NSLinguisticTagAdverb
  • NSLinguisticTagPronoun
  • NSLinguisticTagDeterminer
  • NSLinguisticTagParticle
  • NSLinguisticTagPreposition
  • NSLinguisticTagNumber
  • NSLinguisticTagConjunction
  • NSLinguisticTagInterjection
  • NSLinguisticTagClassifier
  • NSLinguisticTagIdiom
  • NSLinguisticTagOtherWord
  • NSLinguisticTagSentenceTerminator
  • NSLinguisticTagOpenQuote
  • NSLinguisticTagCloseQuote
  • NSLinguisticTagOpenParenthesis
  • NSLinguisticTagCloseParenthesis
  • NSLinguisticTagWordJoiner
  • NSLinguisticTagDash
  • NSLinguisticTagOtherPunctuation
  • NSLinguisticTagParagraphBreak
  • NSLinguisticTagOtherWhitespace
  • NSLinguisticTagPersonalName
  • NSLinguisticTagPlaceName
  • NSLinguisticTagOrganizationName

NSLinguisticTagSchemeTokenType 来进行基本的分词(tokenization)就可以分辨出词语空格和标点符号了。至于话语信息或者区分话语的不同部分应该用 NSLinguisticTagSchemeLexicalClass

继续说其它scheme:

回头看上面给出的样例代码,首先用一个你想要用到的scheme组成的数组来初始化一个 NSLinguisticTagger,然后在判断输入字符串的标记之后枚举出每一个tag。

标记选项

除可用的标记scheme之外,还有一些可以传给 NSLinguisticTagger 的附加选项(用按位或|)来改变细微的分词行为:

这些选项的每一个都可以细化标记所代表的广义类别。例如:NSLinguisticTagSchemeLexicalClass 配合 NSLinguisticTaggerOmitPunctuation 就可以在不同种类的标点符号中再细化。推荐用带block的迭代器或predicate来实现。

最后一个选项是针对 NSLinguisticTagSchemeNameType 的:

默认一个名字中的每个短语都被分成不同的实例。很多情况下需要将类似“San Francisco”这样的名字当作一个短语而不是两个短语来看待。传入这个属性即可实现这个功能。


不幸的是在移动设备的UI设计中,自然语言处理并没有并没有被充分的利用。如果能够有效的利用,用户就可以用说话来代替手上的触摸动作来完成相同的事,而且会花费更少的时间。

当然要做到这点并不容易,但如果我们花费一点点时间能让应用在视觉上更赞,就可以给用户与设备和应用的交互体验上带来很大的颠覆。等到那时,再加上 NSLinguisticTagger,使用移动应用将从未如此简单。


除非另有声明,本文采用知识共享「署名-非商业性使用 3.0 中国大陆」许可协议授权。