Python 在sklearn中将训练语料库传递给TfidfVectorizer之前,如何应用自定义词干分析器?

Python 在sklearn中将训练语料库传递给TfidfVectorizer之前,如何应用自定义词干分析器?,python,scikit-learn,stemming,document-classification,tfidfvectorizer,Python,Scikit Learn,Stemming,Document Classification,Tfidfvectorizer,这是我的代码,我有一个句子,我想在将其传递给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_

这是我的代码,我有一个句子,我想在将其传递给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
致:

我评论这句话:

X_train = [sentence_tokenizer_stemmer(text) for text in X_train]
我希望得到相同的结果,但结果不同:

['il', 'il libr', 'libr', 'libr è', 'sul', 'sul tavol', 'tavol', 'è', 'è sul']
['05', '05 ved', 'ved']
为什么??我是否正确实现了外部词干分析器?看起来,至少在第一次运行中删除了stopwords(“è”),即使stop_words=None

[编辑] 正如Vivek所建议的,问题似乎是默认的令牌模式,当tokenizer=None时,无论如何都会应用该模式。因此,如果a将这两行添加到标记器\u词干分析器\u ita的开头:

token_pattern = re.compile(u'(?u)\\b\\w\\w+\\b')
text = " ".join( token_pattern.findall(text) )
我应该得到正确的行为,事实上,对于上面的简单示例,我得到了正确的行为,但对于另一个示例:

X_train = ['0.05%.\n\nVedete?']
我不知道,这两种输出是不同的:

['il', 'il libr', 'libr', 'libr è', 'sul', 'sul tavol', 'tavol', 'è', 'è sul']
['05', '05 ved', 'ved']

为什么??在这种情况下,问号似乎是问题所在,没有问号,输出是相同的

[编辑二]
似乎我必须先停止,然后应用正则表达式,在这种情况下,两个输出是相同的。

这是因为TfidfVectorizer中使用了默认的标记器模式
token\u模式

令牌\u模式:字符串

表示什么构成“标记”的正则表达式,仅在analyzer=='word'时使用。默认regexp选择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\u模式
在您遇到的标记器为None时使用。

您发布的当前代码错误。请仔细检查你的实际代码。你是对的,代码现在是正确的,你可以重现这个问题。谢谢Vivek,这解释了大部分情况,但在其他情况下,事情仍然不起作用(可能是由于标点符号的处理方式),请参阅我对问题的编辑。似乎我必须先停止,然后应用正则表达式,这对我来说似乎不合逻辑:我会说先找到标记,然后应用词干分析器,对吗?忘记我的最后一条评论,正则表达式是在词干分析器之后应用的,只是因为我传递的文本已经词干,而标记器是无的,所以一切都有意义。再次感谢。模拟定义令牌\u模式的简单text.split()的最简单方法是什么?