Numpy科學計算庫 | 神經網絡與深度學習 | Tensorflow 2.0 系列 (4) | AI入門

多維陣列


在機器學習中,我們經常需要把輸入數據轉變為多維陣列(array)的形式,以下圖片解釋了陣列基本原理:

陣列的形狀(shape):描述了陣列的維度,以及各個維度內部的元素個數





建立NumPy陣列

NumPy:全稱為Numeic Python,提供了多維陣列、矩陣的常用操作和高效的科學計算函數
底層通過C語言建立,數據處理速度快、效率高,適用於大規模多維陣列

安裝NumPy

  • Anaconda: 預設安裝
  • pip安裝:pip install numpy

匯入Numpy

1
import numpy as np # 在調用Numpy中的函數時,需要加上前綴np
1
from numpy import * # 在調用Numpy函數時,可不加前綴

NumPy陣列

1
2
3
4
5
6
7
8
9
10
11
# array([陣列]/(元組))
>>>a = np.array([0,1,2,3])

>>>a
array([0,1,2,3])

>>>print(a)
[0,1,2,3]

>>>type(a)
<class 'numpy.ndarray'>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 輸出指定的陣列元素
>>>a[0]
0

>>>print(a[1],a[2],a[3])
1 2 3

>>>a[ 0:3 ]
array([0, 1, 2 ])

>>>a[ :3]
array([0, 1, 2 ])

>>>a[0: ]
array([0, 1, 2, 3])

1
2
3
4
5
6
7
8
9
10
11
12
13
# 陣列的屬性
>>>a = np.array([0,1,2,3])
>>>a
array([0, 1, 2,3])

>>>a.ndim # 陣列的維度
1

>>>a.shape # 陣列的形狀
(4,)

>>>a.size # 陣列中元素的總數
4

二維陣列

1
2
3
4
5
6
7
8
9
10
11
12
# 陣列的屬性
>>>b = np.array([[0,1,2,3],[4,5,6,7][8,9,10,11]])
>>>b
array([[0, 1, 2, 3], #b[0]
[4, 5, 6, 7], #b[1]
[8, 9, 10, 11]]) #b[2]

>>>b[0][1]
1

>>>b[0,1]
1

三維陣列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
>>>t = np.array([[[0,1,2,3],[4,5,6,7],[8,9,10,11],[12,13,14,15],[16,17,18,19,][20,21,22,23]]])

>>>t
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7], #t[0]
[ 8, 9, 10, 11]],

[[12, 13, 14, 15],
[16, 17, 18, 19], #t[2]
[20, 21, 22, 23]]])

>>>t.ndim
3
>>>t.shape
(2,3,4)
>>>t.size
24

>>>t[0].ndim
2
>>>t[0].shape
(3,4)
t[0].size
12

>>>t[0][0]
array([0,1,2,3])
>>>t[0][0].ndim
1
>>>t[0][0].shape
(4,)
>>>t[0][0].size
4
>>>t[0][0][0]
0
>>>t[0,0,0]
0

陣列元素的數據類型

Numpy要求陣列中所有元素的數據類型必須是一致的

1
2
3
4
5
6
7
8
9
10
11
12
# 陣列的屬性
>>>a = np.array([0,1,2,3], dtype = np.int64)
>>>a
array([0,1,2,3], dtype=int64)

>>>a.dtype
dtype('int64')
>>>a.itemsize
8 # 每個元素所佔的字節數
>>>c = np.array([1.2, 3.5, 5.1])
>>>c.dtype
dtype('float64') # 建立NumPy陣列時,數據類型會由原來的元素類型決定

建立特殊的陣列

  • arrange()函數:建立一個由數字序列組成的陣列

    1
    2
    3
    4
    5
    # np.arrange(初始數字, 結束數字, 步長, dtype) 「初始數字省略時,預設由0開始;步長省略時,預設為1;前閉後開:數字序列中不包括結束數字」
    >>>np.arrange(4)
    array([0, 1, 2, 3])
    >>>d = np.arrange(0, 2, 0,3)
    array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
  • ones()函數:建立一個元素全部為1的陣列

    1
    2
    3
    4
    5
    6
    7
    8
    9
    # np.ones(shape, dtype)
    >>>np.ones((3,2), dtype=np.int16)
    array([[1, 1],
    [1, 1],
    [1, 1]], dtype=int16)
    >>>np.ones((3,2)) # 當數據類型省略時,這裡仍然有2層括號
    array([[1., 1.],
    [1., 1.],
    [1., 1.]])

