首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >对numpy数组执行操作的最快方法

对numpy数组执行操作的最快方法
EN

Stack Overflow用户
提问于 2022-01-07 10:45:21
回答 2查看 453关注 0票数 -1

我的代码有以下目标:

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获得一些帮助的最快的代码:

代码语言:javascript
复制
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 
EN

回答 2

Stack Overflow用户

发布于 2022-01-07 11:05:16

对于代码的第一部分,查找公共索引的方法并不有效,而是使用布尔操作:

代码语言:javascript
复制
# 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)
票数 2
EN

Stack Overflow用户

发布于 2022-01-07 16:02:23

我不认为你需要做索引比较。数组值与零的直接匹配应该提供更快的结果:

代码语言:javascript
复制
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循环)作为一个整体来处理它们。

下面是一个示例,说明如何生成具有更好并行性的新度量列表:

代码语言:javascript
复制
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)

输出:

代码语言:javascript
复制
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块,并将结果连接起来。

代码语言:javascript
复制
computeMetrics(a1,a2,1000)      takes 0.044 sec on my laptop
computeMetrics(a1,a2,1_000_000) takes 48 seconds
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70620035

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档