def tokenize(text): text = re.sub('[^a-zA-Z0-9]', ' ', text) words = word_tokenize(text) lemmatizer = WordNetLemmatizer() words = [lemmatizer.lemmatize(w.lower().strip()) for w in words if w not in stopwords.words()] return wordspipeline = Pipeline([('vect', CountVectorizer(tokenizer=tokenize)),# ('tfidf', TfidfTransformer()),# ('clf', MultiOutputClassifier(RandomForestClassifier()))])
根据上述代码,CountVectorizer 适应时间过长(运行了60分钟仍未完成),但如果我移除代码行 if w not in stopwords.words()
,只需5分钟就能完成适应。这段代码可能存在什么问题,以及有什么可能的解决方案?我使用的是 nltk.corpus 中的停用词。
注意:tokenize 函数单独用于任何文本输入时工作正常。
谢谢
回答:
我的初步猜测是 stopwords.words() 函数在每次调用时执行了大量操作。或许,你可以尝试缓存它。对于 lemmatizer 也是如此:只调用一次构造函数可以显著加速代码。
stop_set = set(stopwords.words())lemmatizer = WordNetLemmatizer()def tokenize(text): text = re.sub('[^a-zA-Z0-9]', ' ', text) words = word_tokenize(text) words = [lemmatizer.lemmatize(w.lower().strip()) for w in words if w not in stop_set] return words
根据我的经验,即使是词形还原函数也可以尝试缓存,比如
from functools import lru_cachestop_set = set(stopwords.words())lemmatizer = WordNetLemmatizer()@lru_cache(maxsize=10000)def lemmatize(word): return lemmatizer.lemmatize(w.lower().strip())def tokenize(text): text = re.sub('[^a-zA-Z0-9]+', ' ', text) words = [lemmatize(w) for w in word_tokenize(text)] return [w for w in words if w not in stop_set]