这是我的代码,我有一个句子,我想在将其传递给TfidfVectorizer之前对其进行标记化并最终获取该句子的tf-idf表示:
from sklearn.feature_extraction.text import TfidfVectorizer
import nltk
from nltk.stem.snowball import SnowballStemmer
stemmer_ita = SnowballStemmer("italian")
def tokenizer_stemmer_ita(text):
return [stemmer_ita.stem(word) for word in text.split()]
def sentence_tokenizer_stemmer(text):
return " ".join([stemmer_ita.stem(word) for word in text.split()])
X_train = ['il libro è sul tavolo']
X_train = [sentence_tokenizer_stemmer(text) for text in X_train]
tfidf = TfidfVectorizer(preprocessor=None, tokenizer=None, use_idf=True, stop_words=None, ngram_range=(1,2))
X_train = tfidf.fit_transform(X_train)
# let's see the features
print (tfidf.get_feature_names())
我得到了输出:
['il', 'il libr', 'libr', 'libr sul', 'sul', 'sul tavol', 'tavol']
如果我更改参数
tokenizer=None
为:
tokenizer=tokenizer_stemmer_ita
我评论这一行:
X_train = [sentence_tokenizer_stemmer(text) for text in X_train]
我希望得到相同的结果但结果却不同:
['il', 'il libr', 'libr', 'libr è', 'sul', 'sul tavol', 'tavol', 'è', 'è sul']
为什么呢?我是否正确实施了外部干扰器?至少,似乎在第一次运行中删除了停用词(“è”),即使stop_words = None。
[编辑] 正如Vivek所建议的那样,问题似乎是默认的令牌模式,当tokenizer = None时无论如何都会应用它。因此,如果在tokenizer_stemmer_ita的开头添加这两行:
token_pattern = re.compile(u'(?u)\\b\\w\\w+\\b')
text = " ".join( token_pattern.findall(text) )
我应该得到正确的行为,事实上我得到了上面这个简单的例子,但是对于另一个例子:
X_train = ['0.05%.\n\nVedete?']
我没有,两个输出是不同的:
['05', '05 ved', 'ved']
和
['05', '05 vedete', 'vedete']
为什么呢?在这种情况下,问号似乎是问题,没有它,输出是相同的。
[EDIT2] 似乎我必须首先阻止然后应用正则表达式,在这种情况下,两个输出是相同的。
答案 0 :(得分:1)
这是因为TfidfVectorizer中使用的默认令牌化模式token_pattern
:
token_pattern:string
正则表达式表示构成“令牌”的内容,仅在analyzer =='word'时使用。默认的正则表达式选择2或更多的标记 字母数字字符(标点符号完全被忽略并且总是 作为代币分隔符处理。)
因此未选择字符è
。
import re
token_pattern = re.compile(u'(?u)\\b\\w\\w+\\b')
print token_pattern.findall('il libro è sul tavolo')
# Output
# ['il', 'libro', 'sul', 'tavolo']
当您遇到令牌化器为无时,将使用此默认值token_pattern
。