代码之家  ›  专栏  ›  技术社区  ›  user181452

以numpy的风格重构矩阵置换

  •  1
  • user181452  · 技术社区  · 7 年前

    我写了下面的代码来做矩阵置换的乘法,我想知道它是否可以用 numpy

    Z = np.empty([new_d, X.shape[1]])
    Z = np.ndarray(shape=(new_d, X.shape[1]))
    Z = np.concatenate((X, X**2))
    res = []
    for i in range(0, d):
        for j in range(i+1, d):
            res.append(np.array(X.T[:,i]* X.T[:,j]))
    
    Z = np.concatenate((Z, res))
    

    而: X shape is (7, 1000), d = 7, new_d=35

    有什么建议吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Divakar    7 年前

    方法#1

    我们可以用 np.triu_indices 要获得这些成对排列索引,然后只需执行行索引数组的元素乘法-

    r,c = np.triu_indices(d,1)
    res = X[r]*X[c]
    

    进近#2

    为了提高内存效率和性能,特别是在大型阵列上,我们最好对输入阵列进行切片,并在每次迭代处理数据块时运行单个循环,如下所示-

    n = d-1
    idx = np.concatenate(( [0], np.arange(n,0,-1).cumsum() ))
    start, stop = idx[:-1], idx[1:]
    L = n*(n+1)//2
    res_out = np.empty((L,X.shape[1]), dtype=X.dtype)
    for i,(s0,s1) in enumerate(zip(start,stop)):
        res_out[s0:s1] = X[i] * X[i+1:]
    

    得到 Z 我们可以直接修改先前发布的方法,这样可以避免所有这些连接-

    n = d-1
    N = len(X)
    idx = 2*N + np.concatenate(( [0], np.arange(n,0,-1).cumsum() ))
    start, stop = idx[:-1], idx[1:]
    L = n*(n+1)//2
    Z_out = np.empty((2*N + L,X.shape[1]), dtype=X.dtype)
    Z_out[:N] = X
    Z_out[N:2*N] = X**2
    for i,(s0,s1) in enumerate(zip(start,stop)):
        Z_out[s0:s1] = X[i] * X[i+1:]