Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 三维numpy矩阵中张量的整形_Arrays_Python 3.x_Numpy - Fatal编程技术网

Arrays 三维numpy矩阵中张量的整形

Arrays 三维numpy矩阵中张量的整形,arrays,python-3.x,numpy,Arrays,Python 3.x,Numpy,我基本上是想通过一个3D矩阵(128128,60,6)来完成。第四维是表示该体素处扩散阵列的阵列向量,例如: d[30,30,30,:] = [dxx, dxy, dxz, dyy, dyz, dzz] = D_array 其中dxx等为特定方向的扩散。D_阵列也可以看作一个三角形矩阵(因为dxy==dyx等)。所以我可以用另外两个答案从D_数组到D_平方,例如 D_square = [[dxx, dxy, dxz], [dyx, dyy, dyz],[dzx, dzy, dzz]] 然而,

我基本上是想通过一个3D矩阵(128128,60,6)来完成。第四维是表示该体素处扩散阵列的阵列向量,例如:

d[30,30,30,:] = [dxx, dxy, dxz, dyy, dyz, dzz] = D_array
其中dxx等为特定方向的扩散。D_阵列也可以看作一个三角形矩阵(因为dxy==dyx等)。所以我可以用另外两个答案从D_数组到D_平方,例如

D_square = [[dxx, dxy, dxz], [dyx, dyy, dyz],[dzx, dzy, dzz]]
然而,我似乎不知道下一步是什么——如何将一个D_数组到D_正方形的单位变换应用于整个3D体积

以下是在单个张量上工作的代码片段:

#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))
那么,一次将扩散张量的单位变换公式化为整个3D体积的最简单方法是什么呢?

方法#1

这里是一个使用
行、列
索引从
triu_索引
沿最后两个轴索引到初始化输出数组的方法-

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

最后,提出了一种使用
掩蔽
的新方法,该方法的性能应该更好,因为大多数基于
掩蔽
的方法在索引时都是如此-

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)

矢量化方法:

# 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)。这就是我直观的目标-我的主要误解是在分配给DBU时对d_张量进行索引,但如果按照当前编辑的方式进行,则会将非对角线元素减半。调用.fill_diagonale的优点是保留所有正常的元素(例如非对角元素),但只需切换通过转置将原来的值加倍的对角元素,即非double。我想我们也可以做一些/2,但是被I==j(例如diago索引)掩盖了。我只是写了这篇文章,其他人读到的细节没有出错。我直觉上喜欢这种风格,但我接受了另一种,因为它总体上更全面(检查类型以及维度上的泛型)。谢谢你的回答,虽然它确实有效——尽管这让我意识到我的go-to公式倾向于向量寻址(更接近Daniel的答案)。我需要进一步研究(整数/布尔索引)。我有点了解要点,但还不了解细节。有趣。@LogicOnAbstractions在编辑的文章中,查看应用程序#1,可能更容易。尝试使用较小的数据,比如-
ar=np.random.randint(11,99,(3,6))
并分解每个步骤。
# 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