Python 使用嵌套for循环提高代码段的性能

Python 使用嵌套for循环提高代码段的性能,python,performance,numpy,for-loop,Python,Performance,Numpy,For Loop,我必须连续运行下面所示的代码段大约200000次,该代码段需要大约0.12585秒才能进行1000次迭代。数据点的形状为32704,64 输出=[] 最大值=0 对于数据点中的数据点: tmp=[] 对于数据点中的数据: 最大值=最大数据 如果最大值==0: 附加数据 其他: tmp.appenddata/maxium output.appendtmp 我曾尝试使用map重写它,但这给了我每次迭代平均0.237秒的时间。这可能是由于多个maxy和list调用造成的 np.asarraylistm

我必须连续运行下面所示的代码段大约200000次,该代码段需要大约0.12585秒才能进行1000次迭代。数据点的形状为32704,64

输出=[] 最大值=0 对于数据点中的数据点: tmp=[] 对于数据点中的数据: 最大值=最大数据 如果最大值==0: 附加数据 其他: tmp.appenddata/maxium output.appendtmp 我曾尝试使用map重写它,但这给了我每次迭代平均0.237秒的时间。这可能是由于多个maxy和list调用造成的

np.asarraylistmaplambda数据点:listmaplambda数据:如果maxdata>0,则为data/maxdata,否则为y,数据点,数据点
是否有可能再次优化代码以提高性能?

尝试以下方法:

maximum = datapoints.max(axis=2, keepdims=True)
output = np.where(maximum==0, datapoints, datapoints/maximum)
您将在true_divide中看到一个警告“遇到无效值”,但它应该按预期工作

更新@Arthurtaca指出:

output = datapoints/np.where(maximum==0, 1, maximum)

将消除警告。

尝试以下操作:

maximum = datapoints.max(axis=2, keepdims=True)
output = np.where(maximum==0, datapoints, datapoints/maximum)
您将在true_divide中看到一个警告“遇到无效值”,但它应该按预期工作

更新@Arthurtaca指出:

output = datapoints/np.where(maximum==0, 1, maximum)

将消除警告。

是的,您肯定可以通过矢量化numpy操作来加速此操作。如果我理解您的正确做法,我会这样做:

将numpy作为np导入 我在这里使用一个随机初始化的数组,用您的输入替换它 arr=np.random.randomsize=32704,64 查找第三维的最大值,返回带有形状32704的数组 max_arr=np.maxarr,轴=2 设置除数,返回带有形状32704的数组 除数=np。其中max\u arr==0,1,max\u arr 使用expand_dims添加第三维,返回带有形状3、2704、1的数组 除数=np。展开除数,轴=2 执行除法,形状为32704,64 ans=np.dividearr,除数 从您的代码中,我推断您打算按第三轴的最大值缩放数据,但如果为0,则放弃缩放。您似乎还希望输出与输入具有相同的形状,这解释了您构建输出和tmp的方式。这就是为什么我将代码片段保留在numpy数组中,以w/输出结束,但如果您需要它的原始形式,则可以通过一个简单的循环来重新排列数据:

输出=[] 对于ans中的i: tmp=[] 对于i中的j: tmp.j output.appendtmp
为便于将来参考,请提供更详细的问题。这将使人们更容易参与,并且您将增加快速回答问题的机会

是的,通过矢量化numpy操作,您肯定可以加快速度。如果我理解您的正确做法,我会这样做:

将numpy作为np导入 我在这里使用一个随机初始化的数组,用您的输入替换它 arr=np.random.randomsize=32704,64 查找第三维的最大值,返回带有形状32704的数组 max_arr=np.maxarr,轴=2 设置除数,返回带有形状32704的数组 除数=np。其中max\u arr==0,1,max\u arr 使用expand_dims添加第三维,返回带有形状3、2704、1的数组 除数=np。展开除数,轴=2 执行除法,形状为32704,64 ans=np.dividearr,除数 从您的代码中,我推断您打算按第三轴的最大值缩放数据,但如果为0,则放弃缩放。您似乎还希望输出与输入具有相同的形状,这解释了您构建输出和tmp的方式。这就是为什么我将代码片段保留在numpy数组中,以w/输出结束,但如果您需要它的原始形式,则可以通过一个简单的循环来重新排列数据:

输出=[] 对于ans中的i: tmp=[] 对于i中的j: tmp.j output.appendtmp
为便于将来参考,请提供更详细的问题。这将使人们更容易参与,并且您将增加快速回答问题的机会

下面是一个简短的答案:

def bar(datapoints):
    m = np.amax(datapoints, axis=2)
    m[m == 0] = 1
    return datapoints / m[:,:,np.newaxis]
这是你如何到达那里的解释我是如何到达那里的!:

让我们从一些示例数据开始:

>>> x = np.array([[[1, 2, 3, 4], [11, -12, 13, -14]], [[26, 27, 28, 29], [0, 0, 0, 0]]])
现在检查您在原始函数中得到了什么:

