DeepLearing学习笔记-数据矢量化

来源:互联网 发布:java游戏编程入门 编辑:程序博客网 时间:2024/05/16 05:51

背景:

通过矢量化提高矩阵运算速度

准备知识:

dot/outer/elementwise product 的区别:

dot product 点乘:

向量点积:
向量的点乘,也叫向量的内积、数量积,对两个向量执行点乘运算,就是对这两个向量对应位一一相乘之后求和的操作,点乘的结果是一个标量。
定义:ab=||a||||b||cos(θ),即是两个向量的模和两向量夹角余弦的乘积。
点乘的几何意义是可以用来表征或计算两个向量之间的夹角,以及在b向量在a向量方向上的投影。
矩阵内积:
内积是一种降维运算,变成一个数。矩阵的内积是每行每列的点积所组成的矩阵。所以,点积是一维向量之间的操作,内积是多维向量,即矩阵的操作。两者本质是一样的。其实,内积就是我们一般常用的矩阵乘积,行列进行相互乘积,作为结果矩阵指定位置的元素结果值。所以,要求a矩阵的列数量等于b矩阵的行数量。
示例代码:

x = numpy.array([1, 2])y = numpy.array([10, 20])print("Array inner:")print(numpy.inner(x, y))''' Output:Array inner:50'''x = numpy.mat([[1, 2], [3, 4]])y = numpy.mat([10, 20])print("Matrix inner:")print(numpy.inner(x, y))
Output:Matrix inner:[[ 50] [110]]

outer product 外积:

两个向量的叉乘,又叫向量积、外积、叉积,叉乘的运算结果是一个向量而不是一个标量,是向量的升维运算。并且两个向量的外积与这两个向量组成的坐标平面垂直。m维向量和n维向量的外积是m*n维矩阵。
定义:
a×b
矩阵外积:
假设a的维度是(m,n),b的维度是(p,q)
a×b=a11...a1m.........a1m...amnb11...b1p.........b1q...bpq=a11b11...a1nb11a21b11...amnb11..................a11b1q...a1nb1qa21b1q...amnb1qa11b21...a1nb21a21b21...amnb21..................a11bpq...a1nbpqa21bpq...amnbpq(1)
向量外积:
a=(x1,y1,z1)
b=(x2,y2,z2)
a×b=ix1x2jy1y2kz1z2=(y1z2y2z1)i(x1z2x2z1)j+(x1y2x2y1)k(2)
其中:
i=(1,0,0)j=(0,1,0)k=(0,0,1)
叉乘几何意义:
在三维几何中,向量a和向量b的叉乘结果是一个向量,更为熟知的叫法是法向量,该向量垂直于a和b向量构成的平面。
在二维空间中,叉乘还有另外一个几何意义就是:aXb等于由向量a和向量b构成的平行四边形的面积。

示例代码:

x = numpy.array([1, 3])y = numpy.array([10, 20])print("Array outer:")print(numpy.outer(x, y))''' Output:Array outer:[[10 20] [30 60]]'''x = numpy.mat([[1, 2], [3, 4]])y = numpy.mat([10, 20])print("Matrix outer:")print(numpy.outer(x, y))
Output:Matrix outer:[[10 20] [20 40] [30 60] [40 80]]

elementwise product 元素积:

定义:
ab
有三种情况:
ab=[a1am][b1...bm](3)

ab=[a1an]b1b2...bm =a1b1...a1bm.........anb1...anbm(4)
第三种情况,就是两个矩阵尺寸相同,则是对应位置的元素乘积。

示例代码:

x = numpy.array([1, 3])y = numpy.array([10, 20])print("Array element-wise product:")print(x * y)

输出:
Array element-wise product:
[10 60]

矢量化操作:

循环实现矩阵运算:

import timex1 = [9, 2, 5, 0, 0, 7, 5, 0, 0, 0, 9, 2, 5, 0, 0]x2 = [9, 2, 2, 9, 0, 9, 2, 5, 0, 0, 9, 2, 5, 0, 0]#用循环来实现dot product### CLASSIC DOT PRODUCT OF VECTORS IMPLEMENTATION ###tic = time.process_time()dot = 0for i in range(len(x1)):    dot+= x1[i]*x2[i]toc = time.process_time()print ("dot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")#用循环来实现outer product### CLASSIC OUTER PRODUCT IMPLEMENTATION ###tic = time.process_time()outer = np.zeros((len(x1),len(x2))) # we create a len(x1)*len(x2) matrix with only zerosfor i in range(len(x1)):    for j in range(len(x2)):        outer[i,j] = x1[i]*x2[j]toc = time.process_time()print ("outer = " + str(outer) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")#用循环来实现 元素之间乘积### CLASSIC ELEMENTWISE IMPLEMENTATION ###tic = time.process_time()mul = np.zeros(len(x1))for i in range(len(x1)):    mul[i] = x1[i]*x2[i]toc = time.process_time()print ("elementwise multiplication = " + str(mul) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")#用循环来实现泛化的点积,即内积。### CLASSIC GENERAL DOT PRODUCT IMPLEMENTATION ###W = np.random.rand(3,len(x1)) # Random 3*len(x1) numpy arraytic = time.process_time()gdot = np.zeros(W.shape[0])for i in range(W.shape[0]):    for j in range(len(x1)):        gdot[i] += W[i,j]*x1[j]toc = time.process_time()print ("gdot = " + str(gdot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

