V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
ShikiSuen
V2EX  ›  iDev

中文分词时该怎样定义被误拆的专有词?

  •  
  •   ShikiSuen · 247 天前 · 1614 次点击
    这是一个创建于 247 天前的主题,其中的信息可能已经有所发展或是发生改变。

    先来个例子:

    import Foundation
    
    func tokenize(sentence: String) -> [String] {
      var tokens:[String] = [String]()
      let tagger = NSLinguisticTagger(tagSchemes: [.tokenType], options: 0)
      tagger.string = sentence
      let range = NSMakeRange(0, sentence.utf16.count)
      let options: NSLinguisticTagger.Options = [.omitWhitespace, .omitPunctuation]
      tagger.enumerateTags(in: range, unit: .word, scheme: .tokenType, options: options) { (tag, tokenRange, stop) in
        let word = (sentence as NSString).substring(with: tokenRange)
        tokens.append(word)
      }
      return tokens
    }
    
    let texts: [String] = ["有個大夫叫白朮,他有個徒弟叫七七。"]
    for text in texts {
      let tokens = tokenize(sentence: text)
      print("\(text) --> \(tokens)")
    }
    

    直接运行该 swift 脚本,可以发现「白朮」(「白术」的繁体中文写法)被拆开了。 该怎样定义这个词、使其不被误拆呢?

    17 条回复    2023-10-22 09:10:06 +08:00
    blackcat888
        1
    blackcat888  
       247 天前 via Android
    不玩原神即可
    chenY520
        2
    chenY520  
       247 天前
    自定义词典吧
    ShikiSuen
        3
    ShikiSuen  
    OP
       247 天前
    @blackcat888 跟原神无关的例句也可以拿来测试:
    「金庸有一篇小說,張三丰是其中的一個角色。」
    该怎样让这个断句器认为“张三丰”是一个完整的词?
    ShikiSuen
        4
    ShikiSuen  
    OP
       247 天前
    @chenY520 对,我想问这里该怎么自定义。
    chenY520
        5
    chenY520  
       247 天前
    @ShikiSuen #4

    import Foundation

    // 创建自定义词典,将需要保留的词汇映射到一个数组,以便后续检查
    let customDictionary: [String: [String]] = [
    "白术": ["白术"],
    "大夫": ["大夫"],
    "七七": ["七七"]
    ]

    func tokenize(sentence: String) -> [String] {
    var tokens: [String] = []
    let tagger = NSLinguisticTagger(tagSchemes: [.tokenType], options: 0)
    tagger.string = sentence
    let range = NSMakeRange(0, sentence.utf16.count)
    let options: NSLinguisticTagger.Options = [.omitWhitespace, .omitPunctuation]

    tagger.enumerateTags(in: range, unit: .word, scheme: .tokenType, options: options) { (tag, tokenRange, stop) in
    let word = (sentence as NSString).substring(with: tokenRange)
    if let specialCases = customDictionary[word] {
    tokens.append(contentsOf: specialCases)
    } else {
    tokens.append(word)
    }
    }
    return tokens
    }

    let texts: [String] = ["有個大夫叫白朮,他有個徒弟叫七七。"]
    for text in texts {
    let tokens = tokenize(sentence: text)
    print("\(text) --> \(tokens)")
    }
    chenY520
        6
    chenY520  
       247 天前
    @ShikiSuen #4 chatgpt 可以试试
    zjuster
        7
    zjuster  
       247 天前
    之前做过知识图谱,用的 NLP 相关技术和模型。其中的专有词都是走 NER 的(命名实体识别)。NLP 的技术模型另说,NER 就要调教很多模型了。

    楼主的这个命题都是人工打标的。分两种
    1. 模型建设
    先用第三方的中英文语料库调教启动语料库,然后迭代模型,设置在不同的 context 下,某些特定的字符组合将被识别为 entity 模型的概率组合,然后给到人工评估模型结果,打分来调教。这个算是日常模型调教,有更新就需要做定量对比模型版本的。
    如果语料库的质量比较高,能够减少很多术语的问题。
    前公司是搜索出身的,本身就积累了大量的 user query 库,所以这方便少了很多麻烦。

    2. 强制识别
    这没啥好说的,直接人工干预模型结果,一般是纠错 case ,需要一个一个积累。比较麻烦的是以后 context 模型调整,或者划分,需要人工重新做一遍。

    不清楚楼主的目的和背景,我建议先找一下中文语料库,别的不说,新华词典啊就能解决你的“白术”问题。
    抛开原神,这也是一款中药材。龙葵之类的,都应该是能识别出来的。
    难点应该是如何识别是游戏角色白术,还是中药材白术。
    ShikiSuen
        8
    ShikiSuen  
    OP
       247 天前
    @chenY520 您不妨把「白术」全改成「白朮」再試試看?
    我這邊測試結果:
    ["有", "個", "大夫", "叫", "白", "朮", "他", "有", "個", "徒弟", "叫", "七七"]
    白朮還是被切了。
    ShikiSuen
        9
    ShikiSuen  
    OP
       247 天前
    感觉五楼 @chenY520 的方法作用有限:唯一用到自订辞典的场合居然在 enumerateTags 的 loop 内部。此时的 word 断然不可能是「白朮」,只可能是「白」与「朮」。

    得想办法在 enumerateTags 执行之前就将自订辞典给介入到里面去。
    yuhu96
        10
    yuhu96  
       246 天前
    jieba 自定义词库。不知道你 swift 里有没有这一套,你上网抓取领域相关的词汇(随便哪里,比如百度百科)做好词库,加载这个词库,分词的时候就不容易错分。
    oxoxoxox
        11
    oxoxoxox  
       246 天前
    ChatGPT 3.5 的答案:

    有個大夫叫白朮,他有個徒弟叫七七。

    拆分为单词:
    有 / 個 / 大夫 / 叫 / 白朮 / , / 他 / 有 / 個 / 徒弟 / 叫 / 七七。
    kingbill
        12
    kingbill  
       246 天前
    你得有个牛逼的词库
    S1deny
        13
    S1deny  
       246 天前
    感觉得需要大量的语义词库进行训练才行啊 自定义的词库以哈工大词典和百度情感词典为例 好像那个腾讯的词向量模型涉及到了很多的词库
    ShikiSuen
        14
    ShikiSuen  
    OP
       246 天前
    @yuhu96 @oxoxoxox @kingbill @S1deny
    先感谢各位的意见。

    然后呢,问题的真正症结已经在 #9 讲清楚了。
    第三方服务不是不能用,但我将这个讨论串放在 iDev 版、自然是要问与 macOS 内建模组有关的问题。
    不然我直接投递在别的版面就好。
    iugo
        15
    iugo  
       236 天前
    如果 NSLinguisticTagger 内置会更好, 即便没有, 也是有一些笨方法解决的.

    ```swift
    let customDictionary = ["白朮": 1]

    func tokenize(sentence: String) -> [String] {
    var tokens:[String] = [String]()
    let tagger = NSLinguisticTagger(tagSchemes: [.tokenType], options: 0)
    tagger.string = sentence
    let range = NSMakeRange(0, sentence.utf16.count)
    let options: NSLinguisticTagger.Options = [.omitWhitespace, .omitPunctuation]
    tagger.enumerateTags(in: range, unit: .word, scheme: .tokenType, options: options) { (tag, tokenRange, stop) in
    let word = (sentence as NSString).substring(with: tokenRange)
    // 找到上一个单词, 如果本单词加上一个单词和词库匹配, 则修改之前的词
    let oldnew = (tokens.last ?? "") + word
    if customDictionary.keys.contains(oldnew) {
    tokens.removeLast()
    tokens.append(oldnew)
    } else {
    tokens.append(word)
    }
    }
    return tokens
    }
    ```
    iugo
        16
    iugo  
       236 天前
    因为是笨办法, 所以这里面有两个问题:

    1. 如果多个组合怎么处理? 比如这个大夫姓 "叫" , 全名 "叫白朮". 因为代码只能将两个词进行匹配, 那么则匹配不上. 如果不是完全匹配而是匹配字符串前面的部分, 则可能出现误匹配. 所以当前的两个字完全匹配是一个简单做法.
    2. 换用 Set. 不过这个 Set 做不了替换, 比如今后想将 白朮 替换为 白术 用字典就简单, 用集合就做不到.

    总之, 这种分词办法比较笨, 因为并没有了解真实的语义. 最好还是服务端做, 用 python 这种库.
    BB9z
        17
    BB9z  
       188 天前
    训练自定义模型打标签,再结合标签结果分词?
    https://developer.apple.com/documentation/naturallanguage/creating_a_word_tagger_model
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1092 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 23:12 · PVG 07:12 · LAX 16:12 · JFK 19:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.