cs231n---Python Numpy教程(第二弹)

Numpy库:它提供了高性能的多维数组对象,以及相关工具。

数组array

一个numpy数组是一个由不同数值组成的网格。网格中的数据都是同一种数据类型,可以通过非负整型数的元组来访问。

维度的数量成为数组的。数组大小是一个由整型数构成的元组,可以描述数组不同维度上的大小。

从列表创建数组,利用方括号[]访问其中元素:

# 数组array
import numpy as np

a = np.array([1, 2, 3])# creat a rank 1 array  1阶数组
print(a) # [1 2 3]
print(type(a)) # <class 'numpy.ndarray'>
print(a.shape) # (3,)
print(a[0], a[1], a[2])  # 1 2 3
a[0] = 5
print(a)  # [5 2 3]

b = np.array([[1,2,3],[4,5,6]])# creat a rank 2 array  2阶数组
print(b)
# [[1 2 3]
#  [4 5 6]]
print(b.shape)  # (2, 3)
print(b[0,0], b[0,1], b[1,0])  # 1 2 4

Numpy还提供了其他创建数组的方法:

import numpy as np

a = np.zeros((2,2))  # 生成全为0的数组array
print(a)
# [[ 0.  0.]
#  [ 0.  0.]]

b = np.ones((1,2))  # 生成全为1的数组array
print(b)
# [[ 1.  1.]]

c = np.full((2,2), 8) # 常数均为8的2x2数组
print(c)
# [[8 8]
#  [8 8]]

d = np.eye(2)  # 单位矩阵identity matrix
print(d)
# [[ 1.  0.]
#  [ 0.  1.]]

e = np.random.random((2,2))
print(e)
# [[ 0.46699318  0.2937788 ]
#  [ 0.35273887  0.30353399]]

访问数组

切片:与python列表类似,numpy数组可以使用切片语法。而数组是多维的,所以必须为每个维度指定好切片。

# 创建一个2维3x4的数组 create the following rank 2 array with shape (3, 4)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])

# 使用切片选出行索引2前(不包含2)即index=0,1,第一行第二行
# 选择出索引1,2(不包含3)即第二,三列
# [[2 3]
#  [6 7]]
b = a[:2, 1:3]

print(a[0,1])  # 2

b[0,0] = 88  # b[0,0]等价于a[0,1]:b[0,0] is the same piece of data as a[0,1]
print(a)
# [[ 1 88  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
print(a[0,1])  # 88

可以同时使用整型和切片语法来访问数组,但,这样会产生一个比原数组低阶的新数组。

a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])

row_r1 = a[1, :]
row_r2 = a[1:2, :]
print(row_r1, row_r1.shape) # [5 6 7 8] (4,)
print(row_r2, row_r2.shape) # [[5 6 7 8]] (1, 4)

col_r1 = a[:, 1]
col_r2 = a[:, 1:2]
print(col_r1, col_r1.shape) # [ 2  6 10] (3,)
print(col_r2, col_r2.shape) 
# [[ 2]
#  [ 6]
#  [10]] (3, 1)
整型数组访问:使用切片语法访问数组时,得到的总是原数组的一个子集。整型数组访问我们利用其它数组的数据构建一个新的数组:
import numpy as np
a = np.array([[1,2], [3,4], [5,6]])
# [[1 2]
#  [3 4]
#  [5 6]]

# 整型数组访问
print(a[[0,1,2], [0,1,0]])  # [1 4 5]
#等价于
print(np.array([a[0,0], a[1,1], a[2,0]]))

print(a[[0,0], [1,1]]) # [2 2]
# 等价于
print(np.array([a[0,1], a[0,1]]))

整型数组还可以选择或更改矩阵中每行的一个元素:

import numpy as np

a = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]])
print(a)
# [[ 1  2  3]
#  [ 4  5  6]
#  [ 7  8  9]
#  [10 11 12]]
b = np.array([0,2,0,1]) # 创建一个数组索引

# 选取每行对应b中索引的元素
print(np.arange(4)) # [0 1 2 3]
print(a[np.arange(4), b]) # [ 1  6  7 11]

a[np.arange(4), b] += 10
print(a)
# [[11  2  3]
#  [ 4  5 16]
#  [17  8  9]
#  [10 21 12]]
布尔型数组访问:布尔型数组访问可以选择数组中任意元素。通常,这种访问方式用于选取数组中满足某些条件的元素:
# 布尔型数组访问
import numpy as np


a = np.array([[1, 2], [3, 4], [5, 6]])


bool_idx = (a > 2) # 找到数组a中比2大的元素
print(bool_idx)
# [[False False]
#  [ True  True]
#  [ True  True]]


print(a[bool_idx])
# [3 4 5 6]


print(a[a > 2])  # [3 4 5 6]

数据类型

每个numpy数组都是数据类型相同的元素组成的网格。当创建数组时,numpy会猜测数组的数据类型,我们可以通过参数直接指定数据:

