【问题标题】:Looking for a quick way to speed up my code寻找一种快速的方法来加快我的代码
【发布时间】:2014-01-09 12:01:24
【问题描述】:

我正在寻找一种方法来加快我的代码。我设法加快了我的大部分代码,将运行时间减少到大约 10 小时,但它仍然不够快,因为我的时间不多了,我正在寻找一种快速优化我的代码的方法。

一个例子:

text = pd.read_csv(os.path.join(dir,"text.csv"),chunksize = 5000)
new_text = [np.array(chunk)[:,2] for chunk in text]
new_text = list(itertools.chain.from_iterable(new_text))

在上面的代码中,我以块的形式读取了大约 600 万行文本文档并将它们展平。此代码大约需要 3-4 小时才能执行。这是我的程序的主要瓶颈。 编辑:我意识到我不是很清楚主要问题是什么,扁平化是最耗时的部分。

我的程序的这一部分也需要很长时间:

    train_dict = dict(izip(text,labels))
    result = [train_dict[test[sample]] if test[sample] in train_dict else predictions[sample] for sample in xrange(len(predictions))]

上面的代码首先压缩带有相应标签的文本文档(这是一个机器学习任务,train_dict 是训练集)。在程序的早期,我在测试集上生成了预测。我的火车和测试集之间有重复,所以我需要找到那些重复。因此,我需要逐行迭代我的测试集(总共 200 万行),当我找到重复项时,我实际上不想使用预测标签,而是使用 train_dict 中重复项的标签。我把这次迭代的结果赋给了上面代码中的变量result。

我听说 python 中有各种库可以加速你的部分代码,但我不知道其中哪些可以完成这项工作,而且我知道我没有时间研究这个,这就是为什么我需要有人指出我正确的方向。有没有一种方法可以加快上面的代码 sn-ps 速度?

edit2

我又调查了一遍。这绝对是一个内存问题。我尝试逐行读取文件,一段时间后速度急剧下降,而且我的ram使用率接近100%,python的磁盘使用率急剧增加。如何减少内存占用?或者我应该找到一种方法来确保我不会将所有内容都记住?

edit3 由于记忆是我的问题的主要问题,我将概述我的程序的一部分。我暂时放弃了预测,这大大降低了我的程序的复杂性,而是为我的测试集中的每个非重复插入一个标准样本。

import numpy as np
import pandas as pd
import itertools
import os

train = pd.read_csv(os.path.join(dir,"Train.csv"),chunksize = 5000)
train_2 = pd.read_csv(os.path.join(dir,"Train.csv"),chunksize = 5000)
test = pd.read_csv(os.path.join(dir,"Test.csv"), chunksize = 80000)
sample = list(np.array(pd.read_csv(os.path.join(dir,"Samples.csv"))[:,2]))#this file is only 70mb
sample = sample[1]
test_set = [np.array(chunk)[:,2] for chunk in test]
test_set = list(itertools.chain.from_iterable(test_set))

train_set = [np.array(chunk)[:,2] for chunk in train]
train_set = list(itertools.chain.from_iterable(train_set))
labels = [np.array(chunk)[:,3] for chunk in train_2]
labels = list(itertools.chain.from_iterable(labels))

"""zipping train and labels"""
train_dict = dict(izip(train,labels))
"""finding duplicates"""
results = [train_dict[test[item]] if test[item] in train_dict else sample for item in xrange(len(test))]

虽然这不是我的整个程序,但这是我的代码中需要优化的部分。正如你所看到的,我在这一部分只使用了三个重要的模块,pandas、numpy 和 itertools。展平 train_set 和 test_set 时会出现内存问题。我唯一要做的就是阅读文件,获取必要的部分,用字典中的相应标签压缩火车文件。然后搜索重复项。

