【发布时间】:2017-08-28 12:57:23
【问题描述】:
我有一个 df:
id text
1 This is a good sentence
2 This is a sentence with a number: 2015
3 This is a third sentence
我有一个文本清理功能:
def clean(text):
lettersOnly = re.sub('[^a-zA-Z]',' ', text)
tokens = word_tokenize(lettersOnly.lower())
stops = set(stopwords.words('english'))
tokens = [w for w in tokens if not w in stops]
tokensPOS = pos_tag(tokens)
tokensLemmatized = []
for w in tokensPOS:
tokensLemmatized.append(WordNetLemmatizer().lemmatize(w[0], get_wordnet_pos(w[1])))
clean = " ".join(tokensLemmatized)
return clean
get_wordnet_pos()是这个:
def get_wordnet_pos(treebank_tag):
if treebank_tag.startswith('J'):
return wordnet.ADJ
elif treebank_tag.startswith('V'):
return wordnet.VERB
elif treebank_tag.startswith('N'):
return wordnet.NOUN
elif treebank_tag.startswith('R'):
return wordnet.ADV
else:
return wordnet.NOUN
我正在将 extractFeatures() 应用于 pandas 列并创建一个包含结果的新列:
df['cleanText'] = df['text'].apply(clean)
结果df:
id cleanText
1 good sentence
2 sentence number
3 third sentence
循环时间似乎呈指数增长。例如,使用%%timeit,将其应用于五行,每个循环运行 17 毫秒。 300 行以每个循环 800 毫秒运行。 500 行以每个循环 1.26 秒的速度运行。
我通过在函数外部实例化 stops 和 WordNetLemmatizer() 来更改它,因为它们只需要调用一次。
stops = set(stopwords.words('english'))
lem = WordNetLemmatizer()
def clean(text):
lettersOnly = re.sub('[^a-zA-Z]',' ', text)
tokens = word_tokenize(lettersOnly.lower())
tokens = [w for w in tokens if not w in stops]
tokensPOS = pos_tag(tokens)
tokensLemmatized = []
for w in tokensPOS:
tokensLemmatized.append(lem.lemmatize(w[0], get_wordnet_pos(w[1])))
clean = " ".join(tokensLemmatized)
return clean
在apply 行上运行%prun -l 10 会生成此表:
672542 function calls (672538 primitive calls) in 2.798 seconds
Ordered by: internal time
List reduced from 211 to 10 due to restriction <10>
ncalls tottime percall cumtime percall filename:lineno(function)
4097 0.727 0.000 0.942 0.000 perceptron.py:48(predict)
4500 0.584 0.000 0.584 0.000 {built-in method nt.stat}
3500 0.243 0.000 0.243 0.000 {built-in method nt._isdir}
14971 0.157 0.000 0.178 0.000 {method 'sub' of '_sre.SRE_Pattern' objects}
57358 0.129 0.000 0.155 0.000 perceptron.py:250(add)
4105 0.117 0.000 0.201 0.000 {built-in method builtins.max}
184365 0.084 0.000 0.084 0.000 perceptron.py:58(<lambda>)
4097 0.057 0.000 0.213 0.000 perceptron.py:245(_get_features)
500 0.038 0.000 1.220 0.002 perceptron.py:143(tag)
2000 0.034 0.000 0.068 0.000 ntpath.py:471(normpath)
可以预见,感知器标记器似乎占用了大量资源,但我不确定如何简化它。此外,我不确定在哪里调用 nt.stat 或 nt._isdir。
我应该如何更改函数或应用方法以提高性能?这个函数是 Cython 还是 Numba 的候选函数?
【问题讨论】:
-
不能说没有您的数据和预期的输出。
-
添加了样本输入数据和清洗功能的结果。我得到了正确的输出 - 问题更多是关于如何更快地获得正确的输出。
-
有趣。单词的顺序重要吗?我猜是的?
-
是的,因为
cleanedText稍后会被发送到矢量化器以收集 ngram、频率、tf-idf 权重等。 -
我看到最明显的改进点是将
get_wordnet_pos减少为strdefaultdict。
标签: python performance pandas nltk apply