【问题标题】:How to get the highest element in absolute value in a numpy matrix?如何获得numpy矩阵中绝对值的最高元素?
【发布时间】:2021-10-08 06:44:01
【问题描述】:

这是我目前正在做的,它可以工作,但有点麻烦:

x = np.matrix([[1, 1], [2, -3]])
xmax = x.flat[abs(x).argmax()]

【问题讨论】:

  • 对我来说看起来很优雅...?是平缓还是什么?因为老实说,这看起来真的很不错。

标签: python numpy


【解决方案1】:

您要查找的值必须是 x.max()x.min(),以便您可以这样做

max(x.min(), x.max(), key=abs)

这类似于 aestrivex 的解决方案,但可能更具可读性?请注意,这将在x.min()x.max() 具有相同绝对值的情况下返回最小值,例如-55。如果您有偏好,只需相应地将输入订购到max

【讨论】:

    【解决方案2】:

    最紧凑的方式可能是:

    x_max = np.abs(x).max()  
    

    默认情况下,.max() 方法直接对展平数组进行操作(取自NumPy documentation)。所以该运算寻找n维数组np.abs(x)的最大绝对值。


    执行时间

    此外,它比问题的解决方案快 2000 倍以上。考虑到在 Дмитрий Пасько 的示例中应用的 IPython %time 魔术函数,我得到(在带有 Python 3.8 和 NumPy 1.19.1 的 MacBook Pro 2015 上):

    x = np.random.rand(50000, 500) - 0.5
    
    # numpy solution
    x_max = np.abs(x).max()
    "Wall time: 67.7 µs"
    
    # question's solution
    %time xmax = x[abs(x).argmax()]
    "Wall time: 157 ms"
    
    # Daniel's solution
    %time xmax=x[np.unravel_index(abs(x).argmax(), x.shape)] 
    "Wall time: 88.9 µs"
    
    # Дмитрий Пасько's solution
    %time newdt = np.array([dt.min(),dt.max()])
      ... xmax = newdt.flat[abs(newdt).argmax()]
    "Wall time: 26.7 ms"
    

    【讨论】:

      【解决方案3】:

      我正在寻找一种方法来获取沿指定轴的 N 维数组的最大绝对值的有符号值,这些答案都没有处理。所以,我整理了一个函数来完成它。没有承诺,但据我测试它是有效的:

      def maxabs(a, axis=None):
          """Return slice of a, keeping only those values that are furthest away
          from 0 along axis"""
          maxa = a.max(axis=axis)
          mina = a.min(axis=axis)
          p = abs(maxa) > abs(mina) # bool, or indices where +ve values win
          n = abs(mina) > abs(maxa) # bool, or indices where -ve values win
          if axis == None:
              if p: return maxa
              else: return mina
          shape = list(a.shape)
          shape.pop(axis)
          out = np.zeros(shape, dtype=a.dtype)
          out[p] = maxa[p]
          out[n] = mina[n]
          return out
      

      【讨论】:

      • 好答案!我会将 p = abs(maxa) > abs(mina) 更改为 p = abs(maxa) >= abs(mina)
      【解决方案4】:

      这可以快速计算绝对最大值 - 以与 np.maxnp.argmax 本身相同的方式尊重任意 axis 参数。

      def absmaxND(a, axis=None):
          amax = a.max(axis)
          amin = a.min(axis)
          return np.where(-amin > amax, amin, amax)
      

      对于长数组,它比 a.flat[abs(a).argmax()] 快大约 2.5 倍,即使对于简单的情况 axis=None,因为它不会渲染原始大数组的 abs()。

      【讨论】:

        【解决方案5】:

        编辑:对不起,我的回答跑题了。正如 Ophion 指出的那样,这将返回索引,而不是值 - 您必须将 flat 与我的“xmax”(实际上是“xmaxInd”)一起使用才能获得正确的值。因此,我认为您的解决方案是最好的。


        经过一番试验,我意识到你可以这样做:

        x = np.matrix([[1,1], [2,-3]])
        absX = abs(x)
        xmax = argmax(absX)
        

        似乎 numpy 允许您获取矩阵的absargmax。多么方便!

        timeit 检查:

        def meth1():
            x = np.matrix([[1,1],[2,-3]])
            xmax = x.flat[abs(x).argmax()]
        
        def meth2():
            x = np.matrix([[1,1],[2,-3]])
            xmax = argmax(abs(x))
        
        t1 = timeit.Timer("meth1()","from __main__ import meth1")
        t2 = timeit.Timer("meth2()","from __main__ import meth2")
        

        mean(t1.repeat(1,100000))Out[99]: 7.854323148727417 mean(t2.repeat(1,100000))Out[98]: 7.7788529396057129

        所以meth2() 稍微快一点。可能是因为它不涉及调用flat

        【讨论】:

        • 这返回 3,而不是 -3,这不是问题所要问的。
        • @Ophion 说得好,我对索引感到困惑。我认为你必须使用flat
        【解决方案6】:

        我唯一能想到的,看起来更糟糕的是:

        xmax=x[np.unravel_index(abs(x).argmax(), x.shape)]
        

        【讨论】:

          【解决方案7】:

          我用过

          dt = np.random.rand(50000,500)-0.5
          # ur
          xmax = dt.flat[abs(dt).argmax()] #230 ms
          
          # new
          newdt = np.array([dt.min(),dt.max()]) # 56ms
          xmax = newdt.flat[abs(newdt).argmax()] # 4ms
          

          几乎快 4 倍(60 毫秒对 230 毫秒)!!

          【讨论】:

            【解决方案8】:

            请原谅死灵,但我似乎无法评论 JoeCondron 的回答。

            我喜欢:

            max(x.min(), x.max(), key=abs) 
            

            但我相信它可以进一步简化:

            max(x, key=abs)
            

            似乎对我有用(或非一维):

            max(x.flat, key=abs)
            

            【讨论】:

              【解决方案9】:

              我认为这是一种非常简单的方法,如果代码可读性是您最关心的问题,它可能会稍微好一些。但实际上,您的方式同样优雅。

              np.min(x) if np.max(abs(x)) == abs(np.min(x)) else np.max(x)
              

              【讨论】:

                猜你喜欢
                • 2017-02-23
                • 1970-01-01
                • 2018-10-20
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多