【发布时间】:2020-05-30 14:48:34
【问题描述】:
我有一个 Python 脚本,我在其中大量使用 numpy。我最近了解了更多关于 numpys 固有并行化的知识,应该避免使用 numpy 进行大的 for 循环,而是依赖隐式并行索引。
我的脚本中有一个非常大的 for 循环(实际上包含另一个 for 循环)。该循环将数据拆分为训练集和测试集,以某种方式独立操作每个集,拟合模型并重复。这是一个 n 次重复的 k-fold。
但是,脚本非常慢,如果 n 和 k 很大,似乎会导致内存泄漏。我认为这也是由于巨大的 for 循环。所以我想摆脱 for 循环并以并行方式使用拆分。但是,我没有成功。这是我的脚本中发生的事情:
第一位是通用的:
from sklearn.model_selection import RepeatedKFold
import ...
#Some data is imported, functions defined, variables pre-allocated.
number_conditions = 10 #Usually bigger.
output = np.array(number_conditions, number_conditions) #This contains real data, though.
outer_k = 5
outer_reps = 1 # usually much higher
outer_rkf = RepeatedKFold(n_splits=outer_k, n_repeats=outer_reps)
array_for_indices = list(range(number_conditions))
这是非高效的for循环版本:
for train_indices, test_indices in outer_rkf.split(array_for_indices):
ixgrid_train = np.ix_(train_indices, train_indices)
output_train = output[ixgrid_train]
ixgrid_test = np.ix_(test_indices, test_indices)
output_test = output[ixgrid_test]
...
这之后是一些繁重的数据操作和另一个嵌套的 for 循环,然后重复 (outer_k*outer_reps) 次。
我想并行化这个并尝试了这个:
outer_split_1, outer_split_2, outer_split_3, outer_split_4, outer_split_5 = outer_rkf.split(array_for_indices)
index = np.array([outer_split_1, outer_split_2, outer_split_3, outer_split_4, outer_split_5])
all_train_inds = index[:, 0]
all_test_inds = index[:, 1]
ixgrid_train = np.ix_(all_train_inds, all_train_inds)
output_train = output[ixgrid_train]
但最后一行给了我
IndexError: 用作索引的数组必须是整数(或布尔)类型
哪种对我有意义:在 for 循环版本中,ixgrid_train 是一个包含两个整数数组的元组。在后一个版本中,它是一个包含两个对象数组的元组,这些对象又包含数组。
我尝试使 index 不是一个数组,而是一个元组或列表,并尝试以不同的方式索引 index(写这表明我 index 可能是一个有待改进的名称)。但是,我从来没有实现我想要的:output_train 不仅包含一次拆分所需的数据,而且包含所有数据,并且一次性分配。
我的问题的根本在于我不知道如何从根本上增加我正在做的事情的维度。我想我需要将我在循环版本中循环的维度转换为我正在操作的对象的维度,但我不知道如何做到这一点,这会产生实际的并行性。特别是,因为元组让我感到困惑。
我怎样才能实现我想要的:一次为所有折叠创建所有索引,然后一次为每个折叠分配所有选定的数据,以便我以后可以继续并行处理?
感谢您的任何意见! :)
【问题讨论】:
-
如何更加关注这个问题?仅通过阅读您的描述,我无法想象发生了什么。我可以猜到迭代的
ixgrid_train是。但无法想象第二个。
标签: python numpy indexing parallel-processing