# 数据类型
import numpy as np

x = np.array([1, 2])
print(x.dtype)

x = np.array([1.0, 2.0])
print(x.dtype)

# x = np.array([1, 2], dtype=np.int64)
# print(x.dtype) # for python2 is ok,but python3 is false

数组计算

基本数学计算函数会对数组中的元素逐个进行计算,既可以利用操作符重载,也可以使用函数方式:

# 数组计算
import numpy as np

x = np.array([[1,2], [3,4]])
y = np.array([[5,6], [7,8]])

print(x + y)
print(np.add(x, y))
# [[ 6  8]
#  [10 12]]

print(x - y)
print(np.subtract(x, y))
# [[-4 -4]
#  [-4 -4]]

print(x * y)
print(np.multiply(x, y))
# [[ 5 12]
#  [21 32]]

print(x / y)
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))
print(np.dot(v, w))
# 219

print(x.dot(v))
print(np.dot(x, v))
# [29 67]

print(x.dot(y))
print(np.dot(x, y))
# [[19 22]
#  [43 50]]

numpy提供了很多计算数组的函数,其中最常用的一个是sum:

# sum函数
import numpy as np

x = np.array([[1,2], [3,4]])
# [[1 2]
#  [3 4]]

print(np.sum(x)) # 10 即数组中所有元素之和
print(np.sum(x, axis=0)) # [4 6] 数组中每列(axis=0)元素相加
print(np.sum(x, axis=1)) # [3 7] 数组中每行(axis=1)元素相加
除了计算,还需改变数组或者操作其中的元素。其中numpy中用 T 将矩阵转置
# 转置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]]

v = np.array([1,2,3]) # 对一维数组不起作用
print(v) # [1 2 3]
print(v.T) # [1 2 3]

广播broadcasting

广播是一种强有力的机制,它使Numpy可以让不同大小的矩阵在一起进行数学计算。我们常会有一个小的矩阵和一个大的矩阵,然后需要用小的矩阵对大的矩阵做一些计算。

# baseline for循环
import numpy as np

# We will add the vector v to each row of the matrix x, 
# storing the result in the matrix y
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) # 创建一个空矩阵大小和x一样 create an empty matrix with the same shape as x
print(y)
# [[0 0 0]
#  [0 0 0]
#  [0 0 0]
#  [0 0 0]]

# Add the vector v to each row of the matrix x with an explicit  
for i in range(4):
    y[i, :] = x[i, :] + v

print(y)
# [[ 2  2  4]
#  [ 5  5  7]
#  [ 8  8 10]
#  [11 11 13]]

以上是baseline,但是当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))  # Stack 4 copies of v on top of each other 拓展
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广播机制可以让我们不用创建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]]

对两个数组使用广播机制要遵守下列规则:

  1. 如果数组的秩不同,使用1来将秩较小的数组进行扩展,直到两个数组的尺寸的长度都一样。
  2. 如果两个数组在某个维度上的长度是一样的,或者其中一个数组在该维度上长度为1,那么我们就说这两个数组在该维度上是相容的。
  3. 如果两个数组在所有维度上都是相容的,他们就能使用广播。
  4. 如果两个输入数组的尺寸不同,那么注意其中较大的那个尺寸。因为广播之后,两个数组的尺寸将和那个较大的尺寸一样。
  5. 在任何一个维度上,如果一个数组的长度为1,另一个数组长度大于1,那么在该维度上,就好像是对第一个数组进行了复制。

如果上述解释看不明白,可以读一读文档和这个解释译者注:强烈推荐阅读文档中的例子。

下面是一些广播机制的使用:

# examples
import numpy as np

v = np.array([1,2,3]) # v has shape (3,)

w = np.array([4,5]) # w has shape (2,)
# To compute an outer product, we first reshape v to be a column
# vector of shape (3, 1); we can then broadcast it against w to yield

print(np.reshape(v, (3, 1))) # 变成3行一列
# [[1]
#  [2]
#  [3]]

# an output of shape (3, 2), which is the outer product of v and w:
print(np.reshape(v, (3, 1)) * w)
# [[ 4  5]
#  [ 8 10]
#  [12 15]]

x = np.array([[1,2,3], 
              [4,5,6]])

print(x * 2)
# [[ 2  4  6]
#  [ 8 10 12]]

print(x + v)
# [[2 4 6]
#  [5 7 9]]

print(x.T)
# [[1 4]
#  [2 5]
#  [3 6]]

print((x.T + w).T)
# [[ 5  6  7]
#  [ 9 10 11]]

print(np.reshape(w, (2,1))) 
# [[4]
#  [5]]

print(x + np.reshape(w, (2,1)))
# [[ 5  6  7]
#  [ 9 10 11]]

Numpy文档

这篇教程涉及了你需要了解的numpy中的一些重要内容,但是numpy远不止如此。可以查阅numpy文献来学习更多。

以上内容转载整理来自知乎专栏点击打开链接,侵删侵删。







  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值