在numpy中创建倾斜/连续移动矩阵的最快方法
我需要创建一个(w,N)-矩阵,如下所示:在numpy中创建倾斜/连续移动矩阵的最快方法,numpy,optimization,python-3.6,Numpy,Optimization,Python 3.6,我需要创建一个(w,N)-矩阵,如下所示: w//2............N-1,N-1 . \ N-1 . \ N-1 . \ N-1 1...............N-1,N-1 0...................N-1 00..................N-2 . \ N-3 . \ . . \
w//2............N-1,N-1
. \ N-1
. \ N-1
. \ N-1
1...............N-1,N-1
0...................N-1
00..................N-2
. \ N-3
. \ .
. \ .
000000..............N-w//2
这是一个(w,N)矩阵,有一个奇数w。中行是从0到N的范围。对于中行上方的每一行索引,该行将按相同的方法向左移动,对于中行下方的每一行,该行将按相同的方法向右移动
N通常在10^4左右,w通常在10到10^2之间
我想出了两种方法:
from scipy.ndimage import shift
middle = np.arange(0, N)
final = np.vstack(
[shift(middle, i, mode='nearest') for i in range(-w//2, 0)] +
[middle] +
[shift(middle, i, mode='nearest') for i in range(1, w//2)] )
这需要0.035
秒才能运行
np.vstack([
np.maximum(
0,
np.minimum(
N-1,
np.arange(-step, N-step)
)
)
for step in range(-w//2, w//2)
])
这需要0.021
秒才能运行
np.vstack([
np.maximum(
0,
np.minimum(
N-1,
np.arange(-step, N-step)
)
)
for step in range(-w//2, w//2)
])
这些数字分别为N=10^3和w=21
我真的很想把这些数字降到尽可能低的水平,最好降到1ms左右
我尝试了多处理,但这并没有真正起到作用,开销太大,无法从并发中获得一些东西。我也知道我可以把这个结果存储在某个地方,但是这需要这个函数的调用者进行重大的更改,所以这将在以后完成
是否有任何数学关系可以表示这样的倾斜/移位操作?我想不出一个,但如果有,numpy可能会利用这个优势击败我的成绩
那么,是的,有什么办法让我的代码更快吗?用适当的形状和水平值从
0
到N
(包括)初始化一个数组
w,N=11,10
arr=np.empty(shape=[w,N],dtype=int)
arr[:]=np.arange(N)
啊
>>> [[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]]
从每行中减去一个适当的值
arr += np.arange(w).reshape([-1, 1])[::-1] - (1+w//2)
arr
>>> [[ 5., 6., 7., 8., 9., 10., 11., 12., 13., 14.],
[ 4., 5., 6., 7., 8., 9., 10., 11., 12., 13.],
[ 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.],
[ 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.],
[ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10.],
[ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[-1., 0., 1., 2., 3., 4., 5., 6., 7., 8.],
[-2., -1., 0., 1., 2., 3., 4., 5., 6., 7.],
[-3., -2., -1., 0., 1., 2., 3., 4., 5., 6.],
[-4., -3., -2., -1., 0., 1., 2., 3., 4., 5.],
[-5., -4., -3., -2., -1., 0., 1., 2., 3., 4.]]
如果值与限制值交叉,则重新为其指定限制值
arr[arr<0] = 0
arr[arr>N-1] = N-1
arr
>>> [[5., 6., 7., 8., 9., 9., 9., 9., 9., 9.],
[4., 5., 6., 7., 8., 9., 9., 9., 9., 9.],
[3., 4., 5., 6., 7., 8., 9., 9., 9., 9.],
[2., 3., 4., 5., 6., 7., 8., 9., 9., 9.],
[1., 2., 3., 4., 5., 6., 7., 8., 9., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 0., 1., 2., 3., 4., 5., 6., 7., 8.],
[0., 0., 0., 1., 2., 3., 4., 5., 6., 7.],
[0., 0., 0., 0., 1., 2., 3., 4., 5., 6.],
[0., 0., 0., 0., 0., 1., 2., 3., 4., 5.],
[0., 0., 0., 0., 0., 0., 1., 2., 3., 4.]]
arr[arrN-1]=N-1
啊
>>> [[5., 6., 7., 8., 9., 9., 9., 9., 9., 9.],
[4., 5., 6., 7., 8., 9., 9., 9., 9., 9.],
[3., 4., 5., 6., 7., 8., 9., 9., 9., 9.],
[2., 3., 4., 5., 6., 7., 8., 9., 9., 9.],
[1., 2., 3., 4., 5., 6., 7., 8., 9., 9.],
[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.],
[0., 0., 1., 2., 3., 4., 5., 6., 7., 8.],
[0., 0., 0., 1., 2., 3., 4., 5., 6., 7.],
[0., 0., 0., 0., 1., 2., 3., 4., 5., 6.],
[0., 0., 0., 0., 0., 1., 2., 3., 4., 5.],
[0., 0., 0., 0., 0., 0., 1., 2., 3., 4.]]
编辑
我试着给脚本计时
import timeit
script = '''
w, N = 21, 10**3
arr = np.empty(shape= [w, N], dtype= int)
arr[:] = np.arange(N)
arr += np.arange(w).reshape([-1, 1])[::-1] - (1+w//2)
arr[arr<0] = 0
arr[arr>N-1] = N-1
'''
time = timeit.timeit(script, number= 100000, setup= 'import numpy as np') / 100000
time
>>> 0.00019059010320999733 # 0.19 ms
import timeit
脚本=“”
w、 N=21,10**3
arr=np.empty(shape=[w,N],dtype=int)
arr[:]=np.arange(N)
arr+=np.arange(w).重塑([-1,1])[::-1]-(1+w//2)
arr[arrN-1]=N-1
'''
time=timeit.timeit(脚本,编号=100000,安装程序='importnumpyasnp')/100000
时间
>>>0.0001905901032099733#0.19毫秒
一个非常好的方法。我希望它比实际移动数组更快。@TlsChris我已经对脚本进行了基准测试。另外,如果我的回答有帮助,请点击“向上投票”按钮旁边的“勾号”接受我的回答。我已经向上投票了,但无法接受,因为我没有问这个问题。您的方法很容易理解和维护。@TlsChris oops my bad:py您的解决方案速度稍慢,平均0.022
秒,但我确实同意,它看起来很适合维护。