【问题标题】:Reshaping tensors in a 3D numpy matrix在 3D numpy 矩阵中重塑张量
【发布时间】:2018-12-02 18:05:15
【问题描述】:

我实际上是在尝试完成 this 然后 this 但使用 3D 矩阵,例如 (128,128,60,6)。第 4 维是一个数组向量,表示该体素处的扩散数组,例如:

d[30,30,30,:] = [dxx, dxy, dxz, dyy, dyz, dzz] = D_array

其中 dxx 等是特定方向的扩散。 D_array 也可以看作是一个三角矩阵(因为 dxy == dyx 等)。所以我可以使用这两个其他答案从 D_array 到 D_square,例如

D_square = [[dxx, dxy, dxz], [dyx, dyy, dyz],[dzx, dzy, dzz]]

我似乎无法弄清楚下一步 - 如何将 D_array 到 D_square 的单位转换应用于整个 3D 体积。

这是适用于单个张量的代码 sn-p:

#this solves an linear eq. that provides us with diffusion arrays at each voxel in a 3D space
D = np.einsum('ijkt,tl->ijkl',X,bi_plus)

#our issue at this point is we have a vector that represents a triangular matrix.
# first make a tri matx from the vector, testing on unit tensor first
D_tri = np.zeros((3,3))
D_array = D[30][30][30]
D_tri[np.triu_indices(3)] = D_array
# then getting the full sqr matrix
D_square = D_tri.T + D_tri
np.fill_diagonal(D_square, np.diag(D_tri))

那么,将 Diffusion 张量的单位变换同时公式化到整个 3D 体积的 numpy 方法是什么?

【问题讨论】:

    标签: arrays python-3.x numpy


    【解决方案1】:

    方法#1

    这是一个使用来自triu_indicesrow, col 索引沿最后两个轴索引到一个初始化的输出数组 -

    def squareformnd_rowcol_integer(ar, n=3):
        out_shp = ar.shape[:-1] + (n,n)
        out = np.empty(out_shp, dtype=ar.dtype)
    
        row,col = np.triu_indices(n)
    
        # Get a "rolled-axis" view with which the last two axes come to the front
        # so that we could index into them just like for a 2D case
        out_rolledaxes_view = out.transpose(np.roll(range(out.ndim),2,0))    
    
        # Assign permuted version of input array into rolled output version
        arT = np.moveaxis(ar,-1,0)
        out_rolledaxes_view[row,col] = arT
        out_rolledaxes_view[col,row] = arT
        return out
    

    方法#2

    另一个将最后两个轴合并为一个,然后使用线性索引进行索引 -

    def squareformnd_linear_integer(ar, n=3):
        out_shp = ar.shape[:-1] + (n,n)
        out = np.empty(out_shp, dtype=ar.dtype)
    
        row,col = np.triu_indices(n)
        idx0 = row*n+col
        idx1 = col*n+row
    
        ar2D = ar.reshape(-1,ar.shape[-1])
        out.reshape(-1,n**2)[:,idx0] = ar2D
        out.reshape(-1,n**2)[:,idx1] = ar2D
        return out
    

    方法#3

    终于有了一个使用masking 的新方法,并且性能应该更好,因为大多数基于masking 的方法在索引方面都是如此 -

    def squareformnd_masking(ar, n=3):
        out = np.empty((n,n)+ar.shape[:-1] , dtype=ar.dtype)
    
        r = np.arange(n)
        m = r[:,None]<=r
    
        arT = np.moveaxis(ar,-1,0)
        out[m] = arT
        out.swapaxes(0,1)[m] = arT
        new_axes = range(out.ndim)[2:] + [0,1]
        return out.transpose(new_axes)
    

    (128,128,60,6) 形状随机数组的时间安排 -

    In [635]: ar = np.random.rand(128,128,60,6)
    
    In [636]: %timeit squareformnd_linear_integer(ar, n=3)
         ...: %timeit squareformnd_rowcol_integer(ar, n=3)
         ...: %timeit squareformnd_masking(ar, n=3)
    10 loops, best of 3: 103 ms per loop
    10 loops, best of 3: 103 ms per loop
    10 loops, best of 3: 53.6 ms per loop
    

    【讨论】:

    • 它确实有效——尽管这让我意识到我的首选公式往往是向量寻址(更多地符合 Daniel 的回答)。我需要研究一下(整数/布尔索引)。我有点明白它的要点,但不是细节(还)。很有趣。
    • @LogicOnAbstractions 在编辑后的帖子中,查看 app#1,可能会更容易。尝试使用较小的数据,例如 - ar = np.random.randint(11,99,(3,6)) 并分解每个步骤。
    【解决方案2】:

    一种矢量化的方法:

    # Gets the triangle matrix
    d_tensor = np.zeros(128, 128, 60, 3, 3)
    triu_idx = np.triu_indices(3)
    d_tensor[:, :, :, triu_idx[0], triu_idx[1]] = d
    # Make it symmetric
    diagonal = np.zeros(128, 128, 60, 3, 3)
    idx = np.arange(3)
    diagonal[:, :, :, idx, idx] = d_tensor[:, :, :, idx, idx]
    d_tensor = np.transpose(d_tensor, (0, 1, 2, 4, 3)) + d_tensor - diagonal
    

    【讨论】:

    • 这几乎可以工作,除了它会使 diagognale 上的元素加倍(这就是我在转置后使用 np.fill 的原因)。直观地说,这就是我的目标——我的主要误解是在分配给 d 时对 d_tensor 的索引
    • 但是,如果您按照当前编辑的方式进行操作,则非对角线元素将减半。调用 .fill_diagonale 的优点是保留所有正常的元素(例如非对角元素),但只需将已被转置加倍的对角元素切换为旧值,非双倍。我想我们也可以做一些 /2 但被 i==j 掩盖(例如 diago 索引)。我只是在写其他人的这篇文章,在这个细节上不会出错。
    • 我直觉上更喜欢这种风格,但我接受了另一种风格,因为它总体上更全面(检查类型以及维度上的更多泛型)。谢谢你的回答
    猜你喜欢
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    • 2011-05-28
    • 2020-10-25
    • 2021-03-07
    • 2016-11-08
    • 2021-10-05
    相关资源
    最近更新 更多