Python深度学习:基于PyTorch
上QQ阅读APP看书,第一时间看更新

1.6 通用函数

Numpy提供了两种基本的对象,即ndarray和ufunc对象。前文已经介绍了ndarray,本节将介绍Numpy的另一个对象通用函数(ufunc)。ufunc是universal function的缩写,它是一种能对数组的每个元素进行操作的函数。许多ufunc函数都是用C语言级别实现的,因此它们的计算速度非常快。此外,它们比math模块中的函数更灵活。math模块的输入一般是标量,但Numpy中的函数可以是向量或矩阵,而利用向量或矩阵可以避免使用循环语句,这点在机器学习、深度学习中非常重要。表1-5为Numpy中常用的几个通用函数。

表1-5 Numpy中的几个常用通用函数

1.math与numpy函数的性能比较

import time
import math
import numpy as np
x = [i * 0.001 for i in np.arange(1000000)]
start = time.clock()
for i, t in enumerate(x):
    x[i] = math.sin(t)
print ("math.sin:", time.clock() - start )
x = [i * 0.001 for i in np.arange(1000000)]
x = np.array(x)
start = time.clock()
np.sin(x)
print ("numpy.sin:", time.clock() - start )

打印结果:

math.sin: 0.5169950000000005
numpy.sin: 0.05381199999999886

由此可见,numpy.sin比math.sin快近10倍。

2.循环与向量运算比较

充分使用Python的Numpy库中的内建函数(Built-in Function),来实现计算的向量化,可大大地提高运行速度。Numpy库中的内建函数使用了SIMD指令。如下使用的向量化要比使用循环计算速度快得多。如果使用GPU,其性能将更强大,不过Numpy不支持GPU。PyTorch支持GPU,后面第5章将介绍PyTorch如何使用GPU来加速算法。

import time
import numpy as np
x1 = np.random.rand(1000000)
x2 = np.random.rand(1000000)
##使用循环计算向量点积
tic = time.process_time()
dot = 0
for i in range(len(x1)):
    dot+= x1[i]*x2[i]
toc = time.process_time()
print ("dot = " + str(dot) + "\n for loop----- Computation time = " + str(1000*(toc - tic)) + "ms")
##使用numpy函数求点积
tic = time.process_time()
dot = 0
dot = np.dot(x1,x2)
toc = time.process_time()
print ("dot = " + str(dot) + "\n verctor version---- Computation time = " + str(1000*(toc - tic)) + "ms")

输出结果:

dot = 250215.601995
 for loop----- Computation time = 798.3389819999998ms
dot = 250215.601995
 verctor version---- Computation time = 1.885051999999554ms

从运行结果上来看,使用for循环的运行时间大约是向量运算的400倍。因此,在深度学习算法中,一般都使用向量化矩阵进行运算。