【问题标题】:How can I improve the efficiency of matrix multiplication in python?如何提高python中矩阵乘法的效率?
【发布时间】:2018-05-10 13:28:03
【问题描述】:

我写了一个代码来做不同范围的矩阵乘法,但是执行代码需要很多时间,

代码:

使用嵌套循环将两个矩阵相乘

import time

print("Enter the size of matrix A")
m = int(input())
n = int(input())
print("Enter the size of matrix A")
p = int(input())
q = int(input())
if(n==p):
     print('enter matrix A')
else:
    print("invalid entry")
    exit()
our_list1 = []
A = []
i = 0
int(i)

for i in range(m):
    for i in range(n):
            number = int(input('Please enter a element '))
            our_list1.append(number)
    A.append(our_list1)
    our_list1= []
print(A)
print('enter matrix B')
our_list1 = []
B = []

for i in range(p):
    for i in range(q):
            number = int(input('Please enter a element '))
            our_list1.append(number)
    B.append(our_list1)
    our_list1= []
print(B)
start_time = time.time()

#
our_list1 = []
R = []

for i in range(m):
    for i in range(q):
            number = 0
            our_list1.append(number)
    R.append(our_list1)
    our_list1= []
print(R)
for i in range(len(A)):

    # iterating by coloum by B
    for j in range(len(B[0])):

        # iterating by rows of B
        for k in range(len(B)):
            R[i][j] += A[i][k] * B[k][j]
print(R)
print("--- %s seconds ---" % (time.time() - start_time))

这种矩阵乘法的执行时间比较长,如何才能选择有效的大维数范围矩阵乘法呢?所以高维数组可以顺利快速地执行。 示例输出:

Matrix A[[3, 3, 3], [3, 3, 3], [3, 3, 3]]
Matrix B[[3, 3, 3], [3, 3, 3], [3, 3, 3]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
[[27, 27, 27], [27, 27, 27], [27, 27, 27]]
--- 0.00014400482177734375 seconds ---

高维乘法需要 0.00014400482177734375 秒,我可以改进这个时间吗?

【问题讨论】:

  • 只需使用专门的模块即可,即numpy
  • 我不认为 0.0001 秒是“很多时间”,但如果你需要处理大矩阵,你应该使用 numpy
  • 好吧,我以前没用过 numpy,能用它做高阶矩阵乘法吗?
  • 可以的,这个模块就是为有效处理这类问题而设计的。
  • 好的,我会用 nympy 并检查时差

标签: python python-3.x list numpy


【解决方案1】:

您的 cmets 中的这种计时有一些明显的缺点:

  1. print() 比较贵,和计算无关。将它包含在时间安排中可能会占用整个时间的很大一部分。
  2. 使用挂钟 (time.time()) 不是获得稳定计时的好方法;运行一次,您的系统上可能会发生任何事情。

这应该会提供一个更好的测试用例进行比较:

import numpy as np

def python_lists():
    A = [[3, 3, 3], [3, 3, 3], [3, 3, 3]]
    B = [[3, 3, 3], [3, 3, 3], [3, 3, 3]]
    our_list1 = []
    R = []

    for i in range(3):
        for i in range(3):
                number = 0
                our_list1.append(number)
        R.append(our_list1)
        our_list1= []

    for i in range(len(A)):

        # iterating by coloum by B
        for j in range(len(B[0])):

            # iterating by rows of B
            for k in range(len(B)):
                R[i][j] += A[i][k] * B[k][j]


def numpy_array():
    A = np.full((3, 3), 3)
    B = np.full((3, 3), 3)
    result = np.dot(A, B)

还有时间:

%timeit python_lists()
15 µs ± 45.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit numpy_array()
5.57 µs ± 44.7 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

因此,对于这个示例,NumPy 的速度要快约 3 倍。但如果你有更大的数组,这会更重要。

编辑: 实际上,您可能会争辩说,在函数内部创建 AB 对实际矩阵乘法的计时没有帮助,所以如果我先创建列表/数组并传递它们,新的计时是:

%timeit python_lists(A, B)
14.4 µs ± 98.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

%timeit numpy_array(A, B)
1.2 µs ± 13.3 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

并且,为了完整起见,对于形状为 (200, 200) 的数组:

%timeit python_lists()
6.99 s ± 128 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%timeit numpy_array()
5.77 ms ± 43.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

【讨论】:

  • 感谢您的详细分析,现在我正在想办法创建一个可以传递 A 和 B 的函数
  • 你是如何计算函数 %timeit python_lists(A, B) 的时间的?如果我在代码或终端中使用它会出现语法错误
  • @NikhilR 我使用 Spyder 作为我的 IDE,所以它让我可以访问 iPython 魔术方法 - %timeit is one of those。如果您使用的是常规 Python,那么您将不得不使用 timeit module 跳过更多的障碍
猜你喜欢
  • 2012-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 2014-02-25
相关资源
最近更新 更多