使用NLTK预处理模型输入文本时触发RecursionError求助
解决PorterStemmer文本预处理时触发的RecursionError问题
问题描述
我在用这段代码对文本做预处理(准备输入模型)时,触发了RecursionError: maximum recursion depth exceeded in comparison错误:
train_corpus = [] for i in range(0, len(train_text)): data = re.sub("[^a-zA-Z]", ' ', train_text[i]).lower().split() data = [ps.stem(word) for word in data if not word in set(stopwords.words("english"))] data = ' '.join(data) train_corpus.append(data)
其中train_text是存储文本的Pandas Series,ps是NLTK的PorterStemmer对象。
解决方案
这个错误的核心原因是PorterStemmer的递归实现遇到了极端单词(比如超长词、带有重复后缀的特殊词),导致无限递归,超过了Python默认的递归深度限制。下面给你几个可行的解决思路:
1. 替换为更稳定的词干提取器
PorterStemmer的递归逻辑比较容易触发这类问题,换成NLTK的SnowballStemmer会更稳定——它是Porter算法的改进版,用迭代代替了部分递归,对极端情况的处理更好:
from nltk.stem.snowball import SnowballStemmer # 初始化SnowballStemmer ps = SnowballStemmer("english") # 后续预处理代码不变 train_corpus = [] for i in range(0, len(train_text)): data = re.sub("[^a-zA-Z]", ' ', train_text[i]).lower().split() data = [ps.stem(word) for word in data if not word in set(stopwords.words("english"))] data = ' '.join(data) train_corpus.append(data)
如果不需要严格的词干提取,也可以用WordNetLemmatizer(词形还原),它基于词典,逻辑更简单,几乎不会出现递归问题:
from nltk.stem import WordNetLemmatizer from nltk.corpus import wordnet # 初始化词形还原器 lemmatizer = WordNetLemmatizer() # 预处理代码修改为词形还原 train_corpus = [] for i in range(0, len(train_text)): data = re.sub("[^a-zA-Z]", ' ', train_text[i]).lower().split() # 可选:给lemmatize指定词性(默认是名词),提升还原效果 data = [lemmatizer.lemmatize(word, pos=wordnet.VERB) for word in data if not word in set(stopwords.words("english"))] data = ' '.join(data) train_corpus.append(data)
2. 过滤超长单词
如果坚持要用PorterStemmer,可以在预处理时过滤掉过长的单词(比如长度超过20的词),这类词往往是触发递归问题的元凶:
train_corpus = [] for i in range(0, len(train_text)): data = re.sub("[^a-zA-Z]", ' ', train_text[i]).lower().split() # 增加长度过滤条件 data = [ps.stem(word) for word in data if not word in set(stopwords.words("english")) and len(word) < 20] data = ' '.join(data) train_corpus.append(data)
3. 不推荐:临时提高递归深度
虽然可以用sys.setrecursionlimit()临时提高Python的递归深度,但这只是治标不治本,还可能导致栈溢出崩溃,除非你确定问题只是偶然触发,否则不建议这么做:
import sys # 提高递归深度到10000(默认是1000) sys.setrecursionlimit(10000) # 然后执行你的预处理代码
内容的提问来源于stack exchange,提问作者user9176398
相关产品推荐
相关产品推荐

