用户警告:您的 stop_words 可能与您的预处理不一致
Posted
技术标签:
【中文标题】用户警告:您的 stop_words 可能与您的预处理不一致【英文标题】:User Warning: Your stop_words may be inconsistent with your preprocessing 【发布时间】:2019-12-11 21:18:52 【问题描述】:我正在关注this 文档聚类教程。作为输入,我给出了一个可以下载的 txt 文件here。它是使用 \n 划分的 3 个其他 txt 文件的组合文件。创建 tf-idf 矩阵后,我收到了以下警告:
,,UserWarning:您的 stop_words 可能与您的预处理不一致。标记停用词生成标记 ['abov', 'afterward', 'alon', 'alreadi', 'alway', 'ani', 'anoth', 'anyon', 'anyth', 'anywher', 'becam' ,'因为','becom','befor','besid','cri','描述','dure','els','elsewher','empti','everi','everyon','一切”,“无处不在”,“五十”,“福尔蒂”,“henc”,“此后”,“herebi”,“howev”,“hundr”,“inde”,“mani”,“meanwil”,“moreov” , 'nobodi', 'noon', 'noth', 'noher', 'onc', 'onli', 'otherwis', 'ourselv', 'perhap', 'pleas', 'sever', 'sinc', '真诚的','sixti','someon','someth','sometim','somewher','themselv','thenc','theaft','therebi','therefor','togeth','twelv' , 'twenti', 'veri', 'whatev', 'whenc', 'whenev', 'wherea', 'whereaft', 'wherebi', 'wherev', 'whi', 'yourself'] 不在停用词中。 “停用词。” % 排序(不一致))”。
我猜这与词形还原和停用词删除的顺序有关,但由于这是我在 txt 处理中的第一个项目,我有点迷茫,我不知道如何解决这个问题......
import pandas as pd
import nltk
from nltk.corpus import stopwords
import re
import os
import codecs
from sklearn import feature_extraction
import mpld3
from nltk.stem.snowball import SnowballStemmer
from sklearn.feature_extraction.text import TfidfVectorizer
stopwords = stopwords.words('english')
stemmer = SnowballStemmer("english")
def tokenize_and_stem(text):
# first tokenize by sentence, then by word to ensure that punctuation is caught as it's own token
tokens = [word for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]
filtered_tokens = []
# filter out any tokens not containing letters (e.g., numeric tokens, raw punctuation)
for token in tokens:
if re.search('[a-zA-Z]', token):
filtered_tokens.append(token)
stems = [stemmer.stem(t) for t in filtered_tokens]
return stems
def tokenize_only(text):
# first tokenize by sentence, then by word to ensure that punctuation is caught as it's own token
tokens = [word.lower() for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]
filtered_tokens = []
# filter out any tokens not containing letters (e.g., numeric tokens, raw punctuation)
for token in tokens:
if re.search('[a-zA-Z]', token):
filtered_tokens.append(token)
return filtered_tokens
totalvocab_stemmed = []
totalvocab_tokenized = []
with open('shortResultList.txt', encoding="utf8") as synopses:
for i in synopses:
allwords_stemmed = tokenize_and_stem(i) # for each item in 'synopses', tokenize/stem
totalvocab_stemmed.extend(allwords_stemmed) # extend the 'totalvocab_stemmed' list
allwords_tokenized = tokenize_only(i)
totalvocab_tokenized.extend(allwords_tokenized)
vocab_frame = pd.DataFrame('words': totalvocab_tokenized, index = totalvocab_stemmed)
print ('there are ' + str(vocab_frame.shape[0]) + ' items in vocab_frame')
print (vocab_frame.head())
#define vectorizer parameters
tfidf_vectorizer = TfidfVectorizer(max_df=0.8, max_features=200000,
min_df=0.2, stop_words='english',
use_idf=True, tokenizer=tokenize_and_stem, ngram_range=(1,3))
with open('shortResultList.txt', encoding="utf8") as synopses:
tfidf_matrix = tfidf_vectorizer.fit_transform(synopses) #fit the vectorizer to synopses
print(tfidf_matrix.shape)
【问题讨论】:
你检查过here或here吗? 您的链接显示上传不存在。 【参考方案1】:警告试图告诉您,如果您的文本包含“always”,则在匹配包含“always”但不包含“alway”的停止列表之前,它将被规范化为“alway”。所以它不会从你的词袋中删除。
解决方案是确保您预处理停止列表以确保它像您的标记一样被规范化,并将规范化单词列表作为stop_words
传递给矢量化器。
【讨论】:
这是一个相当烦人的任务。如果我将please
定义为停用词,向量化器会抱怨,因为它被标记为pleas
。如果我通过pleas
(即标记化的停用词),向量化器会抱怨,因为它被标记化为plea
。
@MERose,我仍然不相信有最好的方法来处理这个问题。不同的包有different stop word lists 和标记化/词形还原方法。有一种解决方法,可以使用或不使用停用词列表,即基于语料库的停用词。您可以使用CountVectorizer()
和TfidfVectorizer()
中的max_df
和min_df
来控制它。请参阅 stop_words here.【参考方案2】:
我遇到了同样的问题,对我来说以下工作:
-
将
stopwords
包含到tokenize
函数中,然后
从tfidfVectorizer
中删除stopwords
参数
像这样:
1.
stopwords = stopwords.words('english')
stemmer = SnowballStemmer("english")
def tokenize_and_stem(text):
tokens = [word for sent in nltk.sent_tokenize(text) for word in nltk.word_tokenize(sent)]
filtered_tokens = []
for token in tokens:
if re.search('[a-zA-Z]', token):
filtered_tokens.append(token)
#exclude stopwords from stemmed words
stems = [stemmer.stem(t) for t in filtered_tokens if t not in stopwords]
return stems
-
从矢量化器中删除
stopwords
参数:
tfidf_vectorizer = TfidfVectorizer(
max_df=0.8, max_features=200000, min_df=0.2,
use_idf=True, tokenizer=tokenize_and_stem, ngram_range=(1,3)
)
【讨论】:
我测试了你的代码,但它不是那么好。它将“Khadse”视为“khads”。 @edusanketdk 我的代码为提出的问题提供了一个很好的解决方案。您描述的问题是一个不同的问题,而不是由于我的代码,而主要是由于库的功能。请注意,我的回答是明确针对“英语”作为一种语言量身定制的,而“Khadse”不是英语母语单词。 确实如此。但是数据总是会包含不在英语词汇表中的名词和名称。因此,显然希望创建一个不会像那样失败的健壮模型。另外,我知道这是图书馆的问题,所以我们不应该使用它们,或者至少进行一些优化。对吗? @edusanketdk 我想在这种情况下,您可以手动扩展停用词列表以包含常用的非英语单词。据我所见,nltk 库仍然是目前使用最广泛、工作最好的库之一。如果您知道一个更好的库,请随意添加另一个答案。 @GasparAvitFerrero 是的,我认为您可能是对的,而且很有发现。【参考方案3】:由于 PT-BR 语言,我遇到了这个问题。
TL;DR:删除您的语言的重音。
# Special thanks for the user Humberto Diogenes from Python List (answer from Aug 11, 2008)
# Link: http://python.6.x6.nabble.com/O-jeito-mais-rapido-de-remover-acentos-de-uma-string-td2041508.html
# I found the issue by chance (I swear, haha) but this guy gave the tip before me
# Link: https://github.com/scikit-learn/scikit-learn/issues/12897#issuecomment-518644215
import spacy
nlp = spacy.load('pt_core_news_sm')
# Define default stopwords list
stoplist = spacy.lang.pt.stop_words.STOP_WORDS
def replace_ptbr_char_by_word(word):
""" Will remove the encode token by token"""
word = str(word)
word = normalize('NFKD', word).encode('ASCII','ignore').decode('ASCII')
return word
def remove_pt_br_char_by_text(text):
""" Will remove the encode using the entire text"""
text = str(text)
text = " ".join(replace_ptbr_char_by_word(word) for word in text.split() if word not in stoplist)
return text
df['text'] = df['text'].apply(remove_pt_br_char_by_text)
I put the solution and references in this gist.
【讨论】:
以上是关于用户警告:您的 stop_words 可能与您的预处理不一致的主要内容,如果未能解决你的问题,请参考以下文章
金蝶提示: 激活控件'VB.UserControl'失败.这个控件可能与您的应用程序不兼容.确定您使用的这个版.