Sklearn TfidfVectorizer是否有特征最小长度限制?如何包含指定特征?
TfidfVectorizer丢失短特征(如'i'、'a'、'2')的原因及解决方法
问题描述
我有一个包含句子的pandas DataFrame,需要计算TF-IDF。数据集示例如下:
df['sentence'] = ['buy donuts', 'buy donuts', 'buy donuts', 'buy donuts', 'buy donuts', 'buy donuts', 'buy donuts', 'buy donuts', 'buy donuts', 'buy donuts', 'purchase donuts', 'purchase donuts', 'purchase donuts', 'purchase donuts', 'purchase donuts', 'buy donut', 'buy a donut', 'buy 2 donuts', 'buy 2 donuts', 'buy 2 donuts', 'buy 12 donuts', 'buy 12 donuts', 'buy 12 donuts', 'purchase 2 donuts', 'purchase 12 donuts', 'i want to buy 2 donuts', 'i want to buy 12 donuts', 'i want to buy donuts', 'i want to buy some donuts', 'buy some donuts', 'buy two donuts', 'buy two donuts', 'buy two donuts', 'buy twelve donuts', 'buy twelve donuts', 'buy twelve donuts', 'purchase two donuts', 'purchase twelve donuts', 'i want to buy two donuts', 'i want to buy twelve donuts']
我的处理流程是:
- 用spaCy对句子做词形还原
- 将词形还原后的结果传入sklearn的
TfidfVectorizer
但遇到异常:即使min_df和max_df用默认值、未移除停用词,get_feature_names()返回的特征里却缺少了'i'、'a'、'2',其中"2"对业务至关重要。
请问TfidfVectorizer是否有特征最小长度限制?如何将这些术语纳入特征?
我的处理代码如下:
import spacy import pandas as pd import numpy as np from sklearn.feature_extraction.text import TfidfVectorizer nlp = spacy.load("en", disable=['ner']) vect = TfidfVectorizer(binary=True) ## Load in data df = pd.read_csv('buy donuts.csv', encoding='utf-8') df.columns = df.columns.str.lower() ## Normalize sentences df['sentence'] = df['sentence'].str.replace(r"[^\w\s']", '').str.lower().str.strip().replace('', np.nan) df = df.dropna(subset=['unit name', 'sentence']) ## Get lemmas for tfidf def lemmas(x): docs = nlp(x) sents_lemma = [token.lemma_ for token in docs] return ' '.join(sents_lemma) # 注:原代码中index.map是多余的,直接apply即可 df['lemmas'] = df['sentence'].apply(lemmas) ## Get tfidf and calculate scores tfidf = vect.fit_transform(df.lemmas.values.tolist()) scores = ((tfidf * tfidf.T).A).mean(axis=0) print(vect.get_feature_names())
解答
问题根源:默认token_pattern过滤了短字符
TfidfVectorizer默认使用的token_pattern参数值为(?u)\b\w\w+\b,这个正则表达式的逻辑是:
(?u):开启Unicode匹配模式\b:匹配单词边界\w\w+:仅匹配至少两个字母/数字/下划线组成的序列
所以单字符的'i'、'a',以及单个数字'2'都会被这个规则过滤掉,不会被纳入特征池——这就是你看不到这些特征的核心原因,和min_df/max_df或停用词设置无关。
解决方法:自定义token_pattern保留短字符
你只需要在初始化TfidfVectorizer时,修改token_pattern参数,让它匹配任意长度的字母/数字序列即可,比如使用(?u)\b\w+\b:
# 修改TfidfVectorizer初始化代码 vect = TfidfVectorizer(binary=True, token_pattern=r'(?u)\b\w+\b')
这个正则表达式中的\w+会匹配一个或多个字母/数字/下划线字符,这样单字符的'i'、'a',以及单个数字'2'都会被正确识别为特征。
额外验证提示
- 词形还原步骤不会影响这些短字符:spaCy的lemmatizer对
'i'、'a'、'2'这类词不会做修改,它们会完整保留在lemmas列中。 - 如果后续需要排除特定单字符停用词,可以手动指定
stop_words参数(比如stop_words=['i', 'a']),但根据你的需求,保留这些词即可,无需设置该参数。
修改后重新运行代码,vect.get_feature_names()就会包含你需要的'i'、'a'、'2'等特征了。
内容的提问来源于stack exchange,提问作者Harrison Allen
相关产品推荐
相关产品推荐

