我有一个对象,我将一个大规模的for循环方法转换为一系列矢量化的numpy数组(大约快50倍)。现在我试图添加一个新方法,我需要处理一个numpy矩阵,然后根据矩阵内的数组索引“移位”子数组内容(即插入值)。我知道我可以通过for循环实现这一点,但我试图通过使用矢量数学来实现加速增益。
我想知道是否有快速有效的方法来完成以下任务:
import numpy as np
period = [1, 2, 3]
x = [1, 10, 100]
y = [.2, .4, .6]
z = np.outer(x,y)
print(z)
结果:
[[ 0.2 0.4 0.6]
[ 2. 4. 6. ]
[ 20. 40. 60. ]]
我想在z中移动行,将基于句点的零数添加为z中的行索引,基本上如下:
[[ 0.0 0.2 0.4 0.6 ]
[ 0.0 0.0 2.0 4.0 6.0 ]
[ 0.0 0.0 0.0 20.0 40.0 60.0 ]]
最终,我想要对垂直/列轴(轴= 1)求和。我需要一个如下的最终数组:
[ 0.0 0.2 2.4 24.6 46.0 60.0]
答案 0 :(得分:2)
frames=[]
files = [...some list of files..]
for img_file in files:
frame = cv2.imread(img_file, 1)
frames.append[frame]
# and then later
for frame in frames:
cv2.imshow('frame', frame)
# or by individual frame
cv2.imshow('frame', frames[123])
是一个参差不齐的清单。我们可以使用viectorized数组魔术来构建它,至少不是普通的东西。
要解决这个问题,我们需要展平或填充此结构
[[ 0.0 0.2 0.4 0.6 ]
[ 0.0 0.0 2.0 4.0 6.0 ]
[ 0.0 0.0 0.0 20.0 40.0 60.0 ]]
或
[[ 0.0 0.2 0.4 0.6 0.0 0.0]
[ 0.0 0.0 2.0 4.0 6.0 0.0 ]
[ 0.0 0.0 0.0 20.0 40.0 60.0 ]]
[ 0.0 0.2 0.4 0.6 0.0 0.0 2.0 4.0 6.0 0.0 0.0 0.0 20.0 40.0 60.0 ]
让我们对平面数组的块进行求和,但是你需要一个跳过总和。我想我可以探索扁平转置。
我的第一个想法是,填充的数组看起来像对角线的,[。2,2,2,20]在对角线上,[.4,4,40]在下一个偏移处,等等。我知道sum.reduceat
可以根据矩阵和偏移量构建矩阵,但我不认为sparse
中存在这样的函数。它们一次只能处理一个偏移量。
但它看起来也像numpy
可以产生的那种偏移。
让我们探讨一下:
stride_tricks
这是我们想要的那种转变,但方向是错误的;所以让我们翻转In [458]: as_strided =np.lib.index_tricks.as_strided
In [459]: Z=np.pad(z,[[0,0],[3,3]],mode='constant')
In [460]: Z
Out[460]:
array([[ 0. , 0. , 0. , 0.2, 0.4, 0.6, 0. , 0. , 0. ],
[ 0. , 0. , 0. , 2. , 4. , 6. , 0. , 0. , 0. ],
[ 0. , 0. , 0. , 20. , 40. , 60. , 0. , 0. , 0. ]])
In [461]: Z.strides
Out[461]: (72, 8) # prod an offset with (72+8, 8)
In [462]: as_strided(Z,shape=(3,6),strides=(80,8))
Out[462]:
array([[ 0. , 0. , 0. , 0.2, 0.4, 0.6],
[ 0. , 0. , 2. , 4. , 6. , 0. ],
[ 0. , 20. , 40. , 60. , 0. , 0. ]])
:
Z
泛化可以留给读者。
是否有任何速度优势未知。可能不适用于这个小案例,对于非常大的案例可能是肯定的。
这会清理填充并稍微向前移动
In [463]: Z1=Z[::-1,:].copy()
In [464]: as_strided(Z1,shape=(3,6),strides=(80,8))
Out[464]:
array([[ 0. , 0. , 0. , 20. , 40. , 60. ],
[ 0. , 0. , 2. , 4. , 6. , 0. ],
[ 0. , 0.2, 0.4, 0.6, 0. , 0. ]])
In [465]: as_strided(Z1,shape=(3,6),strides=(80,8)).sum(0)
Out[465]: array([ 0. , 0.2, 2.4, 24.6, 46. , 60. ])
这忽略了In [497]: Z=np.pad(z,[[0,0],[1,4]],mode='constant')
In [498]: Z.strides
Out[498]: (64, 8)
In [499]: as_strided(Z,shape=(3,6),strides=(64-8,8))
Out[499]:
array([[ 0. , 0.2, 0.4, 0.6, 0. , 0. ],
[ 0. , 0. , 2. , 4. , 6. , 0. ],
[ 0. , 0. , 0. , 20. , 40. , 60. ]])
的构建方式。如果外部产品是问题的核心,我可以尝试跨越1d z
,并使用y
来执行加权总和。
x
在此构造中,In [553]: x=np.array([1,10,100]); y=np.array([.2,.4,.6])
In [554]: z=np.concatenate(([0,0],y[::-1],[0,0,0]))
In [555]: z
Out[555]: array([ 0. , 0. , 0.6, 0.4, 0.2, 0. , 0. , 0. ])
In [556]: Z=as_strided(z,shape=(3,6), strides=(8,8))
In [557]: Z
Out[557]:
array([[ 0. , 0. , 0.6, 0.4, 0.2, 0. ],
[ 0. , 0.6, 0.4, 0.2, 0. , 0. ],
[ 0.6, 0.4, 0.2, 0. , 0. , 0. ]])
In [558]: np.dot(x,Z)
Out[558]: array([ 60. , 46. , 24.6, 2.4, 0.2, 0. ])
是Z
上的视图,因此小于之前的z
。但我确信Z
在将其发送到已编译的代码时会复制。 dot
可能会避免这种情况,在不扩展视图的情况下对视图进行编译迭代。处理非常大的数组时,这可能会有所不同。
结果相反,但很容易修复。我甚至可以在施工期间修理它。
答案 1 :(得分:1)
循环第一维可行:
a = np.array(
[[0.2 , 0.4 , 0.6],
[2., 4., 6. ],
[20., 40., 60. ]])
s0, s1 = a.shape
res = np.zeros((s0, s0 + s1))
for i in range(s1):
res[i, i + 1: i + s0 + 1] = a[i]
>>> np.sum(res,axis=0)
array([ 0. , 0.2, 2.4, 24.6, 46. , 60. ])
答案 2 :(得分:1)
您还可以先计算指数并立即指定:
a = np.array(
[[0.2 , 0.4 , 0.6],
[2., 4., 6. ],
[20., 40., 60. ]])
s0, s1 = a.shape
rows = np.repeat(np.arange(s0), s1).reshape(a.shape)
cols = (np.add.outer(np.arange(0, s0), np.arange(s1)) + 1)
res = np.zeros((s0, s0 + s1))
res[rows, cols] = a
np.sum(res,axis=0)
>>> np.sum(res,axis=0)
array([ 0. , 0.2, 2.4, 24.6, 46. , 60. ])