- zeros()函數:建立一個元素全部為0的陣列
1
2
3
4
# np.zeros(shape, dtype)
>>>np.zeros((2,3))
array([[0., 0., 0.],
[0., 0., 0.]])

- eye()函數:建立一個單位矩陣
1
2
3
4
5
6
7
8
9
# np.eye(shape, dtype)
>>>np.eye(3)
array([[1., 0., 0.],
[0., 1., 0.]
[0., 1., 0.]])

>>>np.eye(2,3)
array([[1., 0., 0.],
[0., 1., 0.]])

- linspace()函數:建立一個等差數列
1
2
3
# np.linspace(start, stop, num=50, dtype) 參數:初始數字、結束數字、元素數目、元素數據類型
>>>np.linsapce(1,6,6)
array([1., 2., 3., 4., 5., 6.])

- logspace()函數:建立一個等比數列
1
2
3
# np.logspace(start, stop, num=50, base=10, dtype) 參數:初始數字、結束數字、元素數目、底、元素數據類型
>>>np.logspace(1,5,5, base=2)
array([2., 4., 8., 16., 32.])

- asaarray()函數:將串列或元組轉化為陣列物件
1
2
3
4
5
6
7
8
9
10
11
import numpy as np

list1 = [[1,1,1],[1,1,1],[1,1,1]]
arr1 = np.array(list1)
arr2 = np.asaart(list1)

list1[0][0] = 3

print('list1:\n',list1)
print('arr1:\n',arr1)
print('arr2:\n',arr2)

執行結果:
1
2
3
4
5
6
7
8
9
10
list1:
[[3, 1, 1], [1, 1, 1], [1, 1, 1]]
arr1:
[[1 1 1]
[1 1 1]
[1 1 1]]
arr2:
[[1 1 1]
[1 1 1]
[1 1 1]]

當源數據本身是一個ndarray物件時,array()會複製出一個副本,佔用新的記憶體,而asarray()則不複製副本,它會直接飲用原陣列
1
2
3
4
5
6
7
8
9
10
11
import numpy as np

arr1 = np.ones((3,3))
arr1 = np.array(arr1)
arr2 = np.asaart(arr1)

list1[0][0] = 3

print('arr1:\n',arr1)
print('arr2:\n',arr2)
print('arr3:\n',arr3)

執行結果:
1
2
3
4
5
6
7
8
9
10
11
12
arr1:
[[3. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
arr2:
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
arr3:
[[3. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]

陣列運算


陣列元素的切片

可以使用切片來訪問NumPy陣列中的一部分,切片方法和Python序列數據結構的切片一樣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 一維陣列
>>>a = np.array([0,1,2,3])
>>>a[ 0:3 ]
array([ 0, 1, 2 ])
>>>a[ :3]
array([ 0, 1, 2 ])
>>>a[0: ]
array([ 0, 1, 2, 3 ])

# 二維陣列
>>>b = np.array([[0,1,2,3][4,5,6,7],[8,9,10,11]])
>>>b
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>>b[0]
array([0,1,2,3])
>>>b[0:2]
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
>>>b[:2]
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
>>>b[0:2, 0:2]
array([[0, 1],
[4, 5]])
>>>b[:,0]
array([0, 4, 8])

改變陣列的形狀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>>b = np.arrange(12)
>>>b
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])

# np.reshape(shape) -> 不改變當前陣列,按照shape建立新的陣列
>>>b.reshape(3,4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>>b
array([ 0,1,2,3,4,5,6,7,8,9,10,11])

>>>a = np.arrange(12)
>>>a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
# np.resize(shape) -> 改變當前陣列,按照shape建立陣列
>>>a.resize(3,4)
>>>array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])

陣列之間的運算

1
2
3
4
>>> a = np.array([0,1,2,3])
>>> d = np.array([2,3,4,5])
>>> a+d
array([[ 2, 4, 6, 8]]) # 相加的2個陣列形狀和長度需要一致,否則就會出現錯誤

陣列之間的減法、乘法、除法運算,和加法運算規則相同 當兩個陣列中元素的數據類型不同時,準確度低的數據類型會自動傳喚成較高的數據類型
1
2
3
4
5
6
7
8
9
10
11
# 一維陣列可以和多維陣列相加,相加時會將一維陣列擴展至多維
>>>a = np.array([0,1,2,3])
>>>b = np.array([[0,1,2,3],[4,5,6,7],[8,9,10,11]])
>>> a+b
array([[ 0, 2, 4, 6]
[ 4, 6, 8, 10]
[ 8, 10, 12, 14]])
>>>b ** 2
array([[ 0, 1, 4, 9]
[ 16, 25, 36, 49]
[ 64, 81, 100, 121]])

