将向量放在矩阵+变换中

时间:2018-11-06 09:35:30

标签: python python-3.x matrix

所以我有一个用Numpy创建的向量

V = [10 20 30 40  0  1]

我想要这样的矩阵M:

 [10.  0.  0.  0.  0.  0.]
 [20. 10.  0.  0.  0.  0.]
 [30. 20. 10.  0.  0.  0.]
 [40. 30. 20. 10.  0.  0.]
 [ 0. 40. 30. 20. 10.  0.]
 [ 1.  0. 40. 30. 20. 10.]
 [ 0.  1.  0. 40. 30. 20.]
 [ 0.  0.  1.  0. 40. 30.]
 [ 0.  0.  0.  1.  0. 40.]
 [ 0.  0.  0.  0.  1.  0.]
 [ 0.  0.  0.  0.  0.  1.]

为此,我将其用于循环和矢量提取,但由于我的矢量V有500列并且矩阵M有500*2 -1行和500列,所以它太长了。

此外,对于不同的向量V,我必须重复至少10万次

是否可以使用矩阵计算并避免循环来获得此结果? (尽快)

谢谢!

(我在Spyder上使用Python 3.6)

编辑:我的解决方案:

t = 480 n = 10000

t1 = time.time()
for p in range(n):
    for j in range(M.shape[1]):
        M[j:j+t,j] = np.transpose(V[:])
print(time.time()-t1)   

14秒仅10000次...太长了

编辑2:评论中解决方案的基准:

(这里Prate为V)

t1 = time.time()
for p in range(n):
    for j in range(M.shape[1]):
        M[j:j+t,j] = np.transpose(Prate[:])
print(time.time()-t1) 


t1 = time.time()
for p in range(n):
    n = len(Prate)
    m = np.tile(np.concatenate((np.array(Prate), np.zeros(t))), t)[:2*t*t-t]
    result = m.reshape(t, -1).T
print(time.time()-t1)  

t1 = time.time()
for p in range(n):
    ind = np.arange(t)
    indices = ((ind[:,None] + ind).ravel() , np.repeat(ind, t))
    base = np.zeros((n1, t))
    base[indices] = np.tile(Prate, t)
print(time.time()-t1) 

输出:

16.737313747406006
29.46031618118286 
3.6843104362487793

编辑3 :为了避免遍历两倍于所需大小的数组,我提出了不同的问题:

我有一个向量(1x6):

V = [1 20 5 0  0  9]

我想要这样的矩阵M(6x6):

 [1.  20.  5.  0.  0.  9.]
 [0.  1.  20.  5.  0.  0.]
 [0.  0.  1.  20.  5.  0.]
 [0.  0.  0.  1.  20.  5.]
 [0.  0.  0.  0.  1.  20.]
 [0.  0.  0.  0.   0.  1.]

每行都是相同的向量V(它的一部分),但有一个偏移量以获得三角形矩阵。

如何做到没有循环?

(这只是一个简单的示例,但实向量V更大)

谢谢:D

4 个答案:

答案 0 :(得分:0)

是的,对于数组v,我们首先可以用len(v)extra 0`s构建一个numpy数组:

n = len(V)
m = np.tile(np.concatenate((V, np.zeros(n))), n)[:2*n*n-n]
result = m.reshape(n, 1).T

对于给定的V列表,这给我们:

>>> np.tile(np.concatenate((V, np.zeros(n))), n)[:2*n*n-n].reshape(n,-1).T
array([[10.,  0.,  0.,  0.,  0.,  0.],
       [20., 10.,  0.,  0.,  0.,  0.],
       [30., 20., 10.,  0.,  0.,  0.],
       [40., 30., 20., 10.,  0.,  0.],
       [ 0., 40., 30., 20., 10.,  0.],
       [ 1.,  0., 40., 30., 20., 10.],
       [ 0.,  1.,  0., 40., 30., 20.],
       [ 0.,  0.,  1.,  0., 40., 30.],
       [ 0.,  0.,  0.,  1.,  0., 40.],
       [ 0.,  0.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  1.]])

对于包含500个元素并运行1万次的numpy数组,我们获得:

>>> timeit(f, number=10000)
5.285840999999891

因此,转换具有500个元素的单个数组在我的机器上需要0.5毫秒。因此,构造所有这些数组大约需要52.86秒。

编辑:我实现了以下三种尝试:

def wil():
    n = len(V)
    return np.tile(np.concatenate((V, np.zeros(n))), n)[:2*n*n-n].reshape(n,-1).T


def mii():
    n = len(V)
    M = np.zeros((2*n-1, n))
    for j in range(n):
        M[j:j+n,j] = np.transpose(V[:])
    return M


def kas():
    n = len(V)
    ind = np.arange(n)
    indices = ((ind[:,None] + ind).ravel() , np.repeat(ind, n))
    base = np.zeros((2*n-1, n))
    base[indices] = np.tile(V, n)
    return base

并生成具有500个元素的随机数组:

V = np.random.randn(500)

然后我们使用以下命令进行测试:

>>> timeit(wil, number=10000)
3.461620999999923
>>> timeit(mii, number=10000)
13.704932000000099
>>> timeit(kas, number=10000)
159.63497699999994 

答案 1 :(得分:0)

这是一种矢量化方法:

FreeBooksProductId

答案 2 :(得分:0)

如果您只需要一种快速的解决方案,而又不想避免出现循环的解决方案,则可以简单地使用NumbaCython

示例

import numpy as np
import numba as nb

@nb.njit()
def create_mat(V):
  arr=np.zeros((V.shape[0],V.shape[0]),dtype=V.dtype)
  for i in range(V.shape[0]):
    for j in range(i,V.shape[0]):
      arr[i,j]=V[j-i]
  return arr

时间

V=np.random.rand(10000)
#The first call has an constant compilation overhead of about 0.2s, 
#which is neglected here.
create_mat: 0.35s

答案 3 :(得分:0)

使用以下内容:

from scipy.linalg import toeplitz
res=np.tril(toeplitz(V).T

输出:

res
>>array([[10, 20, 30, 40,  0,  1],
         [ 0, 10, 20, 30, 40,  0],
         [ 0,  0, 10, 20, 30, 40],
         [ 0,  0,  0, 10, 20, 30],
         [ 0,  0,  0,  0, 10, 20],
         [ 0,  0,  0,  0,  0, 10]])