【问题标题】:Is it possible to avoid this loop using numpy?是否可以使用 numpy 避免此循环?
【发布时间】:2020-09-16 01:36:24
【问题描述】:

假设你有两个 numpy 矩阵:

import numpy as np

n = 800
m = 16
A = np.zeros((n, 4)) #np.random.rand(n,4) if you wish
B = np.zeros(m)      #np.random.rand(m) if you wish

在我的代码中,我需要将 B 中找到的每个值减去 A 的所有值,然后计算该平方并获得为我提供该新矩阵最小值的索引。因此,我将有 m 个最小值。从这些中,我需要最低限度。为此,我现在使用这样的循环:

min_C = np.zeros(m)

for j in range(m):
    C = A[:,2]-B[j]
    C = C*C
    min_C[j] = np.where(C == np.amin(C))[0][0]

所以我对每个 j 都有一个最小值。然后,我做 min_C 的最小值。我可以避免这个循环以获得绝对最小值吗?如果可能的话,我现在无法想象如何编码。这只是为了提高我的代码的效率,我需要它,因为这个计算是用不同的 A 和 B 完成了很多次,当然。

【问题讨论】:

    标签: python performance numpy loops


    【解决方案1】:

    利用broadcasting,您可以将其减少到以下结果min(m,n) 数组:

    ((A[:,2]-B[:,None])**2).min()
    

    【讨论】:

    • 哇!真的很有用! :) 我也可以获取索引吗?我的意思是,如果我这样做 G = (A[:,2]-B[:,None])**2) 我会得到一个大矩阵,其中每一行都是 C[j] (嗯,实际上,它就像 [ [ [第 1 行]] [[第 2 行]] ... ])。最好让每个 G[j] 在那个 j 中具有最小值
    • 是的,你有 argmin 给你最小值的索引。所以((A[:,2]-B[:,None])**2).argmin()。请注意,这两个有一个 axis 参数,用于查找 row-wise 或 col-wise 最小值或 argmins @learning
    【解决方案2】:

    我假设您的示例代码中出现的固定索引 2 将保持固定,这将问题简化为 A 是一维的情况。 如果我正确理解了这个问题并查看了您的样本输出,那么您正在寻找一个索引,而不是出现在 C 本身之一中的值,这样我们就可以用绝对值替换正方形。首先,我们通过@yatu 的广播提示创建 A[i,2] 和 B[j] 的所有组合的绝对值,然后计算沿第二个轴(大小为 n)的 argmin 的最小值

    c = np.abs(A[:,2]-B[:,None])
    answer = np.min(np.argmin(c, axis=1))
    

    我希望我得到你所要求的正确,如果要改变 A 的固定索引,请扩展广播:

    c = np.abs(A[:,:]-B[:,None,None])
    answer = np.min(np.argmin(c, axis=1))
    

    输出将是一个 int,这与您的示例代码不同。

    【讨论】:

    • 谢谢!但我已经有了@yatu 的解决方案。只有两件事:1)我实际上发现我正在寻找的轴是 2,而不是 1。2)你知道 np.abs 是否比 **2 快吗?
    • 当然,不用担心! 1) 好的,但是出于好奇,我是否正确地回答了您的问题。 2) 我没想到会这样,但是看起来像 **2 的简短检查实际上更快,谢谢!
    • 好的,谢谢!关于我说的轴,如果你输入 B = np.zeros(m) 它是 1 就像你说的那样,但是在我的测试文件中我有 B = np.zeros(m,1) 并且我不得不输入axis = 2 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多