Hike News
Hike News

Python機器學習-numpy

introduction

  • 對一份大型的數據來說,是由多筆樣本所構成的

    • 列(column)通常為樣本的指標或是特徵(feature)
    • 行(row)則代表一筆含有多項特徵的資料集合
  • 綜合以上,以矩陣形式表示資料會更為直觀

    • 計算方便
    • 計算效率高
  • numpy庫可用於矩陣計算


導入numpy Library

1
import numpy as np

產生陣列(array)

從列表(list)產生陣列

將列表類型轉換為numpy.ndarray以創建陣列

1
2
3
data = [1,2,3,4,5]
arr = np.array(data)
arr

亦可直接填入list
1
2
arr = np.array([1,2,3,4,5])
arr

result
1
array([1, 2, 3, 4, 5])

查看類型

1
type(arr)

result
1
numpy.ndarray

  • 類型為numpy.ndarray

arrange產生陣列

產生int陣列

1
np.arange(10)

result
1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

產生float陣列

1
np.arange(10.0)

result
1
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

步進產生陣列
example 1:

1
np.arange(10,30,5)

  • 從10開始,每+5產生值到30停止,但不包含30

result

1
array([10, 15, 20, 25])

example 2:

1
np.aarange(0,2,0.3)

result

1
array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])


linspace產生1D陣列

得到特定範圍內指定個數元素的陣列

1
2
from numpy import pi
np.linspace(0,2*pi,6)

  • 產生從0開始到2pi(包含2pi),分成6等份的一維陣列
  • 若未指定分成多少等份,預設為50等份,即(start,inclusive stop,50)

result

1
2
array([0.        , 1.25663706, 2.51327412, 3.76991118, 5.02654825,
6.28318531])

logspace產生1D陣列

得到10的start次方到10的inclusive stop次方的陣列

1
np.logspace(0, 3, 8)         # 10^0 to 10^3 (inclusive) with 8 points

result

1
2
array([   1.        ,    2.6826958 ,    7.19685673,   19.30697729,
51.79474679, 138.94954944, 372.75937203, 1000. ])


創建二維(2D)矩陣

搭配range()創建2D array

1
2
3
data2 = [range(1, 5), range(5, 9)]        # list of lists
arr2 = np.array(data2) # 2d array
arr2

直接填入嵌套的list創建

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

result

1
2
array([[1, 2, 3, 4],
[5, 6, 7, 8]])


將矩陣轉為列表類型

  • numpy.ndrray轉為list
    1
    2
    a = arr2.tolist()       # convert array back to list
    type(a)
    result
    1
    list

陣列檢查

查看矩陣存放的類型(dtype)

在創建矩陣時不像list,各元素之間可為不同類型,
矩陣中的元素必須為同一類型

1
2
arr_test = np.array([1,2,3,4,5])
arr_test.dtype

result

1
dtype('int64')

只要其中一個元素類型不一樣,
為了滿足其中一個元素的類型,會將其他元素轉換為更泛用的類型

example 1:

1
2
arr_test = np.array([1,2,3,4,5.0])
arr_test.dtype

result
1
dtype('float64')

example 2:

1
2
arr_test = np.array([1,2,3,'4',5.0])
arr_test.dtype

result
1
dtype('<\U21')


查看矩陣的結構(shape)

常用於debug

2D array

1
arr2.shape
  • shape返回一個tuple,為(row, column)形式

result

1
(2, 4)

1D array

1
arr.shape

result

1
(5,)


查看矩陣維度(ndim)

1
2
print(arr.ndim)
print(arr2.ndim)

result

1
2
1
2


查看矩陣的元素總數(size)

1
2
print(arr.size)
print(arr2.size)

result

1
2
5
8


矩陣的選取(切片slicing)

透過索引(index)選取特定範圍內的陣列

語法

與list切片的方法一樣,只是不同維度需用逗號(,)隔開
start (= 0) : stop (= last) :step (= 1)

取特定行

example 1:

1
2
arr = np.array([range(1,4),range(4,7),range(7,10)])
arr[0, :]

result
1
array([1, 2, 3])

example 2:

1
arr[0:2, :]

result
1
2
array([[1, 2, 3],
[4, 5, 6]])

取特定列

example 1:

1
arr[:, 0]

result
1
array([1, 4, 7])

  • 單取一列值時,返回為1d-array

example 2:

1
arr[:, 1:]