执行结果:

dot = 278 ----- Computation time = 0.0msouter = [[ 81.  18.  18.  81.   0.  81.  18.  45.   0.   0.  81.  18.  45.   0.    0.] [ 18.   4.   4.  18.   0.  18.   4.  10.   0.   0.  18.   4.  10.   0.    0.] [ 45.  10.  10.  45.   0.  45.  10.  25.   0.   0.  45.  10.  25.   0.    0.] [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.    0.] [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.    0.] [ 63.  14.  14.  63.   0.  63.  14.  35.   0.   0.  63.  14.  35.   0.    0.] [ 45.  10.  10.  45.   0.  45.  10.  25.   0.   0.  45.  10.  25.   0.    0.] [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.    0.] [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.    0.] [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.    0.] [ 81.  18.  18.  81.   0.  81.  18.  45.   0.   0.  81.  18.  45.   0.    0.] [ 18.   4.   4.  18.   0.  18.   4.  10.   0.   0.  18.   4.  10.   0.    0.] [ 45.  10.  10.  45.   0.  45.  10.  25.   0.   0.  45.  10.  25.   0.    0.] [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.    0.] [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.   0.    0.]] ----- Computation time = 0.0mselementwise multiplication = [ 81.   4.  10.   0.   0.  63.  10.   0.   0.   0.  81.   4.  25.   0.   0.] ----- Computation time = 0.0msgdot = [ 17.02350757  18.34972831  15.85377834] ----- Computation time = 0.0ms

上述的运行结果,并没有很直观表现循环操作的耗时,这是因为测试时候选用的数据量少的缘故。

基于numpy的矢量化矩阵运算

x1 = [9, 2, 5, 0, 0, 7, 5, 0, 0, 0, 9, 2, 5, 0, 0]x2 = [9, 2, 2, 9, 0, 9, 2, 5, 0, 0, 9, 2, 5, 0, 0]### VECTORIZED DOT PRODUCT OF VECTORS ###tic = time.process_time()dot = np.dot(x1,x2)toc = time.process_time()print ("dot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")### VECTORIZED OUTER PRODUCT ###tic = time.process_time()outer = np.outer(x1,x2)toc = time.process_time()print ("outer = " + str(outer) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")### VECTORIZED ELEMENTWISE MULTIPLICATION ###tic = time.process_time()mul = np.multiply(x1,x2)toc = time.process_time()print ("elementwise multiplication = " + str(mul) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")### VECTORIZED GENERAL DOT PRODUCT ###tic = time.process_time()dot = np.dot(W,x1)toc = time.process_time()print ("gdot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

运行结果:

dot = 278 ----- Computation time = 0.0msouter = [[81 18 18 81  0 81 18 45  0  0 81 18 45  0  0] [18  4  4 18  0 18  4 10  0  0 18  4 10  0  0] [45 10 10 45  0 45 10 25  0  0 45 10 25  0  0] [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0] [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0] [63 14 14 63  0 63 14 35  0  0 63 14 35  0  0] [45 10 10 45  0 45 10 25  0  0 45 10 25  0  0] [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0] [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0] [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0] [81 18 18 81  0 81 18 45  0  0 81 18 45  0  0] [18  4  4 18  0 18  4 10  0  0 18  4 10  0  0] [45 10 10 45  0 45 10 25  0  0 45 10 25  0  0] [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0] [ 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0]] ----- Computation time = 0.0mselementwise multiplication = [81  4 10  0  0 63 10  0  0  0 81  4 25  0  0] ----- Computation time = 0.0msgdot = [ 17.02350757  18.34972831  15.85377834] ----- Computation time = 0.0ms

采用矢量化的方式执行,结果更加简洁高效(数据量大时候,更加明显)。且对于np.dot是可以适用于矩阵或者矩阵向量的。对应元素的乘积,可以用np.multiply()或者*操作符。

循环方式和矢量化速度对比:

import timeimport numpy as npa = np.random.rand(1000000)b = np.random.rand(1000000)tic = time.time()c = np.dot(a,b)print(c)toc = time.time()print("vectorized version:" + str(1000*(toc-tic)) + "ms")c = 0tic = time.time()for i in range(1000000):    c+=a[i]*b[i]toc = time.time()print(c)print("loop version:" + str(1000*(toc-tic)) + "ms")

运行结果如下:

250375.165705vectorized version:24.0023136138916ms250375.165705loop version:543.0543422698975ms
阅读全文
0 0
原创粉丝点击