矩陣運算

矩陣乘法:
1)乘號運算符號:矩陣中對應的元素分別相乘

1
2
3
4
5
6
>>>A = np.array([[1,1],[0,1]])
>>>B = np.array([[2,0],[3,4]])
>>>C = A * B
>>>C
array([2, 0],
[0, 4])

2)矩陣相乘:按照矩陣相乘的規則運算
1
2
3
4
5
6
>>>np.matmul(A,B)
array([[5, 4],
[3, 4]])
>>>np.dot(A,B)
array([[5, 4],
[3, 4]])

轉置矩陣:
1
2
3
4
5
6
>>>np.transpose(A)
array([[1, 0],
[1, 1]])
>>>np.transpose(B)
array([[2, 3],
[0, 4]])

逆矩陣:
1
2
3
4
5
6
>>>np.linalg.inv(A)
array([[ 1., -1.],
[ 0., 1.]])
>>>np.linalg.inv(B)
array([[ 0.5 , 0. ],
[ -0.375, 0.25 ]])

陣列元素之間的運算

numpy.sum() -> 計算所有元素的和
numpy.produ() -> 計算所有元素的積
numpy.diff() -> 計算陣列的相鄰元素之間的差
np.sqrt() -> 計算各元素的開方根
np.exp() -> 計算各元素的指數值
np.abs() -> 取得各元素的絕對值

1
2
3
4
>>>a = np.arrange(4)
array([0, 1, 2, 3])
>>>np.sum(a)
6

以行求和&以列求和

  • axes:陣列中每個維度被稱為一個axes軸
  • rank:axes的個數
  • 一維陣列 (rank = 1)
  • 二維陣列 (rank = 2)
  • 三維陣列 (rank = 3)

陣列堆疊運算

1
2
3
4
5
6
7
8
9
10
11
>>>x = np.array([1, 2, 3]) # 新增一維陣列x
>>>y = np.array([4, 5, 6]) # 新增一維陣列y

>>>np.stack((x, y), axis=0) # 在axis=0上進行堆疊
array([[1, 2, 3],
[4, 5 ,6]])

>>>np.stack((x, y), axis=1) # 在axis=1上進行堆疊
array([[1,4],
[2,5],
[3,6]])

矩陣 - numpy.matrix

  • matrix(字符串/串列/元組/陣列)
  • mat(字符串/串列/元組/陣列)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    >>>a = np.mat(' 1 2 3 ; 4 5 6 ') # 參數為字符串
    >>>a
    matrix([[1, 2, 3],
    [4, 5, 6]])

    >>>b = np.mat([[1, 2, 3],[4, 5, 6]]) # 參數為Python串列
    >>>b
    matrix([[1, 2, 3],
    [4, 5, 6]])

使用NumPy二維陣列創建矩陣

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
>>>a = np.array([[1,2,3],[4,5,6]])
>>>a
>>>array([[1,2,3],
[4,5,6]])

>>>m = np.mat(a)
>>>m
matrix([[1, 2, 3],
[4, 5, 5]])

>>>type(a)
<class 'numpy.ndarray'>
>>>type(m)
<class 'numpy.matrix'>

>>>m.ndim
2
>>>m.shape
(2, 3)
>>>m.size
6
>>>m.dtype
dtype( 'int32' )

矩陣相乘

1
2
3
4
5
6
>>>a1 = np.mat([[0,1],[2,3]])
>>>a2 = np.mat([[1,1],[2,0]])
>>>a3 = a1 * a2
>>>a3
matrix([[ 2, 0],
[ 8, 2]])

### 轉置矩陣及逆矩陣 轉置矩陣: .T 逆矩陣 .I
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>>>a1 = np.mat([[1,2],[-1,-3]])
>>>n
matrix([[ 1, 2],
[-1, -3]])

>>>n.T
matrix([[ 1, -1],
[ 2, -3]])

>>>n.I
matrix([[ 3, 2],
[-1, -1]])

>>>n*n.I # 一個矩陣乘以它的逆=單位陣
matrix([[ 1, 0],
[ 0, 1]])

矩陣vs二維陣列

陣列:運算符號簡單(A * B)
二微陣列:能夠表示高維陣列,陣列更加靈活,速度更快

