提高数据预处理速度 - Python 中的正则表达式
Improve Data Preprocessing Speed - Regex in Python
我在 Python 中使用以下 class 对字符串进行预处理,然后再将其传递给机器学习 class化模型以预测其情绪。
我使用正则表达式进行大部分转换以及一些库,如表情符号和推文预处理器。代码工作正常,但我认为它很慢。
你对如何提高它的速度有什么建议吗?
用法示例:
string = "I am very happy with @easyjet #happy customer . Second sentence"
preprocessor = TextPreprocessing()
result = preprocessor.text_preprocessor(string)
结果将是:[“我很开心,笑脸很开心”,“第二句”,“我很开心,笑脸很开心,第二句”]
import re
import preprocessor as p # this is the tweet-preprocessor library
import emoji
import os
import numpy as np
import pandas as pd
class TextPreprocessing:
def __init__(self):
p.set_options(p.OPT.MENTION, p.OPT.URL)
# remove punctuation
def _punctuation(self, val):
val = re.sub(r'[^\w\s]', ' ', val)
val = re.sub('_', ' ', val)
return val
#remove white spaces
def _whitespace(self, val):
return " ".join(val.split())
#remove numbers
def _removenumbers(self, val):
val = re.sub('[0-9]+', '', val)
return val
#remove unicode
def _remove_unicode(self, val):
val = unidecode(val).encode("ascii")
val = str(val, "ascii")
return val
#split string into sentenses
def _split_to_sentences(self, body_text):
sentences = re.split(
r"(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s", body_text)
return sentences
# cleaning functions that combines all of the above functions
def _clean_text(self, val):
val = val.lower()
val = self._removenumbers(val)
val = p.clean(val)
val = ' '.join(self._punctuation(emoji.demojize(val)).split())
val = self._remove_unicode(val)
val = self._whitespace(val)
return val
def text_preprocessor(self, body_text):
body_text_df = pd.DataFrame({"body_text": body_text}, index=[1])
sentence_split_df = body_text_df.copy()
sentence_split_df["body_text"] = sentence_split_df["body_text"].apply(
self._split_to_sentences)
lst_col = "body_text"
sentence_split_df = pd.DataFrame(
{
col: np.repeat(
sentence_split_df[col].values, sentence_split_df[lst_col].str.len(
)
)
for col in sentence_split_df.columns.drop(lst_col)
}
).assign(**{lst_col: np.concatenate(sentence_split_df[lst_col].values)})[
sentence_split_df.columns
]
final_df = (
pd.concat([sentence_split_df, body_text_df])
.reset_index()
.drop(columns=["index"])
)
final_df["body_text"] = final_df["body_text"].apply(self._clean_text)
return final_df["body_text"]
这个问题可能与所有想要将其 NLP 模型投入生产的数据科学家有关。
由于我无法发表评论,我将尝试(在某种程度上)回答您的问题:
- 您应该阐明如何衡量执行时间的改进。为此使用 timeit 及其重复功能:
import timeit
from functools import partial
...
if __name__ == "__main__":
# http://25.io/toau/audio/sample.txt
with open("sample.txt") as f:
text = f.read()
tp = TextPreprocessing()
print(min(timeit.Timer(partial(tp.text_preprocessor, text)).repeat(repeat=10, number=1)))
您还可以在特定方法上使用 timeit 来检查瓶颈。
很遗憾,由于 L58 和 L64 中未定义 np.
,我无法 运行 您的代码示例
所以我无法检验我的假设。你也没有提供样本数据。
一些一般性想法:
- 使用
re.compile()
编译所有正则表达式
- 如果您不需要 _remove* 的模块化,您可以考虑组合这些正则表达式
.copy()
操作是昂贵的尝试摆脱它们
- 还有一些 _remove* 方法有异味。请参阅替代方案的链接:
Removing numbers from string
我在 Python 中使用以下 class 对字符串进行预处理,然后再将其传递给机器学习 class化模型以预测其情绪。
我使用正则表达式进行大部分转换以及一些库,如表情符号和推文预处理器。代码工作正常,但我认为它很慢。
你对如何提高它的速度有什么建议吗?
用法示例:
string = "I am very happy with @easyjet #happy customer . Second sentence"
preprocessor = TextPreprocessing()
result = preprocessor.text_preprocessor(string)
结果将是:[“我很开心,笑脸很开心”,“第二句”,“我很开心,笑脸很开心,第二句”]
import re
import preprocessor as p # this is the tweet-preprocessor library
import emoji
import os
import numpy as np
import pandas as pd
class TextPreprocessing:
def __init__(self):
p.set_options(p.OPT.MENTION, p.OPT.URL)
# remove punctuation
def _punctuation(self, val):
val = re.sub(r'[^\w\s]', ' ', val)
val = re.sub('_', ' ', val)
return val
#remove white spaces
def _whitespace(self, val):
return " ".join(val.split())
#remove numbers
def _removenumbers(self, val):
val = re.sub('[0-9]+', '', val)
return val
#remove unicode
def _remove_unicode(self, val):
val = unidecode(val).encode("ascii")
val = str(val, "ascii")
return val
#split string into sentenses
def _split_to_sentences(self, body_text):
sentences = re.split(
r"(?<!\w\.\w.)(?<![A-Z][a-z]\.)(?<=\.|\?)\s", body_text)
return sentences
# cleaning functions that combines all of the above functions
def _clean_text(self, val):
val = val.lower()
val = self._removenumbers(val)
val = p.clean(val)
val = ' '.join(self._punctuation(emoji.demojize(val)).split())
val = self._remove_unicode(val)
val = self._whitespace(val)
return val
def text_preprocessor(self, body_text):
body_text_df = pd.DataFrame({"body_text": body_text}, index=[1])
sentence_split_df = body_text_df.copy()
sentence_split_df["body_text"] = sentence_split_df["body_text"].apply(
self._split_to_sentences)
lst_col = "body_text"
sentence_split_df = pd.DataFrame(
{
col: np.repeat(
sentence_split_df[col].values, sentence_split_df[lst_col].str.len(
)
)
for col in sentence_split_df.columns.drop(lst_col)
}
).assign(**{lst_col: np.concatenate(sentence_split_df[lst_col].values)})[
sentence_split_df.columns
]
final_df = (
pd.concat([sentence_split_df, body_text_df])
.reset_index()
.drop(columns=["index"])
)
final_df["body_text"] = final_df["body_text"].apply(self._clean_text)
return final_df["body_text"]
这个问题可能与所有想要将其 NLP 模型投入生产的数据科学家有关。
由于我无法发表评论,我将尝试(在某种程度上)回答您的问题:
- 您应该阐明如何衡量执行时间的改进。为此使用 timeit 及其重复功能:
import timeit
from functools import partial
...
if __name__ == "__main__":
# http://25.io/toau/audio/sample.txt
with open("sample.txt") as f:
text = f.read()
tp = TextPreprocessing()
print(min(timeit.Timer(partial(tp.text_preprocessor, text)).repeat(repeat=10, number=1)))
您还可以在特定方法上使用 timeit 来检查瓶颈。
很遗憾,由于 L58 和 L64 中未定义
np.
,我无法 运行 您的代码示例 所以我无法检验我的假设。你也没有提供样本数据。一些一般性想法:
- 使用
re.compile()
编译所有正则表达式 - 如果您不需要 _remove* 的模块化,您可以考虑组合这些正则表达式
.copy()
操作是昂贵的尝试摆脱它们- 还有一些 _remove* 方法有异味。请参阅替代方案的链接:
Removing numbers from string