比如说,我有1D numpy数组X
(features)和Y
(binary class),还有一个函数f
,它接受X
和Y
的两个片并计算一个数。你知道吗
我还有一个索引数组S
,通过它我需要分割X
和Y
。可以保证,每个片都不会是空的。你知道吗
所以我的代码是这样的:
def f(x_left, y_left, x_right, y_right):
n = x_left.shape[0] + x_right.shape[0]
lcond = y_left == 1
rcond = y_right == 1
hleft = 1 - ((y_left[lcond].shape[0])**2
+ (y_left[~lcond].shape[0])**2) / n**2
hright = 1 - ((y_right[rcond].shape[0])**2
+ (y_right[~rcond].shape[0])**2) / n**2
return -(x_left.shape[0] / n) * hleft - (x_right.shape[0] / n) * hright
results = np.empty(len(S))
for i in range(len(S)):
results[i] = f(X[:S[i]], Y[:S[i]], X[S[i]:], Y[S[i]:])
数组results
必须包含来自S
的每次拆分的f
结果。你知道吗
len(results) == len(S)
我的问题是如何使用numpy以矢量化的方式执行计算,以使代码更快?你知道吗
首先,让我们让你的功能更有效率。您正在执行一些不必要的索引操作:您只需要
lcond.sum()
或len(lcond.nonzero()[0])
而不是y_left[lcond].shape[0]
,后者似乎更快。你知道吗下面是代码的改进循环版本(包括伪输入):
变化相当直接。你知道吗
现在,事实证明,我们确实可以矢量化你的循环。为此,我们必须同时使用
S
的每个元素进行比较。我们可以这样做的方法是创建一个形状为(nS, n)
(其中S.size == nS
)的2d掩码,它将值截止到S
的相应元素。方法如下:将原始解决方案定义为
time_orig()
运行,我们可以检查结果是否相同:以及具有上述随机输入的运行时:
这意味着上面的loopy版本几乎是原来的loopy版本的两倍,而矢量化版本则是原来的三倍。当然,后一种改进的代价是增加了内存需求:现在不再使用shape
(n,)
数组,而是使用shape(nS, n)
数组,如果您的输入数组很大,它会变得很大。但是正如他们所说的,没有免费的午餐,使用矢量化,你经常用运行时来换取内存。你知道吗相关问题 更多 >
编程相关推荐