【Python】疯狂的加速函数!

共 1693字,需浏览 4分钟

 ·

2022-02-12 13:20

作者:杰少

einsum函数


简介

在平时的工作中,包括时间序列等的建模中,我们常常会涉及到线性或者Multilinear代数的计算,很多时候包括我在内也喜欢偷懒使用numpy来处理,个人觉得还是可以的,但有的朋友觉得这个看起来可读性会差一些,并且速度上也差一些,今天就推荐一个新的函数einsum函数。

通过einsum函数,我们可以写出可读性更好,更加高效的函数。

einsum函数


01


关于einsum函数

einsum函数一般会用于向量,矩阵,张量的计算中。

如果输入的是标量(scalar),我们就可以空着,因为它没有下标。

02


einsum函数优势

1.速度优势

因为numpy很多是用C写的。

  • 如果我们使用Python循环时,所有数据操作都在Python解释器中进行。

  • 当使用内置numpy函数时,它发生在C中,这就是numpy速度更快的原因。

  • 使用einsum时,numpy会在C中处理数据一次并返回最终结果,而使用多个numpy函数会花费更多时间返回多个值。

2.可读性优势

einsum的代码可读性会更强,能大大提高代码的可读性和效率。

代码
  • 比较循环,numpy中的其它函数,einsum

从下面的案例中,我们发现einsum比numpy快乐将近30倍,比循环快了500-600倍。

import numpy as np

A = np.random.rand(1000,1000)
B = np.random.rand(1000,1000)
%%time
# Using loops
s = 0
n, m = A.shape
for i in range(n):
    for j in range(m):
        s += A[i, j]*B[i, j] 
s

# CPU times: user 596 ms, sys: 5.79 ms, total: 602 ms
# Wall time: 607 ms
# 249760.77497519302
CPU times: user 596 ms, sys: 5.79 ms, total: 602 ms
Wall time: 607 ms
249760.77497519302
%%time
# Using built-in numpy functions
np.trace(np.dot(A.T, B))

# CPU times: user 113 ms, sys: 8.54 ms, total: 121 ms
# Wall time: 38.1 ms
# 249760.7749751993
CPU times: user 113 ms, sys: 8.54 ms, total: 121 ms
Wall time: 38.1 ms
249760.7749751993
%%time
# Using einsum
np.einsum('ij,ij->', A,B)

# CPU times: user 1.64 ms, sys: 689 µs, total: 2.33 ms
# Wall time: 1.19 ms
# 249760.7749751993
CPU times: user 1.64 ms, sys: 689 µs, total: 2.33 ms
Wall time: 1.19 ms
249760.7749751993
适用问题

所有涉及到矩阵,向量,张量等计算的问题。

参考文献
  1. Write Better And Faster Python Using Einstein Notation
往期精彩回顾




浏览 49
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