我正在尝试对超过1000个(100, 100, 1000)数组进行一些计算。但正如我可以想象的那样,不超过150-200个数组,我的内存就会用完,而且都会失败(至少在我当前的代码中是这样)。
这就是我现在所拥有的:
import numpy as np
toxicity_data_path = open("data/toxicity.txt", "r")
toxicity_data = np.array(toxicity_data_path.read().split("\n"), dtype=int)
patients = range(1, 1000, 1)上面只是每个数组的1和0的列表(指示毒性或无毒性)(在本例中,一个数组是一个患者的数据)。所以在这种情况下,大约有1000名患者。
然后,我从上面的代码创建了两个列表,因此我有一个包含有毒性的患者的列表和一个没有毒性的患者的列表。
patients_no_tox = [i for i, e in enumerate(toxicity_data.astype(np.str)) if e in set("0")]
patients_with_tox = [i for i, e in enumerate(toxicity_data.astype(np.str)) if e in set("1")]然后,我编写了这个函数,它为每个患者获取一个已经保存到磁盘的数组((100, 100, 1000)),然后删除每个数组上的一些索引(也是从保存的文件中加载的),这些索引稍后将无法工作,或者只需要删除。因此,这样做是必要的。结果是所有患者及其3D数据阵列的最终列表。当在列表理解中使用函数时,这就是事情开始消耗内存的地方。
def log_likely_list(patient, remove_index_list):
array_data = np.load("data/{}/array.npy".format(patient)).ravel()
return np.delete(array_data, remove_index_list)
remove_index_list = np.load("data/remove_index_list.npy")
final_list = [log_likely_list(patient, remove_index_list) for patient in patients]下一步是创建我的计算所需的两个列表。我采用最终列表,包括所有患者,并分别删除有毒性或无毒性的患者。
patients_no_tox_list = np.column_stack(np.delete(final_list, patients_with_tox, 0))
patients_with_tox_list = np.column_stack(np.delete(final_list, patients_no_tox, 0))最后一块拼图是在下面的等式中使用这两个列表,其中我将非毒性列表放在等式的右侧,而将毒性列表放在左侧。然后,对于所有患者的3D数组中的每个单独索引,它对所有1000名患者求和,即每个3D数组/患者中的相同索引,然后我得到了一个相当大的值列表。
log_likely = np.sum(np.log(patients_with_tox_list), axis=1) +
np.sum(np.log(1 - patients_no_tox_list), axis=1)如上所述,我的问题是,当我达到150-200时(在patients范围内),我的内存被使用了,它就会关闭。显然,我已经尝试过将内容保存在磁盘上以便加载(这就是我加载这么多文件的原因),但这对我没有太大帮助。我在想,也许我可以一次处理一个数组,然后进入log_likely函数,但最后,在求和之前,我可能只有一个和数组一样大的数组,另外,如果我不能使用numpy sum特征等,计算速度可能会慢得多。
那么,有没有什么方法可以优化/改进这一点,或者是唯一的方法,但更多的地狱RAM?
发布于 2018-08-13 09:02:05
每次使用列表理解时,都会在内存中创建数据的新副本。所以这一行:
final_list = [log_likely_list(patient, remove_index_list) for patient in patients]包含所有1000名患者的完整数据!
更好的选择是使用生成器表达式,它一次处理一个项目。要形成生成器,请使用圆括号而不是括号将for...in...:表达式括起来。这可能看起来像这样:
with_tox_data = (log_likely_list(patient, remove_index_list) for patient in patients_with_tox)
with_tox_log = (np.log(data, axis=1) for data in with_tox_data)
no_tox_data = (log_likely_list(patient, remove_index_list) for patient in patients_no_tox)
no_tox_log = (np.log(1 - data, axis=1) for data in no_tox_data)
final_data = itertools.chain(with_tox_log, no_tox_log)请注意,实际上还没有执行任何计算:在迭代生成器之前,生成器不会执行任何操作。在本例中,聚合所有结果的最快方法是is to use reduce:
log_likely = functools.reduce(np.add, final_data)https://stackoverflow.com/questions/51813567
复制相似问题