为何TF-IDF模型对仅含连字符差异的字符串给出0相似度?
原因分析
问题核心在于TfidfVectorizer默认的分词规则。
sklearn的TfidfVectorizer默认采用正则表达式(?u)\b\w\w+\b来识别token,这个规则的逻辑是:
- 只匹配包含至少两个字母/数字的连续序列(
\w\w+) - 用单词边界(
\b)界定token范围 - 连字符(
-)属于非单词字符(\W),会被当作分词分隔符
对应你的两个字符串:
str1 = 'abcdefgh'会被解析成单个token:abcdefghstr2 = 'abcdef-gh'会被分割成两个token:abcdef和gh
由于两个字符串的token集合完全没有交集,它们的TF-IDF向量在所有维度上都无重叠,余弦相似度自然为0。而当两个字符串完全相同时,token集合完全一致,相似度为1是正常表现。
解决办法
可以通过以下几种方式修正这个问题:
- 修改token_pattern,允许token包含连字符
调整正则表达式,让连字符被视为token的一部分:
vectorizer = TfidfVectorizer(token_pattern=r'(?u)\b[\w-]+\b')
这个规则会匹配包含字母、数字和连字符的连续序列,连字符不再被当作分隔符。
- 预处理字符串,替换连字符
在传入向量器前,将字符串中的连字符替换为空或空格:
str1_processed = str1.replace('-', '') str2_processed = str2.replace('-', '') tfidf_matrix = vectorizer.fit_transform([str1_processed, str2_processed])
- 自定义分词器
如果需要更灵活的逻辑,可以自定义分词函数传入tokenizer参数:
def custom_tokenizer(text): # 示例:保留带连字符的完整token,可根据需求调整逻辑 return [text] if '-' in text else text.split() vectorizer = TfidfVectorizer(tokenizer=custom_tokenizer)
内容的提问来源于stack exchange,提问作者marlon
相关产品推荐
相关产品推荐