result
1
2
3
array([[2, 3],
[5, 6],
[8, 9]])

取特定範圍

1
arr[0:2, 0:2]

result

1
2
array([[1, 2],
[4, 5]])

取特定值

1
2
val = arr[2:2]
val
  • 其等同於arr[2][2],先取行在取列
    result
    1
    9

修改特定值

1
2
arr[1:1] = 100
arr
  • 其等同於arr[1][1] = 100,先取行在取列
    result
    1
    2
    3
    array([[  1,   2,   3],
    [ 4, 100, 6],
    [ 7, 8, 9]])

矩陣的邏輯運算

普通邏輯運算

進行普通邏輯運算時會對陣列中的每一個元素都進行計算,並返回一個bool類型的陣列(不需使用for循環進行運算)
example 1:

1
2
matrix = np.array([range(1,4),range(4,7),range(7,10)])
matrix > 5

result
1
2
3
array([[False, False, False],
[False, False, True],
[ True, True, True]])

example 2:

1
matrix == 9

result
1
2
3
array([[False, False, False],
[False, False, False],
[False, False, True]])

返回為True的值

example 1:

1
2
3
arr_bool = np.array([False,True,False])
arr_int = np.array([1,2,3])
arr_int[arr_bool] # 將arr_bool當作index,傳入arr_int中計算

result
1
array([2])

example 2:

1
2
3
4
matrix = np.array([[5,15,20],[20,25,30],[35,40,45]])
second_col_25 = matrix[1, :] == 25
print(second_col_25)
matrix[second_col_25] # 從matrix中查找符合此bool矩陣的row之值

result
1
2
3
[False  True False]

array([[20, 25, 30]])

  • 結果為matrix[1,:]

與或運算

example 1:

1
2
matrix = np.array([[5,15,20],[20,25,30],[35,40,45]])
(matrix > 25) & (matrix < 50)

  • 務必加上括號()

result

1
2
3
array([[False, False, False],
[False, False, True],
[ True, True, True]])

example 2:

1
(matrix > 25) | (matrix < 10)

result
1
2
3
array([[ True, False, False],
[False, False, True],
[ True, True, True]])

判斷有無非數字值(isnan)

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

result

1
array([False, False, False, False, False,  True])


矩陣的運算

減法

1
2
3
4
a = np.array([10,20,30,40,50])
b = np.arange(5)
print(a-b)
print(b-1)

result

1
2
3
[10 19 28 37 46]
[-1 0 1 2 3]

  • 對應位置相減

求次方

1
2
b = np.arrane(5)
b**2

result

1
array([ 0,  1,  4,  9, 16])

矩陣乘法

使用*則對應位置元素相乘

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

result
1
2
array([[2, 0],
[0, 4]])

使用dot求積

1
2
print(A.dot(B))
print(np.dot(A,B))

  • 兩個效果是一樣的
    result
    1
    2
    3
    4
    5
    [[5 4]
    [3 4]]

    [[5 4]
    [3 4]]

變換矩陣存儲的類型(astype)

透過astype()將矩陣原類型,轉換為其他類型

1
2
3
4
5
str_matrix = np.array([['1','2','3']]) 
print(str_matrix.dtype)
int_matrix = str_matrix.astype(int)
print(int_matrix.dtype)
int_matrix

result
1
2
3
4
<\U1
int64

array([[1, 2, 3]])


矩陣的內置屬性

求最小值(min)

1
2
IntVector = np.array([1,2,3,4,5,6,7,8,9])
IntVector.min()

result

1
1

求最大值(max)

1
2
IntVector = np.array([1,2,3,4,5,6,7,8,9])
IntVector.max()

result

1
9

比較同座標值之大小(maximum,minimum)

1
2
nums = np.arange(5)
np.maximum(nums, np.array([1, -2, 3, -4, 5])) # compare element-wise
  • maximum返回較大的值之矩陣,minimum返回較小值之矩陣

result

1
array([1, 1, 3, 3, 5])

求極值(最大值,最小值)的索引(argmax,argmin)

1
2
3
a = np.floor(10*np.random.random((3,4)))
print(a)
a.argmax(axis = 1)
  • axis=1為求每一行(row)最大值的索引,axis=0為求每一列(column),不加則是全部運算取一返回值

result

1
2
3
4
5
[[8. 8. 8. 4.]
[5. 2. 7. 3.]
[8. 9. 5. 6.]]

