【问题标题】:Is there a faster way to preprocess huge amount of text data in Python?有没有更快的方法来预处理 Python 中的大量文本数据?
【发布时间】:2020-07-31 23:51:46
【问题描述】:

我正在构建情绪分析算法来预​​测 IMDb 评论的分数。我想从头开始,所以我收集了 50 万条评论并创建了自己的数据集。

我正在将小型评论包(包含 50 条评论)发送到带有池的 review_cleaner。它帮助我将 1000 条评论的运行时间从 40 分钟减少到 11 分钟。但是,我有 50 万条评论,我需要更快的方法来处理它们。我在想是否可以在我的 GPU (GTX1060 6GB) 上运行它?我安装了 CUDA,但找不到如何在 GPU 内核上运行特定功能(review_cleaner)。

基本上,我需要的是更快运行预处理的解决方案。我搜索并尝试了许多不同的东西,但无法做到。有什么方法可以更快的运行吗?

def filling_the_database(review_data): 
    try:
        c.executemany("""INSERT INTO preprocessed_reviews(review, review_score) VALUES (?, ?)""", review_data)
        conn.commit()
    except Error as e:
        print(e)


def get_wordnet_pos(word):
    """Map POS tag to first character lemmatize() accepts"""
    tag = nltk.pos_tag([word])[0][1][0].upper()
    tag_dict = {"J": wordnet.ADJ,
                "N": wordnet.NOUN,
                "V": wordnet.VERB,
                "R": wordnet.ADV}

    return tag_dict.get(tag, wordnet.NOUN)


def review_cleaner(review):
    lemmatizer = WordNetLemmatizer()
    new_review_data = ()
    bulk_data = []
    for each in review:
        review_temp = ''.join([i for i in each[0] if not i.isdigit()])
        review_temp = REPLACE_NO_SPACE.sub(" ", review_temp.lower())
        review_temp = nltk.word_tokenize(review_temp)
        review_temp = (lemmatizer.lemmatize(word, get_wordnet_pos(word)) for word in review_temp)
        review_temp = ' '.join([word for word in review_temp if word not in stopwords.words('english')])
        new_review_data = (review_temp, each[1])
        bulk_data.append(new_review_data)
    filling_the_database(bulk_data)


if __name__ == "__main__":
    review_data = ()
    bulk_data = []
    amount_of_reviews = 0
    previous_amount = 0
    conn = create_connection('2020-04-11')
    c = conn.cursor()
    c.execute("""CREATE TABLE IF NOT EXISTS preprocessed_reviews(review TEXT, review_score INTEGER, ID PRIMARY KEY)""")
    conn.commit()
    total_number_of_reviews = c.execute("""SELECT COUNT(*) FROM movie_reviews""")
    for each in total_number_of_reviews:
        total_number_of_reviews = each[0]
    while amount_of_reviews < total_number_of_reviews:
        review_package = []
        amount_of_reviews += 50
        data = c.execute("""SELECT * FROM movie_reviews WHERE ID BETWEEN (?) AND (?)""", (previous_amount, amount_of_reviews-1))
        conn.commit()
        previous_amount = amount_of_reviews
        for each in data:
            review_data = (each[0], each[1])
            review_package.append(review_data)
            del review_data
        bulk_data.append(review_package)
        del review_package
        print(amount_of_reviews)
    p = Pool(4)
    p.map(review_cleaner, bulk_data)
    p.close()
    print('---- %s seconds ----' % (time.time() - start_time))

我在 SQLite 数据库中存储了大约一百万 (400k) 条评论。一栏用于评价,一栏用于评价评分。在另一个表中,我以相同的方式插入预处理的评论,一列用于评论,一列用于评分。我有 16 GB 的 RAM、Intel i7 6700HQ、SSD 和 GTX1060 6GB。

【问题讨论】:

  • Code Review 可能是比这里发布问题更好的地方。
  • 由于没有数值计算,GPU在这里没有用处。您如何存储 5000 万条评论?您如何阅读这些评论?你的机器配置是什么?请相应地更新问题
  • 如果它主要是在做 I/O 然后尝试使用线程
  • 尝试使用更快的 spacy,而不是词形还原,我建议使用词干提取,这可能会使您的性能下降一点,但操作要简单得多,并且会让您大大加快速度。请参阅有关如何使用 spacy 的标记化和词干提取的指南,请注意,您必须关闭解析器标志才能使 spacy 真正加快速度。

标签: python gpgpu sentiment-analysis preprocessor gpu


【解决方案1】:

我的脑海里闪过一些想法。

  1. 从 SQLite 读取和写入可能会产生相当多的开销,而实际上您可以在 16GB 的内存中容纳 500k 条评论。您可以通过将数据转储到表格 csv 文件中,然后使用 pandas 将其读入以进行预处理来做到这一点。您还可以使用 pandarallel 来并行化工作,而不是使用 pool 来让您的生活更轻松。

  2. 如果 SQLite 不是瓶颈,那么它很可能是计算瓶颈,在这种情况下,我会考虑在一夜之间运行该流程,或者租用具有良好 cpu 资源的云计算实例。在 AWS 上短期租用 16 核机器不会太贵,理论上可以实现 4 倍的加速。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-25
    • 2021-04-06
    • 2019-10-17
    • 2021-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多