【问题标题】:Numpy: Multiply a matrix with an array of vectorsNumpy:将矩阵与向量数组相乘
【发布时间】:2017-07-15 17:16:38
【问题描述】:

我很难进入 numpy。我最终想要的是一个简单的由矩阵转换的向量的颤动图。我已经读过很多次了,只是将数组用于矩阵,这很公平。我有一个用于 x 和 y 坐标的网格

X,Y = np.meshgrid( np.arange(0,10,2),np.arange(0,10,1) )
a = np.array([[1,0],[0,1.1]])

但即使在谷歌搜索并尝试了两个多小时后,我也无法从 a 的矩阵乘法和每个向量中得到结果向量。我知道 quiver 将分量长度作为输入,因此进入 quiver 函数的结果向量应该类似于 x 分量的 np.dot(a, [X[i,j], Y[i,j]]) - X[i,j],其中 i 和 j 迭代范围。

我当然可以循环编程,但是 numpy 有太多内置工具可以方便地使用这些矢量化的东西,我相信有更好的方法。

编辑:好的,这是循环版本。

import numpy as np
import matplotlib.pyplot as plt

plt.figure(figsize=(10,10))

n=10
X,Y = np.meshgrid( np.arange(-5,5),np.arange(-5,5) )
print("val test", X[5,3])
a = np.array([[0.5,0],[0,1.3]])
U = np.zeros((n,n))
V = np.zeros((n,n))
for i in range(10):
    for j in range(10):
        product = np.dot(a, [X[i,j], Y[i,j]]) #matrix with vector
        U[i,j] = product[0]-X[i,j]  # have to substract the position since quiver accepts magnitudes
        V[i,j] = product[1]-Y[i,j]

Q = plt.quiver( X,Y, U, V)

【问题讨论】:

  • 您希望结果是什么样的? a.shape = (2,2), X.shape = (10,5), Y.shape = (10,5)。我不明白你的意思......
  • 你能在循环中显示一个简单的版本吗(以便更容易弄清楚你想要做什么)?
  • 完成。它实际上只是一个向量场上的矩阵,结果通过颤动箭头可视化
  • 我发布了一个关于做这种点积的答案here,可能对你有帮助。

标签: numpy scipy


【解决方案1】:

您可以像这样使用 NumPy 广播“手动”进行矩阵乘法:

import numpy as np
import matplotlib.pyplot as plt

X,Y = np.meshgrid(np.arange(-5,5), np.arange(-5,5))
a = np.array([[0.5, 0], [0, 1.3]])

U = (a[0,0] - 1)*X + a[0,1]*Y
V = a[1,0]*X + (a[1,1] - 1)*Y

Q = plt.quiver(X, Y, U, V)

或者,如果您想使用 np.dot,您必须将 XY 数组展平,并将它们组合成适当的形状,如下所示:

import numpy as np
import matplotlib.pyplot as plt

X,Y = np.meshgrid(np.arange(-5,5), np.arange(-5,5))
a = np.array([[0.5, 0], [0, 1.3]])

U,V = np.dot(a-np.eye(2), [X.ravel(), Y.ravel()])

Q = plt.quiver(X, Y, U, V)

【讨论】:

  • 嗯,我很感激。但这都是极其有限的情况,对吧?首先是手写矩阵乘法。这很 hacky,不适用于任何更高的维度等。第二个是依赖于零。
  • 两种情况都是二维的。对于 3D,它应该类似于 U,V,W = np.dot(a-np.eye(3), [X.ravel(), Y.ravel(), Z.ravel()])
【解决方案2】:

作为docs says,对于多维数据np.mul(或@)的工作方式如下:

对于 N 维,它是 a 的最后一个轴和 b 的倒数第二个轴的和积:

dot(a, b)[i,j,k,m] = sum(a[i,j,:] * b[k,:,m])

这不是我们想要的。但是,有一些简单的替代方案不涉及展平-去展平或手动矩阵乘法:np.tensordotnp.einsum

第一个是直接取自the docs的例子:

要使用最左边的索引而不是最右边的索引进行矩阵矩阵乘积,您可以使用np.einsum('ij...,jk...->ik...', a, b)

import numpy as np
import matplotlib.pyplot as plt

X,Y = np.meshgrid(np.arange(-5,5), np.arange(-5,5))
a = np.array([[0.5, 0], [0, 1.3]])

U, V = np.einsum('ij...,jk...->ik...', a - np.eye(2), np.array([X, Y]))
Q = plt.quiver(X, Y, U, V)

第二个是简单的np.tensordot的应用。我们只是教它对第一个参数的第二个轴(列)和第一个参数的第一个轴(行)求和。

import numpy as np
import matplotlib.pyplot as plt

X,Y = np.meshgrid(np.arange(-5,5), np.arange(-5,5))
a = np.array([[0.5, 0], [0, 1.3]])

U, V = np.tensordot(a - np.eye(2), np.array([X, Y]), axes=(1, 0))
plt.quiver(X, Y, U, V)

【讨论】:

    【解决方案3】:

    我一直在为同样的问题而苦苦挣扎,最终使用了 numpy.matrix 类。考虑下面的例子。

    import numpy as np
    
    >>> transformation_matrix = np.array([(1, 0, 0, 1),
    ...                                   (0, 1, 0, 0),
    ...                                   (0, 0, 1, 0),
    ...                                   (0, 0, 0, 1)])
    >>> coordinates = np.array([(0,0,0),
    ...                         (1,0,0)])
    >>> coordinates = np.hstack((coordinates, np.ones((len(coordinates), 1))))
    >>> coordinates
    array([[ 0.,  0.,  0.,  0.],
           [ 1.,  0.,  0.,  0.]])
    

    在这种情况下,numpy.matrix 类会有所帮助。以下代码通过将坐标转置为列向量和 numpy.matrix 类的指定矩阵乘法重载来给出预期结果。

    >>> (np.asmatrix(transformation_matrix) * np.asmatrix(coordinates).T).T
    matrix([[ 1.,  0.,  0.,  1.],
            [ 2.,  0.,  0.,  1.]])
    

    【讨论】:

    • 为什么先将它们定义为数组,然后才将它们转换为矩阵?你可以做到transformation_matrix = np.matrix([(1,0,0,1), (0,1,0,0), (0,0,1,0), (0,0,0,1)])
    • @R.Navega 没错,这只是因为 OP 在 ndarrays 上运行。请注意,asmatrix() 不会复制数据:“与矩阵不同,如果输入已经是矩阵或 ndarray,则 asmatrix 不会复制。等效于矩阵(数据,复制=假)。” docs.scipy.org/doc/numpy/reference/generated/…
    猜你喜欢
    • 2020-09-03
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多