numpy 转置矩阵数组中的每个矩阵而不改变顺序

3phpmpom  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(127)

xy包含3个维度为1*3的矩阵,

x = np.array([[1, 2, 3], [4,5,6], [1, 2, 3]])

y = np.array([[11, 22, 33], [44,55,66], [11, 22, 33]])

I want to make matrix multiplication between x and y, and hence y should be transposed i.e., each vector in y should be 3*1 and Z should be an array that contains the result of x[0]*y[0]' x[1]*y[1]' x[2]*y[2]'

如何在x中只转置每个矩阵而不改变它们的顺序?我尝试了x_transposed = x.T,但它做了不同的事情

lh80um4z

lh80um4z1#

x = np.array([[1, 2, 3], [4,5,6], [1, 2, 3]])是一个 * 二维 * 数组,所以你可以说它包含三个形状为(3,)的 * 向量 *。为了证明这点

for v in x:
    print(v.shape, v)

打印:

(3,) [1 2 3]
(3,) [4 5 6]
(3,) [1 2 3]

要让x包含三个形状为(1, 3)的矩阵,需要它是一个 * 三维 * 数组x = np.array([[[1, 2, 3]], [[4,5,6]], [[1, 2, 3]]])。现在,上面的相同循环打印:

(1, 3) [[1 2 3]]
(1, 3) [[4 5 6]]
(1, 3) [[1 2 3]]

然后,你可以转置这个数组的第二个和第三个轴:

x_transposed = np.transpose(x, axes=(0, 2, 1))

这导致:

array([[[1],
        [2],
        [3]],

       [[4],
        [5],
        [6]],

       [[1],
        [2],
        [3]]])

要将原始x转换为三维数组,您可以在两个现有轴的中间添加一个轴:

x = x[:, None, :]
2skhul33

2skhul332#

我更希望你实际上显示你想要的结果,但我认为你想要的是行对的dot乘积:

In [15]: [np.dot(i,j) for i, j in zip(x,y)]
Out[15]: [154, 847, 154]

如果你花时间去阅读np.dot文档(原始的矩阵乘积函数),你会发现它很乐意将1d数组作为参数。
获得相同值的另一种方法:

In [18]: (x*y).sum(axis=1)
Out[18]: array([154, 847, 154])

一行y是(3)形状(1d)

In [23]: y[0]
Out[23]: array([11, 22, 33])

转置并不会改变任何东西,因为只有一个轴。转置不add维度:

In [24]: y[0].T
Out[24]: array([11, 22, 33])

如果数组是2d,(1,3),转置将使它成为(3,1),一个“列向量”,也可以用以下方法创建:

In [25]: y[0][:,None]
Out[25]: 
array([[11],
       [22],
       [33]])

dot的两个(3,)产生标量:

In [27]: np.dot(x[0],y[0])
Out[27]: 154

dot的(3,)和(3,1)产生一个(1,),数组:

In [28]: np.dot(x[0],y[0][:,None])
Out[28]: array([154])

(a(1,3)与(3,1)将产生a(1,1))。
dot(x,y.T)(或使用matmul运算符),生成一个(3,3)数组,其对角线上有所需的3个值:

In [30]: [email protected]
Out[30]: 
array([[154, 352, 154],
       [352, 847, 352],
       [154, 352, 154]])

得到这个“对角线”的一个更好的方法是使用einsum,指定尺寸j是乘积之和:

In [32]: np.einsum('ij,ij->i',x,y)
Out[32]: array([154, 847, 154])

matmul/@让我们把3维中的第一个当作batch,所以通过制作数组(3,1,3)和(3,3,1),我们得到一个(3,1,1)结果:

In [33]: x[:,None,:] @ y[:,:,None]
Out[33]: 
array([[[154]],

       [[847]],

       [[154]]])

(1,1)维度可以是squeezedout。
对于2d dot/matmul,用A的最后一个dim和B的第二个到最后一个dim进行乘积和。

相关问题