如何扩展NSLinguisticTagger以识别威尔士人名?
解决威尔士人名识别问题的实用方案
嘿,刚好碰到过类似的问题!首先明确说:NSLinguisticTagger目前没有官方途径直接扩展它内置的命名实体识别字典,不过结合你手里的威尔士人名CSV,我们有几个靠谱的办法来搞定Osian这类人名被误判成地名的问题:
1. 最快见效:用你的人名CSV做后处理修正
这是最直接的方案,利用你已有的威尔士人名库,在Tagger识别完之后做二次校验和修正,步骤很简单:
- 先把CSV里的所有威尔士人名加载到一个
Set里(方便O(1)快速查找) - 先收集Tagger的原始识别结果,然后检查每一个结果:如果某个词被标记为
.placeName但存在于你的人名Set里,直接把它修正为.personalName - 额外补充:还可以把那些Tagger没识别出来、但属于你人名Set的词,手动标记为人名
给你修改后的代码示例:
// 先处理CSV,把所有威尔士人名加载到Set里(这里假设你已经完成CSV读取逻辑) let welshPersonalNames: Set<String> = ["Osian", "Rhys", "Gwenllian", "Elin"] // 替换成你的完整人名列表 let text = "Hey I'm Osian" let tagger = NLTagger(tagSchemes: [.nameType]) tagger.string = text let options: NLTagger.Options = [.omitPunctuation, .omitWhitespace, .joinNames] let targetTags: [NLTag] = [.personalName, .organizationName, .placeName] // 第一步:收集Tagger的原始识别结果 var rawEntities: [(word: Substring, tag: NLTag)] = [] tagger.enumerateTags(in: text.startIndex..<text.endIndex, unit: .word, scheme: .nameType, options: options) { tag, tokenRange in if let tag = tag, targetTags.contains(tag) { rawEntities.append((text[tokenRange], tag)) } return true } // 第二步:用威尔士人名库修正结果 for (word, tag) in rawEntities { let normalizedWord = word.lowercased() // 忽略大小写匹配,覆盖各种输入情况 if welshPersonalNames.contains(normalizedWord) { print("\(word): .personalName (修正自 \(tag.rawValue))") } else { print("\(word): \(tag.rawValue)") } } // 第三步:补充识别Tagger漏掉的威尔士人名 text.split(separator: " ").forEach { word in let normalizedWord = word.lowercased() let isAlreadyRecognized = rawEntities.contains(where: { $0.word.lowercased() == normalizedWord }) if welshPersonalNames.contains(normalizedWord) && !isAlreadyRecognized { print("\(word): .personalName (补充识别)") } }
2. 进阶优化:结合上下文规则区分人名/地名
有些威尔士词汇可能既是人名也是地名,这种情况下可以加一些上下文判断逻辑:
- 比如如果词前面有"I'm"、"My name is"、"This is"这类指代人的前缀,优先判定为人名
- 如果词出现在"in"、"near"这类介词后面,更可能是地名
- 你可以把这些规则加到后处理步骤里,进一步提升准确率
3. 长期方案:训练自定义Core ML NER模型
如果你的场景需要更高的准确率,或者有大量威尔士语的语料,可以考虑训练自己的命名实体识别模型:
- 用你的语音转写文本(或者公开的威尔士语文本),标注其中的人名实体
- 用Apple的Create ML工具(Xcode里就有)来训练自定义NER模型
- 把训练好的模型集成到项目里,和NSLinguisticTagger配合使用,或者直接替代它
这种方法的优势是能针对性优化威尔士语人名的识别,但需要花点时间做语料标注。
小提醒
- 处理CSV的时候记得统一大小写,或者匹配时忽略大小写,避免因为输入的大小写不同漏识别
- 如果你的人名库包含姓氏,记得一起加入Set,
joinNames选项会自动合并名和姓,但前提是它们能被正确关联
内容的提问来源于stack exchange,提问作者Osian
相关产品推荐
相关产品推荐