编辑 4 根据要求,我将解释我的数据集。我的 Train.csv 包含 4 列。第一列包含每个样本的 ID,第二列包含标题,第三列包含文本正文样本(从 100 到 700 个单词不等)。第四列包含类别标签。 Test.csv 仅包含 ID 和文本正文和标题。各列以逗号分隔。

【问题讨论】:

  • text.csv 的大小(MB)是多少?
  • text.csv 的大小接近 7000 MB。
  • numpy 可以读取 CSV 文件,numpy 的许多部分都经过了高度优化(尽管我不确定它的 CSV 阅读器)。另外:存储 7000MB 文件的设备是“快速”设备吗?你能把它放在一个 ramdisk 上以便更好地隔离问题吗?
  • 我自己在考虑一个 RAMdisk,以尝试定位问题 :-) 虽然速度为 100MB/s(大多数现代磁盘都可以做到),但 I/O 只有 70 秒,所以有优化这个可能没什么收获......不过可能值得一试。
  • 我只是将它存储在我的硬盘上。我确实有一个 SSD(大约 25 个演出),这可行吗?

标签: python performance python-2.7 optimization pandas


【解决方案1】:

能否请您发布一个六行左右的虚拟样本数据集?

我不太清楚您的代码在做什么,而且我不是 Pandas 专家,但我认为我们可以大大加快这段代码的速度。它将所有数据读入内存,然后不断将数据重新复制到各个地方。

通过编写“惰性”代码,我们应该能够避免所有重新复制。理想的情况是读取一行,根据需要对其进行转换,然后将其存储到最终目的地。此外,当它应该只是迭代值时,此代码使用索引;我们也可以在那里加快速度。

您发布的代码是您的实际代码,还是您制作的只是为了发布在这里的代码?它似乎包含一些错误,所以我不确定它实际上做了什么。特别是,trainlabels 似乎包含相同的数据。

我会回来查看您是否发布了示例数据。如果是这样,我可能会为您编写“惰性”代码,这样可以减少数据的重新复制并且速度会更快。

编辑:根据您的新信息,这是我的虚拟数据:

id,title,body,category_labels
0,greeting,hello,noun
1,affirm,yes,verb
2,deny,no,verb

以下是读取上述内容的代码:

def get_train_data(training_file):
    with open(training_file, "rt") as f:
        next(f)  # throw away "headers" in first line
        for line in f:
            lst = line.rstrip('\n').split(',')
            # lst contains: id,title,body,category_labels
            yield (lst[1],lst[2])

train_dict = dict(get_train_data("data.csv"))

这是构建results的更快方法:

results = [train_dict.get(x, sample) for x in test]

我们没有重复索引test 来查找下一项,而是迭代测试中的值。 dict.get() 方法处理我们需要的 if x in train_dict 测试。

【讨论】:

  • 非常感谢。我在定义火车和标签时犯了错字,我也会对其进行编辑。我将提供和虚拟样本集。
  • 一个问题。数据集中的文本样本非常大。您是否真的需要它们,或者对数据集的解释就足够了?
  • 我只需要了解您的程序在做什么。具有相同形状的“玩具”数据可以正常工作。例如,如果您的数据是一本书的全部内容,您可以只输入一个字符串,例如“一本书的全部内容都放在这里”,这很好。
  • 好的,那我给你拿来。
  • 我的火车数据包含四列,请参阅编辑以获取解释。
【解决方案2】:

你可以试试Cython。它支持 numpy 并且可以给你一个很好的加速。 这里是需要做的介绍和解释 http://www.youtube.com/watch?v=Iw9-GckD-gQ

【讨论】:

    【解决方案3】:

    如果行的顺序不重要,您可以使用集合来查找在训练集中但不在测试集中的元素(交叉训练集和测试集),然后将它们首先添加到您的“结果”中,然后使用集合差异(testset-trainset) 添加测试集中但不在训练集中的元素。这样可以节省检查样本是否在训练集中的时间。

    【讨论】:

    • 感谢您的回答,不幸的是顺序很重要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    相关资源
    最近更新 更多