【问题标题】:Multiply several matrices in numpy在numpy中将几个矩阵相乘
【发布时间】:2012-08-04 00:26:43
【问题描述】:

假设你有 n 个方阵 A1,...,An。反正有没有以一种简洁的方式将这些矩阵相乘?据我所知,numpy 中的 dot 只接受两个参数。一种明显的方法是定义一个函数来调用自身并获取结果。有没有更好的方法来完成它?

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    这可能是一个相对较新的功能,但我喜欢:

    A.dot(B).dot(C)
    

    或者如果你的链条很长,你可以这样做:

    reduce(numpy.dot, [A1, A2, ..., An])
    

    更新:

    有更多关于 reduce here. 的信息这里是一个可能有帮助的例子。

    >>> A = [np.random.random((5, 5)) for i in xrange(4)]
    >>> product1 = A[0].dot(A[1]).dot(A[2]).dot(A[3])
    >>> product2 = reduce(numpy.dot, A)
    >>> numpy.all(product1 == product2)
    True
    

    2016 年更新: 从 python 3.5 开始,有一个新的 matrix_multiply 符号,@:

    R = A @ B @ C
    

    【讨论】:

    • 感谢您的回复。第一个选项工作正常;但第二个没有;或者至少我无法让它工作。您能否详细说明一下,或者举个例子?非常感谢
    • 我一直遇到这个问题,最后写了一个辅助函数。希望这是 NumPy 的一部分:def xdot(*args): return reduce(np.dot, args)
    • 只需添加一条注释,当 A、B 和 C 的类型为 numpy.ndarray 时,此方法有效。这可能适用于其他类型,但我没有检查。
    • NameError: name 'reduce' is not defined
    • 在 python3 中,reduce 被移到了 functools,from functools import reduce
    【解决方案2】:

    用更新复活一个老问题:

    November 13, 2014 开始,现在有一个np.linalg.multi_dot 函数可以完全满足您的需求。它还具有优化调用顺序的好处,尽管在您的情况下这不是必需的。

    请注意,这从 numpy 版本 1.10 开始可用。

    【讨论】:

    • 这应该是将来到达这里的任何人的首选答案。
    • @np.linalg.multi_dot之间有速度差异吗?
    • @kanso37 我使用A_list = [np.random.random(100, 100) for i in range(3)] 创建了一个如上所示的数组列表,使用%timeit np.linalg.multi_dot(A_list)%timeit A_list[0] @ A_list[1] @ A_list[2] 运行一个简单的测试。第二种方法似乎优于第一种方法(在我的机器上为 100 us 对 85 us),但我当然无法判断这是否属实。我还想知道如何将第二种方法以递归方式作为第一种方法进行泛化。
    【解决方案3】:

    实现此目的的另一种方法是使用 einsum,它为 NumPy 实现了 Einstein summation convention

    为了非常简要地解释这个问题的约定:当你把你的多矩阵乘积写成一个很大的乘积之和时,你会得到类似的东西:

    P_im = sum_j sum_k sum_l A1_ij A2_jk A3_kl A4_lm
    

    其中P 是您的产品的结果,A1A2A3A4 是输入矩阵。请注意,您对在 summand 中出现两次的索引进行求和,即 jkl。由于具有此属性的总和经常出现在物理学、向量微积分以及可能的其他一些领域中,因此有一个 NumPy 工具可以解决它,即einsum

    在上面的例子中,你可以用它来计算你的矩阵乘积,如下所示:

    P = np.einsum( "ij,jk,kl,lm", A1, A2, A3, A4 )
    

    这里,第一个参数告诉函数哪些索引应用于参数矩阵,然后将所有双重出现的索引相加,产生所需的结果。

    请注意,计算效率取决于几个因素(因此您最好只测试一下):

    【讨论】:

      【解决方案4】:

      如果您先验地计算所有矩阵,那么您应该使用矩阵链乘法的优化方案。见this Wikipedia article

      【讨论】:

      • 感谢您的评论;但我认为方阵并不重要。对吗?
      • @Nikandish:正确。我错过了您原始答案中的那部分。
      【解决方案5】:
      A_list = [np.random.randn(100, 100) for i in xrange(10)]
      B = np.eye(A_list[0].shape[0])
      for A in A_list:
          B = np.dot(B, A)
      
      C = reduce(np.dot, A_list)
      
      assert(B == C)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-06-06
        • 2020-07-18
        • 1970-01-01
        • 1970-01-01
        • 2015-08-29
        • 1970-01-01
        • 2020-08-27
        • 1970-01-01
        相关资源
        最近更新 更多