Sklearn CountVectorizer自定义分词器tokenize2输出异常问题
问题分析与解决
问题重现
你尝试用自定义分词器构建CountVectorizer,但tokenize2的向量输出不符合预期:
temp_tok = ["or", "Normal sinus rhythm", "sinus", "anuj","Normal sinus"] def tokenize(text): return [temp_tok[0],temp_tok[1], "sinus", "Normal sinus"] def tokenize2(text): return [i for i in temp_tok if i in text] text = "Normal sinus rhythm" # 直接调用分词器,输出一致 print(tokenize(text)) # 输出: ['or', 'Normal sinus rhythm', 'sinus', 'Normal sinus'] print(tokenize2(text)) # 输出: ['or', 'Normal sinus rhythm', 'sinus', 'Normal sinus'] # 构建向量器 vectorizer = CountVectorizer(vocabulary=temp_tok,tokenizer = tokenize) vectorizer2 = CountVectorizer(vocabulary=temp_tok,tokenizer = tokenize2) # 向量输出差异 print(vectorizer.transform([text]).toarray()) # 输出: array([[1, 1, 1, 0, 1]]) print(vectorizer2.transform([text]).toarray()) # 输出: array([[1, 0, 1, 0, 0]])
核心原因
问题出在CountVectorizer的默认预处理逻辑,以及直接调用分词器和向量器内部调用的差异:
- 默认小写转换:
CountVectorizer默认开启lowercase=True,会先把输入文本转为小写,再传给自定义分词器。- 你直接调用
tokenize2(text)时,传入的是原始大写开头的"Normal sinus rhythm",所以"Normal sinus rhythm" in text为True; - 但向量器内部调用
tokenize2时,传入的是预处理后的小写文本"normal sinus rhythm",此时大写的"Normal sinus rhythm"和"Normal sinus"无法匹配小写文本,导致这两个token不会被返回。
- 你直接调用
- "or"的误匹配:原始文本中的
"Normal"包含子串"or",所以直接调用时"or" in text为True,向量器内部处理时小写的"normal"也包含"or",所以这个token会被保留。
解决方法
针对这个问题,有两种可行的修复方式:
方式一:关闭默认小写转换
初始化CountVectorizer时设置lowercase=False,让向量器不修改原始文本的大小写,这样分词器能正确匹配词汇表中的内容:
vectorizer2 = CountVectorizer(vocabulary=temp_tok, tokenizer=tokenize2, lowercase=False) print(vectorizer2.transform([text]).toarray()) # 输出: array([[1, 1, 1, 0, 1]])
方式二:统一分词器和词汇表的大小写
如果需要保留小写转换的逻辑,可将词汇表转为小写,同时修改分词器的匹配逻辑:
# 将词汇表转为小写 temp_tok_lower = [tok.lower() for tok in temp_tok] def tokenize2_lower(text): # 此时text已经是小写,匹配小写的词汇表元素 return [i for i in temp_tok_lower if i in text] vectorizer2 = CountVectorizer(vocabulary=temp_tok_lower, tokenizer=tokenize2_lower) print(vectorizer2.transform([text]).toarray()) # 输出: array([[1, 1, 1, 0, 1]])
额外说明
- 自定义分词器在
CountVectorizer中的执行时机是预处理之后,所以必须考虑预处理步骤(如小写转换、去除标点等)对输入文本的影响; - 当使用
vocabulary参数时,确保分词器返回的token与词汇表的格式(大小写、字符串完全匹配)一致,否则无法正确计数。
内容的提问来源于stack exchange,提问作者Anuj Chopra
相关产品推荐
相关产品推荐

