Numpy PyTorch-Fortran类索引排序中的整形顺序

Numpy PyTorch-Fortran类索引排序中的整形顺序,numpy,view,pytorch,reshape,Numpy,View,Pytorch,Reshape,在numpy中,有一个调整数组形状的排序功能,默认情况下是C,但您可以指定其他排序,如F: a = np.arange(6).reshape((3, 2)) f = np.reshape(a, (2, 3), order='F') # Fortran-like index ordering c = np.reshape(a, (2, 3)) print('a= \n', a) print('f= \n', b) print('c= \n', c) 结果是: a= [[0 1] [2 3

在numpy中,有一个调整数组形状的排序功能,默认情况下是C,但您可以指定其他排序,如F:

a = np.arange(6).reshape((3, 2))
f = np.reshape(a, (2, 3), order='F') # Fortran-like index ordering
c = np.reshape(a, (2, 3)) 
print('a= \n', a)
print('f= \n', b)
print('c= \n', c)
结果是:

a= 
 [[0 1]
 [2 3]
 [4 5]]
f= 
 [[0 4 3]
 [2 1 5]]
c= 
 [[0 1 2]
 [3 4 5]]
在torch.REFORMATE或tensor.view中没有按F顺序进行整形的选项。
有没有办法在PyTorch中实现F顺序重塑?我需要所有东西都在Pytork中。

我认为Pytork没有内置的支持。也就是说,您可以通过使用来实现所需的结果。不幸的是,我怀疑这会非常有效,因为AFAIK permute在内部复制了张量

