gpt4 book ai didi

python - 使用 itertools.combinations 的最快方法

转载 作者:太空宇宙 更新时间:2023-11-03 14:25:48 25 4
gpt4 key购买 nike

我需要加速以下功能:

import numpy as np
import itertools
import timeit

def combcol(myarr):
ndims = myarr.shape[0]
solutions = []
for idx1, idx2, idx3, idx4, idx5, idx6 in itertools.combinations(np.arange(ndims), 6):
c1, c2, c3, c4, c5, c6 = myarr[idx1,1], myarr[idx2,2], myarr[idx3,1], myarr[idx4,2], myarr[idx5,1], myarr[idx6,2]
if c1-c2>0 and c2-c3<0 and c3-c4>0 and c4-c5<0 and c5-c6>0 :
solutions.append(((idx1, idx2, idx3, idx4, idx5, idx6),(c1, c2, c3, c4, c5, c6)))
return solutions

X = np.random.random((20, 10))
Y = np.random.random((40, 10))


if __name__=='__main__':
from timeit import Timer
t = Timer(lambda : combcol(X))
t1 = Timer(lambda : combcol(Y))
print('t : ',t.timeit(number=1),'t1 : ',t1.timeit(number=1))

结果:

t :  0.6165180211451455 t1 :  64.49216925614847 

算法对于我的标准使用来说太慢了 (myarr.shape[0] = 500)。有没有 NumPy 方法可以减少此函数的执行时间(不会浪费太多内存)?
是否可以在 Cython 中实现该问题?

我试过使用 cProfile 来查看哪些部分运行缓慢。这里的大部分时间都花在调用 combcol() 上。

import profile
........
........
profile.run('print(len(combcol(Y))); print')

144547
144559 function calls in 39.672 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
144547 0.641 0.000 0.641 0.000 :0(append)
1 0.000 0.000 0.000 0.000 :0(arange)
2 0.000 0.000 0.000 0.000 :0(charmap_encode)
1 0.000 0.000 39.672 39.672 :0(exec)
1 0.000 0.000 0.000 0.000 :0(len)
1 0.000 0.000 0.000 0.000 :0(print)
1 0.000 0.000 0.000 0.000 :0(setprofile)
1 0.094 0.094 39.672 39.672 <string>:1(<module>)
2 0.000 0.000 0.000 0.000 cp850.py:18(encode)
1 38.938 38.938 39.578 39.578 essaiNumpy4.py:13(combcol)
1 0.000 0.000 39.672 39.672 profile:0(print(len(combcol(Y))); print)
0 0.000 0.000 profile:0(profiler)

最后我修改了如下代码:

def combcol2(myarr):
ndims = myarr.shape[0]
myarr1 = myarr[:,1].tolist()
myarr2 = myarr[:,2].tolist()
solutions = []
for idx1, idx2, idx3, idx4, idx5, idx6 in itertools.combinations(range(ndims), 6):
if myarr1[idx1] > myarr2[idx2] < myarr1[idx3] > myarr2[idx4] < myarr1[idx5] > myarr2[idx6]:
solutions.append(((idx1, idx2, idx3, idx4, idx5, idx6),(myarr1[idx1], myarr2[idx2], myarr1[idx3], myarr2[idx4], myarr1[idx5], myarr2[idx6])))
return solutions

X = np.random.random((40, 10))

if __name__=='__main__':
from timeit import Timer
t = Timer(lambda : combcol2(X))
print('t : ',t.timeit(number=1))

结果:

t :  4.341582240200919

最佳答案

alko 列出了对您的程序有用的检修,Tim Peters 指出 500-choose-6 超过 21 万亿(即 21057686727000)。这个答案将指出对您的原始程序的简单加速。 (我认为与 alko 的方法可能提供的相比,这是一个小的加速,但以下内容对于 future 的 python 编程值得注意。)

你的选择声明是
if c1-c2>0 and c2-c3<0 and c3-c4>0 and c4-c5<0 and c5-c6>0 :
相当于
if c1>c2 and c2<c3 and c3>c4 and c4<c5 and c5>c6 :
但在 python 解释器中,前者比后者花费 67% 的时间。例如,在我的运行 Python 2.7.5+ 的 Intel i3-2120 机器(显然比你的机器快几倍)上,这是这两种情况的一些示例输出:
('t : ', 0.12977099418640137, 't1 : ', 14.45378589630127)
('t : ', 0.0887291431427002, 't1 : ', 8.54729700088501)
4 次此类运行的平均值比率为 14.529/8.709 = 1.668。

关于python - 使用 itertools.combinations 的最快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20829326/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com