我的代码有以下目标:
1.)给定2个numpy数组,a1和a2 (仅由0,1‘s组成)在a1和a2中查找0的索引位置。
2.)查找数组a1和a2之间的匹配索引位置(如果有的话)
3.)计算公制
a1阵列形状= 2161
a2阵列形状= 2161
例如:
a1 =0,1,1,1,1,1
a2 =1,1,0,0,1,0
a1 = idx_a10,3,5中0's的指数
a2 = idx_a22,3,6中0's的指数
公共0's指数b/w a1和a2 =3
function_1执行step1、step2和step3
function1_iterations在随机洗牌a1和重复度量计算1000次后重复function_1。这是为了找出度量是否具有统计意义。
我在一亿个数组对上执行下面的代码,在256个核上进行多处理。1亿数组对的最佳运行时间约为40分钟。有什么办法能让它变得高效吗?我需要在数十亿个数组对上运行这个程序。
下面的代码是我能在前面从codereview获得一些帮助的最快的代码:
def function_1(self,a1, a2):
event_index1, = np.where(a1 == 0)
event_index2, = np.where(a2 == 0)
n1, = event_index1.shape
n2, = event_index2.shape
if n1 == 0 or n2 == 0:
return 0, 0
n_matches, = np.intersect1d(event_index1, event_index2, assume_unique=True,).shape
c_ij = n_matches/2
metric_1= (c_ij *2) / math.sqrt(n1 * n2)
return metric_1
def function1_iterations(self,a1,a2,repeat = 1000,original_metric1):
list_metric1 = []
a1_copy = copy.deepcopy(a1)
for i in range(0,repeat):
np.random.shuffle(a1_copy) # shuffle bits in array and recalculate 1000 times
metric_1 = self.function_1(a1= a1_copy, a2 = a2)
list_metric1.append(metric_1)
list_metric1= np.array(list_metric1)
significance_val = len(np.where(list_metric1>= [original_metric1])[0])/repeat
return significance_val 发布于 2022-01-07 11:05:16
对于代码的第一部分,查找公共索引的方法并不有效,而是使用布尔操作:
# setup
np.random.seed(0)
a1 = np.random.choice([0,1], 1000000)
a2 = np.random.choice([0,1], 1000000)
# your option
event_index1, = np.where(a1 == 0)
event_index2, = np.where(a2 == 0)
n_matches, = np.intersect1d(event_index1, event_index2, assume_unique=True,).shape
n_matches
# output: 250947
# 74.8 ms ± 2.99 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# boolean operations
n_matches = ((a1==0)&(a2==0)).sum()
# output: 250947
# 1.98 ms ± 23.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)发布于 2022-01-07 16:02:23
我不认为你需要做索引比较。数组值与零的直接匹配应该提供更快的结果:
def function_1(a1,a2):
z1 = a1.size - np.sum(a1) # number of zeros in a1
z2 = a2.size - np.sum(a2) # number of zeros in a2
cs = min(a1.size,a2.size) # common size
return np.sum((a1[:cs]|a2[:cs])==0)/math.sqrt(z1*z2) # measure请注意,这假设a1和a2可以大小不同,每次都有不同数量的零。调用函数(function_iterations)不会产生这些条件。在这种情况下,a1一个a2从一个迭代到下一个迭代总是相同的大小,并且有相同数量的零。这意味着可以简化计算,只计算分母一次,并将其作为参数提供(或者将除法与计数匹配分开执行)。
function1_iterations()函数中很少有并行性,所以大部分时间都是在这里度过的。
为了从并行计算中获益,您需要高效地构建一个经过洗牌的位的矩阵,并使用numpy操作(而不是一个包含数千次迭代的Python循环)作为一个整体来处理它们。
下面是一个示例,说明如何生成具有更好并行性的新度量列表:
def computeMetrics(a1,a2,repeat = 1000):
z1 = a1.size - np.sum(a1) # number of zeros in a1
z2 = a2.size - np.sum(a2) # number of zeros in a2
cs = min(a1.size,a2.size) # common size
# shuffle matrix of a1 copies
a1s = np.repeat(a1[None,:],repeat,axis=0)
a1s = np.apply_along_axis(np.random.choice,1,a1s,a1.size,replace=False)
# compute metric for each shuffled row (with parallelism)
return np.sum((a1s[:,:cs]|a2[:cs])==0,axis=1)/math.sqrt(z1*z2)输出:
a1 = np.array([0,1,1,0,1,0,1])
a2 = np.array([1,1,0,0,1,1,0])
print(computeMetrics(a1,a2,10))
[0.33333333 0.66666667 0.33333333 0.33333333 0.33333333 0.66666667
0. 0.66666667 0.33333333 0.33333333]
a1 = np.array([0,1,1,0,1,0,1,0,0,1,1,0,0])
a2 = np.array([1,1,0,0,1,1,0])
print(computeMetrics(a1,a2,10))
[0.21821789 0.21821789 0.21821789 0.43643578 0.43643578 0.43643578
0.65465367 0.21821789 0.21821789 0.21821789]对实际数据使用100 m的重复可能需要太多内存,但您可以将其分解为1M块,并将结果连接起来。
computeMetrics(a1,a2,1000) takes 0.044 sec on my laptop
computeMetrics(a1,a2,1_000_000) takes 48 secondshttps://stackoverflow.com/questions/70620035
复制相似问题