def foo(datapoints):
    output = []
    maxium = 0
    for datapoint in datapoints:
        tmp = []
        for data in datapoint:
            maxium = max(data)
            if maxium == 0:
                tmp.append(data)
            else:
                tmp.append(data / maxium)
        output.append(tmp)
    return numpy.array(output)
结果是:

>>> foo(x)
array([[[ 0.25      ,  0.5       ,  0.75      ,  1.        ],
        [ 0.84615385, -0.92307692,  1.        , -1.07692308]],

       [[ 0.89655172,  0.93103448,  0.96551724,  1.        ],
        [ 0.        ,  0.        ,  0.        ,  0.        ]]])
现在,让我们试用amax:

>>> np.amax(x, axis=0)
array([[26, 27, 28, 29],
       [11,  0, 13,  0]])
>>> np.amax(x, axis=2)
array([[ 4, 13],
       [29,  0]])
啊哈,看起来轴=2就是我们要找的。现在我们想用这个除以原始数组,但只在max不为零的地方。如何只在某些地方进行划分?答案是:我们在任何地方都除以,但在某些地方我们除以1,所以它没有效果。让我们用1代替0:

>>> m = np.amax(x, axis=2)
>>> m[m == 0] = 1
>>> m
array([[ 4, 13],
       [29,  1]])
最后,让我们除以这个,回到轴2,我们之前取最大值:

>>> x / m[:,:,np.newaxis]
array([[[ 0.25      ,  0.5       ,  0.75      ,  1.        ],
        [ 0.84615385, -0.92307692,  1.        , -1.07692308]],

       [[ 0.89655172,  0.93103448,  0.96551724,  1.        ],
        [ 0.        ,  0.        ,  0.        ,  0.        ]]])

把这些放在一起,你会在顶部看到一个横条。

好吧,这里有一个简短的答案:

def bar(datapoints):
    m = np.amax(datapoints, axis=2)
    m[m == 0] = 1
    return datapoints / m[:,:,np.newaxis]
这是你如何到达那里的解释我是如何到达那里的!:

让我们从一些示例数据开始:

>>> x = np.array([[[1, 2, 3, 4], [11, -12, 13, -14]], [[26, 27, 28, 29], [0, 0, 0, 0]]])
N 现在,请检查您在原始函数中获得的内容:

def foo(datapoints):
    output = []
    maxium = 0
    for datapoint in datapoints:
        tmp = []
        for data in datapoint:
            maxium = max(data)
            if maxium == 0:
                tmp.append(data)
            else:
                tmp.append(data / maxium)
        output.append(tmp)
    return numpy.array(output)
结果是:

>>> foo(x)
array([[[ 0.25      ,  0.5       ,  0.75      ,  1.        ],
        [ 0.84615385, -0.92307692,  1.        , -1.07692308]],

       [[ 0.89655172,  0.93103448,  0.96551724,  1.        ],
        [ 0.        ,  0.        ,  0.        ,  0.        ]]])
现在,让我们试用amax:

>>> np.amax(x, axis=0)
array([[26, 27, 28, 29],
       [11,  0, 13,  0]])
>>> np.amax(x, axis=2)
array([[ 4, 13],
       [29,  0]])
啊哈,看起来轴=2就是我们要找的。现在我们想用这个除以原始数组,但只在max不为零的地方。如何只在某些地方进行划分?答案是:我们在任何地方都除以,但在某些地方我们除以1,所以它没有效果。让我们用1代替0:

>>> m = np.amax(x, axis=2)
>>> m[m == 0] = 1
>>> m
array([[ 4, 13],
       [29,  1]])
最后,让我们除以这个,回到轴2,我们之前取最大值:

>>> x / m[:,:,np.newaxis]
array([[[ 0.25      ,  0.5       ,  0.75      ,  1.        ],
        [ 0.84615385, -0.92307692,  1.        , -1.07692308]],

       [[ 0.89655172,  0.93103448,  0.96551724,  1.        ],
        [ 0.        ,  0.        ,  0.        ,  0.        ]]])

把这些加在一起,你会在顶部看到一个横条。

很抱歉,我删除了我的评论,所以你的评论现在没有多大意义!在我摆好姿势后,我注意到你使用了np.asarray。我添加了numpy标记,因为解决方案肯定会涉及numpy的矢量化操作,而不是Python for loops或map。我希望解决方案会涉及函数。抱歉,我删除了我的注释,因此您的注释现在没有多大意义!在我摆好姿势后,我注意到你使用了np.asarray。我添加了numpy标记,因为解决方案肯定会涉及numpy的矢量化操作,而不是Python for loops或map。我希望解决方案会涉及函数。我认为最后一部分您可以使用ans.ToList我认为最后一部分您可以使用ans.ToList似乎您还可以将第二行更改为datapoints/np.wheremaximum==0,1,maximum以避免错误。似乎您最好将第二行更改为datapoints/np.wheremaximum==0,1,maximum以避免错误。