首先声明本篇博客是本人学习CS231n的学习笔记,分享给大家当作参考。
数据类型
每个Numpy数组都是数据类型相同的元素组成的网格。Numpy提供了很多的数据类型用于创建数组。当你创建数组的时候,Numpy会尝试猜测数组的数据类型,你也可以通过参数直接指定数据类型,例子如下:
>>> import numpy as np
>>> x = np.array([1, 2])
>>> print(x.dtype)
int32
>>> x = np.array([1.0,2.0])
>>> print(x.dtype)
float64
>>> x = np.array([1, 2], dtype=np.int64)
>>> print(x.dtype)
int64
详细介绍请查阅Data type objects
数组计算
基本数学计算函数会对数组中元素逐个进行计算,既可以利用操作符重载,也可以使用函数方式:
>>> import numpy as np
>>> x = np.array([[1,2],[3,4]], dtype=np.float64)
>>> y = np.array([[5,6],[7,8]], dtype=np.float64)
>>> print(x + y)
[[ 6. 8.]
[ 10. 12.]]
>>> print(np.add(x,y))
[[ 6. 8.]
[ 10. 12.]]
>>> print(x - y)
[[-4. -4.]
[-4. -4.]]
>>> print(np.subtract(x,y))
[[-4. -4.]
[-4. -4.]]
>>> print(x * y)
[[ 5. 12.]
[ 21. 32.]]
>>> print(np.multiply(x,y))
[[ 5. 12.]
[ 21. 32.]]
>>> print(x / y)
[[ 0.2 0.33333333]
[ 0.42857143 0.5 ]]
>>> print(np.divide(x,y))
[[ 0.2 0.33333333]
[ 0.42857143 0.5 ]]
>>> print(np.sqrt(x))
[[ 1. 1.41421356]
[ 1.73205081 2. ]]
和MATLAB不同,*是元素逐个相乘,而不是矩阵乘法。在Numpy中使用dot来进行矩阵乘法:
>>> import numpy as np
>>> x = np.array([[1,2],[3,4]])
>>> y = np.array([[5,6],[7,8]])
>>> v = np.array([9,10])
>>> w = np.array([11, 12])
>>>
>>> print(v.dot(w))
219
>>> print(np.dot(v,w))
219
>>> print(x.dot(v))
[29 67]
>>> print(np.dot(x,v))
[29 67]
>>> print(x.dot(y))
[[19 22]
[43 50]]
>>> print(np.dot(x,y))
[[19 22]
[43 50]]
Numpy提供了很多计算数组的函数,其中最常用的一个是sum:
>>> import numpy as np
>>> x = np.array([[1,2],[3,4]])
>>> print(np.sum(x)) # Compute sum of all elements;
10
>>> print(np.sum(x,axis=0)) # Compute sum of each column
[4 6]
>>> print(np.sum(x,axis=1)) # Compute sum of each row
[3 7]
想要了解更多函数,可以查看Mathematical functions
除了计算,我们还常常改变数组或者操作其中的元素。其中将矩阵转置是常用的一个,在Numpy中,使用T来转置矩阵:
>>> import numpy as np
>>> x = np.array([[1,2], [3,4]])
>>> print(x)
[[1 2]
[3 4]]
>>> print(x.T)
[[1 3]
[2 4]]
# Note that taking the transpose of a rank 1 array does nothing:
>>> v = np.array([1,2,3])
>>> print(v)
[1 2 3]
>>> print(v.T)
[1 2 3]
Numpy还提供了更多操作数组的方法,请查看Array manipulation routines
Broadcasting
Broadcasting是一种强有力的机制,它让Numpy可以让不同大小的矩阵在一起进行数学计算。我们常常会有一个小的矩阵和一个大的矩阵,然后我们会需要用小的矩阵对大的矩阵做一些计算。
举个例子,如果我们想要把一个向量加到矩阵的每一行,我们可以这样做:
>>> import numpy as np
>>>
>>> x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
>>> v = np.array([1,0,1])
>>> y = np.empty_like(x) # Create an empty matrix with the same shape as x
>>>
>>> for i in range(4):
y[i,:] = x[i,:] + v
>>> print(y)
[[ 2 2 4]
[ 5 5 7]
[ 8 8 10]
[11 11 13]]
这样是行得通的,但是当x矩阵非常大,利用循环来计算就会变得很慢很慢。我们可以换一种思路:
>>> import numpy as np
>>> x = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
>>> v = np.array([1,0,1])
>>> vv = np.tile(v,(4,1))
>>> print(vv)
[[1 0 1]
[1 0 1]
[1 0 1]
[1 0 1]]
>>> y = x + vv
>>> print (y)
[[ 2 2 4]
[ 5 5 7]
[ 8 8 10]
[11 11 13]]
Numpy Broadcasting机制可以让我们不用创建vv,就能直接运算,看看下面例子:
>>> import numpy as np
>>> x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
>>> v = np.array([1, 0, 1])
>>> y = x + v
>>> print(y)
[[ 2 2 4]
[ 5 5 7]
[ 8 8 10]
[11 11 13]]
对两个数组使用Broadcasting机制要遵守下列规则:
(1)如果数组的秩不同,使用1来将秩较小的数组进行扩展,直到两个数组的尺寸的长度都一样。
(2)如果两个数组在某个维度上的长度是一样的,或者其中一个数组在该维度上长度为1,那么我们就说这两个数组在该维度上是相容的。
(3)如果两个数组在所有维度上都是相容的,他们就能使用Broadcasting。
(4)如果两个输入数组的尺寸不同,那么注意其中较大的那个尺寸。因为Broadcasting之后,两个数组的尺寸将和那个较大的尺寸一样。
(5)在任何一个维度上,如果一个数组的长度为1,另一个数组长度大于1,那么在该维度上,就好像是对第一个数组进行了复制。
如果上述解释看不明白,可以读一读文档和这个解释。
支持Broadcasting机制的函数是全局函数。哪些是全局函数可以在文档中查找。
下面是一些Broadcasting机制的使用:
>>> import numpy as np
>>> v = np.array([1,2,3])
>>> w = np.array([4,5])
>>> print(np.reshape(v,(3,1)))
[[1]
[2]
[3]]
>>> print(np.reshape(v,(3,1)) * w)
[[ 4 5]
[ 8 10]
[12 15]]
>>> x = np.array([[1,2,3], [4,5,6]])
>>> print(x + v)
[[2 4 6]
[5 7 9]]
>>> print((x.T + w).T)
[[ 5 6 7]
[ 9 10 11]]
>>> print(x + np.reshape(w, (2, 1)))
[[ 5 6 7]
[ 9 10 11]]
>>> print(x * 2)
[[ 2 4 6]
[ 8 10 12]]
Broadcasting机制能够让你的代码更简洁更迅速,能够用的时候请尽量使用!