Stanford CoreNLP分词规则查询及轻量替代方案咨询
基于UD 2.0规则的轻量正则分词实现(替代Stanford CoreNLP)
Stanford CoreNLP的分词逻辑确实基于UD 2.0分词规范,但官方源码实现冗长且缺乏清晰的规则文档,不管用Stanza、废弃的Python封装还是原生Java版本都很难直接梳理出明确规则。下面针对提出的9项分词要求,给出一套基于正则的轻量实现方案,同时解释特殊token的含义:
核心分词规则与正则实现
以下是针对每项要求的处理逻辑,以及整合后的正则表达式和示例代码:
1. 连字符连接的姓名、复合词不拆分
保留[a-zA-Z]+-[a-zA-Z]+这类结构,将其视为单个token,避免拆分连字符两端的内容。
2. 复数所有格拆分(如boys' → ["boys", "'"])
匹配以复数名词结尾(通常以s结尾)后接单引号的结构,拆分名词和单引号。
3. 单数所有格拆分(如aunt's → ["aunt", "'s"])
匹配非复数名词后接's的结构,拆分名词和's后缀。
4. 尊称缩写不拆分(如Mr./Mrs.保持为单个token)
将Mr\.、Mrs\.、Ms\.、Dr\.这类常见尊称缩写视为整体,不拆分点号和前面的单词。
5. 常规标点独立成token,双连字符不拆分
除了整合到其他结构的标点(如所有格的单引号),其余标点(逗号、句号、问号等)单独作为token;同时保留--为单个token,不拆分为两个-。
6. 缩合动词拆分(如Wouldn't → ["would", "n't"])
匹配以辅音结尾的动词后接n't的缩合结构,拆分为动词原型和n't。
7. and/or不拆分
将and/or视为单个固定token。
8. 人称代词缩写拆分(如I'm → ["I", "'m"])
匹配人称代词后接'm/'re/'ve等缩写后缀的结构,拆分代词和后缀。
整合后的正则分词逻辑
可以通过优先匹配需要保留的整体结构,再处理拆分规则的顺序来实现,示例Python代码如下:
import re def core_nlp_style_tokenize(text): # 定义需要优先保留为单个token的结构 preserve_patterns = [ r'(Mr\.|Mrs\.|Ms\.|Dr\.)', # 尊称缩写 r'and/or', # 固定搭配 r'[a-zA-Z]+-[a-zA-Z]+', # 连字符连接的姓名/复合词 r'--' # 双连字符 ] # 定义拆分规则(按优先级排序) split_patterns = [ r"([a-zA-Z]+)'$", # 复数所有格拆分(如boys' → boys + ') r"([a-zA-Z]+)'s", # 单数所有格拆分(如aunt's → aunt + 's) r"([a-zA-Z]+)n't", # 缩合动词拆分(如Wouldn't → would + n't) r"([I|You|He|She|It|We|They])'m", # 人称代词缩写拆分(如I'm → I + 'm) r"([I|You|He|She|It|We|They])'re", r"([I|You|He|She|It|We|They])'ve", r"([I|You|He|She|It|We|They])'ll", r'([^\w\s\-])', # 常规标点拆分(除了连字符) ] # 先替换需要保留的结构为临时标记,避免被拆分 temp_markers = [] for idx, pattern in enumerate(preserve_patterns): def replace_func(match, idx=idx): temp_markers.append(match.group(0)) return f'__TEMP{idx}__' text = re.sub(pattern, replace_func, text) # 应用拆分规则 for pattern in split_patterns: if r'\2' in pattern: text = re.sub(pattern, r'\1 \2', text) else: text = re.sub(pattern, r'\1 ', text) # 还原临时标记的内容 for idx, marker in enumerate(temp_markers): text = text.replace(f'__TEMP{idx}__', marker) # 分割并过滤空字符串 tokens = [token.strip() for token in text.split() if token.strip()] return tokens # 测试示例 test_cases = [ "Marie Illonig-Alberts is a well-intentioned person", "The boys' toys are next to aunt's chair", "Mr. Smith and Mrs. Jones went to the store", "This is a test--does it work?", "Wouldn't you like to know I'm here?", "We can choose and/or modify the plan" ] for case in test_cases: print(f"输入: {case}") print(f"分词结果: {core_nlp_style_tokenize(case)}\n")
特殊token -LRB-/-RRB-说明
在Stanford CoreNLP的输出中,-LRB-和-RRB-是左括号(和右括号)的标准化标记。CoreNLP会将原始文本中的括号替换为这两个特殊token,目的是:
- 统一处理不同格式的括号(如全角/半角括号);
- 避免括号作为标点符号被误拆分或干扰后续的句法分析;
- 符合UD标注规范中对括号的标准化表示。
其他类似的特殊token还有-LCB-(左大括号{)、-RCB-(右大括号})、-LSB-(左方括号[)、-RSB-(右方括号])。
内容的提问来源于stack exchange,提问作者lrthistlethwaite
相关产品推荐
相关产品推荐