隨機數

隨機數模組 —— numpy.random
np.random.rand(d0,d1…,dn) -> 元素在(0,1)區之間均勻分佈的陣列「浮點數」
np.random.uniform(low,hige, size) -> 元素在[low,high]之間均勻分佈的陣列「浮點數」
numpy.random.randint(low,hige, size) -> 元素在[low,high]之間均勻分佈的陣列「整數」
np.random.randn(d0,d1,…,dn) -> 產生標準正態分佈的陣列「浮點數」
np.random.normal(loc, scale, size) -> 產生正態分佈的陣列「浮點數」

產生隨機數

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
>>>np.random.rand(2,3)
array([[ 0.84543047, 0.76450077, 0.87173984],
[ 0.01204357, 0.1531674 , 0.67527698]])

# 參數為空,返回一個數字
>>>np.random.rand()
0.289648133266711

# 新增3*2的隨機陣列,取值在1至5之間均勻分佈的浮點數
>>>np.random.uniform(1,5,(3,2))
array([[ 2.6034975 , 1.12862773],
[ 3.24128894, 4,97185042],
[ 2.77097208, 1.48494326]])

# 新增3*2的隨機陣列,取值在1至5之間均勻分佈的整數
>>>np.random.randint(1,5,(3,2))
array([2,2],
[4,1],
[4,2])

# 新增2*3的隨機陣列,符合標準正態分佈
>>>np.random.randn(2,3)
array([[-0.94594743, -1.10163142, -0.40212785],
[-1.04332498, -1.35958875, 1.5320874 ]])

# 新增3*2的隨機陣列,符合真態分佈,均值為0,方差為1
>>>np.random.normal(0,1,(3,2))
array([[ 1.48764022, -1.52437091],
[ 0.73473077, 1.51170983],
[-0.99776822, -0.89273968]])

# 新增2*3的隨機陣列,符合標準正態分佈
>>>np.random.normal(2,3)
array([[-0.94594743, -1.10163142, -0.40212785],
[-1.04332498, -1.35958875, 1.5320874 ]])

# 新增3*2的隨機陣列,符合正態分佈,均值為0,方差為1
>>>np.random.normal(0,1,(3,2))
array([[ 1.48764022, -1.52437091],
[ 0.73473077, 1.51170983],
[-0.99776822, -0.89273968]])

隨機種子介紹

由於是隨機數,即使你和我使用同樣的語句,大家所得到的結果也是不同的。
以下將會介紹 seed()函數,使得每次生成的隨機數都相同。

  • 偽隨機數:由隨機種子,根據一定的算法生成
  • 隨機種子:指定隨機數生成時所用算法開始的整數值
    1)如果使用相同的seed()值,則每次生成的隨機數都相同
    2)如果不設定這個值,則系統根據時間來自行選擇這個值,此時每次生成的隨機數因時間差異而不同
    3)設定的seed()值僅一次有效
    4)隨機數產生的算法,和電腦本身的作業系統有關

seed() —— 設定隨機種子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>>>np.random.seed(612) 
>>>np.random.rand(2,3)
array([[0.14347163, 0.49589878, 0.95454587],
[0.13751674, 0.85456667, 0.43853136]])

# 採用seed()設定隨機種子,產生了相同的隨機數
>>>np.random.seed(612)
>>>np.random.rand(2,3)
array([[0.14347163, 0.49589878, 0.95454587],
[0.13751674, 0.85456667, 0.43853136]])

# 沒有設定隨機種子,產生了不一樣的結果
>>>np.random.rand(2,3)
array([[0.27646426, 0.80187218, 0.95813935],
[0.87593264, 0.35781727, 0.500995213]])

shuffle()函數 —— 打亂順序

1
2
3
4
5
6
7
>>>arr = np.arrange(10)
>>>print(arr)
[0 1 2 3 4 5 6 7 8 9]

>>>np.random.shuffle(arr)
>>>print(arr)
[1 7 5 2 9 4 3 6 0 8]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 對於多維陣列,使用shuffle()函數只打亂第一維元素
>>>b = np.arrange(12).reshape(4,3)
>>>b
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9,10,11]])

>>>np.random.shuffle(b)
>>>b
array([[ 3, 4, 5],
[ 9,10,11],
[ 6, 7, 8],
[ 0, 1, 2]])
文章作者: icthk
文章鏈接: https://icthk.github.io/11_Tensorflow2_Numpy.html
版權聲明: 本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 ICTHK Blog