array([0, 2, 1])

求和(sum)

example 1:

1
2
IntMatrix = np.array([range(1,4),range(4,7),range(7,10)])
IntMatrix.sum(axis = 0)

  • axis = 0 代表 求每一列(column)之總和,不加怎是全部元素求和

result

1
array([12, 15, 18])

example 2:

1
2
IntMatrix = np.array([range(1,4),range(4,7),range(7,10)])
IntMatrix.sum(axis = 1)

  • axis = 1 代表 求每一行(row)之總和

result

1
array([ 6, 15, 24])

求集合(unique)

陣列中不會有重複的元素,相當於set()

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

result

1
array([1, 2, 3, 4, 5, 6, 7, 8])


向量(vector)與矩陣(matrix)的轉換

使用reshape將向量轉為矩陣

1
2
3
matrix = np.arange(15)
matrix.reshape(3,5)
matrix
  • 在reshape過程中,元素數量為一固定值,因此確定了3行必定為5列,
    亦可寫成reshape(3,-1)

result

1
2
3
array([[ 0,  1,  2,  3,  4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])

shape賦值將向量轉為矩陣

1
2
3
matrix = np.arange(15)
matrix.shape = (3,-1)
matrix

result

1
2
3
array([[ 0,  1,  2,  3,  4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])


將矩陣拉成一向量

ravel

1
2
3
4
matrix =np.array([[5, 7, 1, 3],
[7, 8, 9, 4],
[8, 8, 7, 0]])
matrix.ravel()

result

1
array([5, 7, 1, 3, 7, 8, 9, 4, 8, 8, 7, 0])

  • ravel產生的陣列仍指向原矩陣,操作其值,原矩陣亦會發生改變

flatten

1
2
3
4
5
matrix =np.array([[5, 7, 1, 3],
[7, 8, 9, 4],
[8, 8, 7, 0]])
a = matrix.flatten() # flatten 回傳一個原始的陣列複本 (a flat copy)
a

result

1
array([5, 7, 1, 3, 7, 8, 9, 4, 8, 8, 7, 0])

  • flatten產生的陣列為一復本,操作其值,原矩陣不會發生改變

使用np.newaxis

將平行向量轉換為垂直向量

1
2
3
a = np.array([0, 1, 2, 3])  
a_col = a[:, np.newaxis] # same as a_col = a[:, None]
a_col

result

1
2
3
4
array([[0],
[1],
[2],
[3]])


初始化矩陣

zeros

初始化一個元素皆為0的矩陣(參數為一tuple)

1
np.zeros((3, 4),dtype=np.int32)

  • dtype可決定存放的類型(亦可不設置,默認為float64)

result

1
2
3
array([[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]], dtype=int32)

ones

初始化一個元素皆為1的矩陣(參數為一tuple)

1
np.ones((2,3,4),dtype=np.int8)

result

1
2
3
4
5
6
7
array([[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]],

[[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]]], dtype=int8)

random

初始化一個元素為0至1之間隨機浮點數的矩陣(參數為一tuple)

1
np.random.random((2,3))

result
1
2
array([[0.78248299, 0.52270045, 0.0945345 ],
[0.30580916, 0.31472853, 0.34269623]])


numpy開啟格式化文件(genfromtxt)

  • 使用numpy.genfromtxt()讀取格式化的數據
    1
    np.genfromtxt("student_score.txt",delimiter=',',dtype=str)
  • 參數1:指定文件路徑
  • delimiter : 指定分隔符(文件中元素之間的分隔符)
  • dtype : 以何種類型將文件讀入(大部分用str方式讀入再去轉換成其他類型)
1
2
3
4
5
array([['Amy', '1001', '18', '95.0'],
['Tom', '1002', '20', '89.5'],
['John', '1003', '21', '77.8'],
['Tony', '1004', '23', '99.0'],
['Lucy', '1005', '19', '88.6']], dtype='<U4')
  • 讀入為一矩陣
1
2
stu_info = np.genfromtxt("student_score.txt",delimiter=',',dtype=str)
type(stu_info)
1
numpy.ndarray
  • 為numpy.ndarray類型

其他操作

指數函數(exp)

1
2
B = np.arange(3)
np.exp(B)

result

1
array([1.        , 2.71828183, 7.3890561 ])

開根號(sqrt)

1
np.sqrt(B)

result

1
array([0.        , 1.        , 1.41421356])

無條件捨去取整(floor)

將矩陣內元素的小數位皆丟棄,只留下整數位的數

1
2
3
A = np.random.random((3,4))*10
print(A)
print(np.floor(A))

result

1
2
3
4
5
6
7
[[4.79808472 2.44399243 5.548923   6.92783862]
[2.83681077 4.38694273 8.19855738 4.97988545]
[1.04608979 1.0399803 2.22577406 7.76268637]]

[[4. 2. 5. 6.]
[2. 4. 8. 4.]
[1. 1. 2. 7.]]

無條件進位取整(ceil)

將矩陣內元素的小數位皆進位,只留下整數位的數

1
2
3
A = np.random.random((3,4))*10
print(A)
print(np.ceil(A))

result

1
2
3
4
5
6
7
[[1.9360702  1.05170707 5.41654963 7.97196499]
[8.12826589 7.20266718 8.15762529 5.84988628]
[4.32137618 9.08694857 1.05489433 6.37825292]]

[[ 2. 2. 6. 8.]
[ 9. 8. 9. 6.]
[ 5. 10. 2. 7.]]

轉置矩陣(T)

1
2
3
matrix =np.array([[9., 3., 8., 0., 6., 9.],
[4., 1., 4., 3., 8., 3.]])
matrix.T

result

1
2
3
4
5
6
array([[9., 4.],
[3., 1.],
[8., 4.],
[0., 3.],
[6., 8.],
[9., 3.]])

擴展矩陣(tile)

定義一個矩陣,以此矩陣為單元擴展成自己需要的維度

1
2
3
a = np.arange(1,3)
b = np.tile(a,(2,2))
b

result
1
2
array([[1, 2, 1, 2],
[1, 2, 1, 2]])


矩陣疊加

平行疊加(hstack)

增加特徵數

1
2
3
4
5
a = np.floor(10*np.random.random((2,2)))
b = np.floor(10*np.random.random((2,2)))
print(a)
print(b)
print(np.hstack((a,b)))

result

1
2
3
4
5
6
7
8
[[1. 3.]
[8. 6.]]

[[1. 4.]
[3. 7.]]

[[1. 3. 1. 4.]
[8. 6. 3. 7.]]

垂直疊加(vstack)

增加樣本數

1
2
3
4
5
a = np.floor(10*np.random.random((2,2)))
b = np.floor(10*np.random.random((2,2)))
print(a)
print(b)
print(np.vstack((a,b)))

result
1
2
3
4
5
6
7
8
9
10
[[2. 1.]
[8. 0.]]

[[5. 5.]
[3. 7.]]

[[2. 1.]
[8. 0.]
[5. 5.]
[3. 7.]]

多維疊加(stack)

  • 兩個一維的矩陣疊加為二維矩陣
  • 兩個二維的矩陣疊加為三維矩陣
    1
    2
    3
    4
    5
    a = np.floor(10*np.random.random((2,2)))
    b = np.floor(10*np.random.random((2,2)))
    print(a)
    print(b)
    np.stack((a,b))

result

1
2
3
4
5
6
7
8
9
10
11
[[7. 7.]
[3. 3.]]

[[4. 4.]
[4. 9.]]

[[[7. 7.]
[3. 3.]]

[[4. 4.]
[4. 9.]]]


矩陣切分(split)

平行切分(np.hsplit)

第二參數為一整數

1
2
3
a = np.floor(10*np.random.random((2,12)))
print(a)
print(np.hsplit(a,3))

  • 將a平行切分成3等份

result

1
2
3
4
5
6
7
8
9
[[1. 5. 8. 1. 3. 1. 9. 4. 3. 8. 8. 9.]
[2. 8. 9. 7. 1. 9. 6. 6. 9. 1. 1. 7.]]

[array([[1., 5., 8., 1.],
[2., 8., 9., 7.]]),
array([[3., 1., 9., 4.],
[1., 9., 6., 6.]]),
array([[3., 8., 8., 9.],
[9., 1., 1., 7.]])]

指定平行切分

第二參數為一tuple

1
2
3
a = np.floor(10*np.random.random((2,12)))
print(a)
print(np.hsplit(a,(3,4,6)))

  • 將陣列於index第3 4 6的位置進行拆分
1
2
3
4
5
6
7
8
9
10
11
[[3. 4. 8. 7. 1. 7. 3. 8. 5. 7. 1. 3.]
[1. 2. 4. 8. 2. 5. 4. 6. 1. 8. 0. 8.]]

[array([[3., 4., 8.],
[1., 2., 4.]]),
array([[7.],
[8.]]),
array([[1.],
[2.]]),
array([[7., 3., 8., 5., 7., 1., 3.],
[5., 4., 6., 1., 8., 0., 8.]])]

垂直切分(np.vsplit)

1
2
3
b = np.floor(10*np.random.random((2,2)))
print(b)
print(np.vsplit(b,2))

result

1
2
3
4
5
[[1. 6.]
[5. 9.]]

[array([[1., 6.]]),
array([[5., 9.]])]

指定垂直切分

1
2
3
b = np.floor(10*np.random.random((3,2)))
print(b)
print(np.vsplit(b,(1,)))

result

1
2
3
4
5
6
7
[[5. 8.]
[9. 9.]
[5. 1.]]

[array([[5., 8.]]),
array([[9., 9.],
[5., 1.]])]

矩陣間的拷貝

Situation 1 - 非拷貝

A與B指向同一矩陣(非拷貝)
只是變量名不同,但指向的為同一個矩陣

1
2
3
4
5
6
7
8
9
10
a = np.arange(12)
print(a.shape)

b = a

print(b is a)
b.shape = (3,-1)
print(a.shape)
print(id(a))
print(id(b))

result
1
2
3
4
5
(12,)
True
(3, 4)
4395559392
4395559392

  • 對A操作等同於對B操作

Situation 2 - 淺拷貝(view)

A與B指向不同矩陣,
但矩陣中存放的值為共用的

1
2
3
4
5
6
7
8
9
10
11
12
13
a =np.arange(12)
print(a.shape)

b = a.view()

print(b is a)
b.shape = (3,-1)
print(a.shape)
print(id(a))
print(id(b))
a[0] = 10000
print(a)
print(b)

result

1
2
3
4
5
6
7
8
9
(12,)
False
(12,)
4395385280
4395385120
[10000 1 2 3 4 5 6 7 8 9 10 11]
[[10000 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]

  • a.view()創建一個a矩陣的淺拷貝
  • a 與 b 為不同矩陣

    • 改變b矩陣的shape,a並無變化
    • a 與 b 指向不同的內存地址
  • a 與 b 矩陣中的值是共用的

    • 操作 a 矩陣的值 b 矩陣仍會改變

Situation 3 - 深拷貝

A與B指向不同矩陣,
矩陣中存放的值也互不相干

1
2
3
4
5
6
7
8
9
10
11
12
13
a =np.arange(12)
print(a.shape)

b = a.copy()

print(b is a)
b.shape = (3,-1)
print(a.shape)
print(id(a))
print(id(b))
a[0] = 10000
print(a)
print(b)

result

1
2
3
4
5
6
7
8
9
(12,)
False
(12,)
4395558752
4395560832
[10000 1 2 3 4 5 6 7 8 9 10 11]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]

  • a.copy()創建一個a矩陣的深拷貝
  • a 與 b 矩陣中的值互不相干

矩陣排序

np.sort排序

返回一個排序好的矩陣

1
2
3
4
matrix =np.array([[9., 3., 8., 0., 6., 9.],
[4., 1., 4., 3., 8., 3.]])
a = np.sort(matrix,axis=1)
a

  • axis=1代表按行排序,axis=0則為按列排序
    result
    1
    2
    array([[0., 3., 6., 8., 9., 9.],
    [1., 3., 3., 4., 4., 8.]])

矩陣內置.sort()排序

對當前調用方法的矩陣排序

1
2
3
4
matrix =np.array([[9., 3., 8., 0., 6., 9.],
[4., 1., 4., 3., 8., 3.]])
matrix.sort(axis =1)
matrix

result

1
2
array([[0., 3., 6., 8., 9., 9.],
[1., 3., 3., 4., 4., 8.]])

argsort返回由小到大排序的索引值

1
2
3
4
matrix =np.array([[9., 3., 8., 0., 6., 9.],
[4., 1., 4., 3., 8., 3.]])
SortIndex = matrix.argsort(axis=1)
SortIndex

result

1
2
array([[3, 1, 4, 2, 0, 5],
[1, 3, 5, 0, 2, 4]])

  • 返回原矩陣由小到大原索引值的矩陣