def重塑_fortran(x,形状):
如果len(x.shape)>0:
x=x.permute(*反转(范围(len(x.shape)))
返回x.重塑(*反转(形状)).置换(*反转(范围(透镜(形状)))
用法示例:

a=torch.arange(6).重塑(3,2)
f=重塑_fortran(a,(2,3))
c=a.重塑(2,3)
导致

a=
张量([[0,1],
[2, 3],
[4, 5]])
f=
张量([[0,4,3],
[2, 1, 5]])
c=
张量([[0,1,2],
[3, 4, 5]])

我认为pytorch对此没有内置支持。也就是说,您可以通过使用来实现所需的结果。不幸的是,我怀疑这会非常有效,因为AFAIK permute在内部复制了张量

def重塑_fortran(x,形状):
如果len(x.shape)>0:
x=x.permute(*反转(范围(len(x.shape)))
返回x.重塑(*反转(形状)).置换(*反转(范围(透镜(形状)))
用法示例:

a=torch.arange(6).重塑(3,2)
f=重塑_fortran(a,(2,3))
c=a.重塑(2,3)
导致

a=
张量([[0,1],
[2, 3],
[4, 5]])
f=
张量([[0,4,3],
[2, 1, 5]])
c=
张量([[0,1,2],
[3, 4, 5]])
工作非常好,我对性能进行了进一步测试。与内置的
整形
相比,基于
置换
的整形需要大约10倍的计算时间。然而,在
numpy
中,内置的类似Fortran的
整形
也需要10倍的计算时间。所以这种方法非常有效:)

以下是i9-10900X和RTX2080Ti的测试代码和结果:

将numpy导入为np
进口火炬
导入时间
dim1=40
dim2=50
dim3=5
def重塑_fortran(x,形状):
如果len(x.shape)>0:
x=x.permute(*反转(范围(len(x.shape)))
返回x.重塑(*反转(形状)).置换(*反转(范围(透镜(形状)))
火炬.cuda.set_装置(0)
设备=火炬。设备('cuda')
x=[范围(100)内的火炬从_numpy(np.random.rand(dim1,dim2))到(设备)]
xx=[范围(100)内的火炬从_numpy(np.random.rand(dim1,dim2))到(设备)]
对于范围(100)内的i:
y=x[i]。重塑([dim2,dim1])
#重塑
t0=时间。时间()
对于范围(100)内的i:
y=xx[i]。重塑([dim2,dim3,-1])
t1=时间。时间()
#fortran整形
对于范围(100)内的i:
yy=重塑fortran(xx[i],[dim2,dim3,-1])
t2=时间。时间()
打印(f'火炬内置整形:{(t1-t0)/100}s')
打印(f'火炬置换整形:{(t2-t1)/100}s')
x=[np.random.rand(dim1,dim2)表示范围(100)]
xx=[np.random.rand(dim1,dim2)表示范围(100)]
对于范围(100)内的i:
y=x[i]。重塑([dim2,dim3,-1])
t0=时间。时间()
对于范围(100)内的i:
yy=xx[i]。重塑([dim2,dim3,-1])
t1=时间。时间()
对于范围(100)内的i:
yyy=xx[i]。重塑([dim2,dim3,-1],order='F')
t2=时间。时间()
打印(f'numpy C重塑:{(t1-t0)/100}s')
打印(f'numpy f重塑:{(t2-t1)/100}s')
工作非常好,我有一个关于性能的进一步测试。与内置的
整形
相比,基于
置换
的整形需要大约10倍的计算时间。然而,在
numpy
中,内置的类似Fortran的
整形
也需要10倍的计算时间。所以这种方法非常有效:)

以下是i9-10900X和RTX2080Ti的测试代码和结果:

将numpy导入为np
进口火炬
导入时间
dim1=40
dim2=50
dim3=5
def重塑_fortran(x,形状):
如果len(x.shape)>0:
x=x.permute(*反转(范围(len(x.shape)))
返回x.重塑(*反转(形状)).置换(*反转(范围(透镜(形状)))
火炬.cuda.set_装置(0)
设备=火炬。设备('cuda')
x=[范围(100)内的火炬从_numpy(np.random.rand(dim1,dim2))到(设备)]
xx=[范围(100)内的火炬从_numpy(np.random.rand(dim1,dim2))到(设备)]
对于范围(100)内的i:
y=x[i]。重塑([dim2,dim1])
#重塑
t0=时间。时间()
对于范围(100)内的i:
y=xx[i]。重塑([dim2,dim3,-1])
t1=时间。时间()
#fortran整形
对于范围(100)内的i:
yy=重塑fortran(xx[i],[dim2,dim3,-1])
t2=时间。时间()
打印(f'火炬内置整形:{(t1-t0)/100}s')
打印(f'火炬置换整形:{(t2-t1)/100}s')
x=[np.random.rand(dim1,dim2)表示范围(100)]
xx=[np.random.rand(dim1,dim2)表示范围(100)]
对于范围(100)内的i:
y=x[i]。重塑([dim2,dim3,-1])
t0=时间。时间()
对于范围(100)内的i:
yy=xx[i]。重塑([dim2,dim3,-1])
t1=时间。时间()
对于范围(100)内的i:
yyy=xx[i]。重塑([dim2,dim3,-1],order='F')
t2=时间。时间()
打印(f'numpy C重塑:{(t1-t0)/100}s')
打印(f'numpy f重塑:{(t2-t1)/100}s')

在NumPy中重塑数组,然后将其转换为PyTorch张量?谢谢,但我需要所有东西都在PyTorch中,因为我想在我的DNN中将该函数用作自定义损失函数。在NumPy中重塑数组,然后将其转换为PyTorch张量?谢谢,但我需要所有东西都在PyTorch中,因为我想在我的DNN中将该函数用作自定义的损失函数。谢谢Jodge,这是一个非常有效的答案。我通过连续的转置、展平和重新排列来实现它,虽然实用,但效率不高。谢谢你的回答。谢谢Jodge,这是一个非常有效的回答。我通过连续的转置、展平和重新排列来实现它,这不是ef
torch build-in reshape: 9.72747802734375e-07 s
torch permute reshape: 1.1897087097167968e-05 s
numpy C reshape: 3.0517578125e-07 s
numpy F reshape: 2.474784851074219e-06 s