文章目錄
1.0 Numpy 介紹
numpy是python機器學習的基礎,因爲它能夠對機器學習中經常處理的向量、矩陣、張量、等數據結構進行有效快速的處理
1.1 聲明向量
# 導入包
import numpy as np
# 行向量
v_row = np.array([1,2,3])
# 列向量
v_column = np.array([[1],
[2],
[3]])
numpy的主要數據結構就是多維數組,創建向量就是在創建一維數組
1.2 創建矩陣
m = np.matrix([[1,2],
[2,3],
[3,4]])
matrix = np.array([[1,2],
[2,3],
[3,4]])
numpy中有兩種創建矩陣的方法,但實際上我們更傾向於使用array方法,理由如下:
1、數組是numpy事實上的標準數據結構。
2、絕大多數numpy操作返回的是數組,而不是矩陣對象。
1.3 創建稀疏矩陣
# 導入需要的包
import numpy as np
from scipy import sparse
# 創建矩陣並稀疏化
mt = np.array([[1,0,1],
[0,1,0],
[4,0,2]])
mt_sparse = sparse.csr_matrix(mt)
# 打印查看
print(mt)
print(mt_sparse)
[[1 0 1]
[0 1 0]
[4 0 2]]
(0, 0) 1
(0, 2) 1
(1, 1) 1
(2, 0) 4
(2, 2) 2
可以看出稀疏化之後只儲存了非零的值,大大壓縮了存儲空間。在機器學習中,我們遇到地大多數矩陣都有很多0元素,例如有一個矩陣,它的行向量代表清華大學的每一門課,列向量代表清華的每一個學生,因爲大多數學生都只選了自己專業的一小部分課程,所以這個龐大的矩陣中會含有相當多的0元素。
csr_matrix函數(compressed sparse row)壓縮稀疏行
即使我們在矩陣中填入更多的0擴展矩陣的行和列,都不會改變該矩陣的存儲大小。
有許多不同類型的稀疏矩陣,如壓縮稀疏列、列表列表和鍵字典。雖然對不同類型及其含義的解釋超出了本書的範圍,但值得注意的是,雖然沒有“最佳”的稀疏矩陣類型,但它們之間存在有意義的區別,我們應該意識到爲什麼我們選擇一種類型而不是另一種類型。
1.4 進行元素的選擇
注意,就像在python絕大多數包中的那樣,numpy也是零索引的(zero-indexed),即從0開始索引:
v_row = np.array([1,2,3])
v_row[2]
3
matrix = np.array([[1,2],
[2,3],
[3,4]])
matrix[1,1]
3
numpy中的切片選擇操作是前開後閉的
v_row = np.array([1,2,3,4,5,6,7])
# 選擇所有元素
print(v_row[:])
# 選擇從第一個元素開始到第二個元素的所有元素
print(v_row[:2])
# 選擇第六個元素之後的所有元素
print(v_row[6:])
# 選擇倒數第二個元素
print(v_row[-2])
[1 2 3 4 5 6 7]
[1 2]
[7]
6
1.5 矩陣的描述
numpy中有可以描述矩陣行列數、元素數、以及維數(即矩陣的秩)的函數
m = np.matrix([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]])
# 行列數
print(m.shape)
# 大小
print(m.size)
# 矩陣的秩
print(m.ndim)
(3, 4)
12
2
如圖,原矩陣可以化爲如圖所示的階梯形矩陣,即矩陣的秩爲2
1.6 對元素進行操作
這裏涉及到一個可以將函數向量化的vectorize函數,NumPy的vectorize類將函數轉換爲可以應用於數組或數組切片中的所有元素的函數,詳細文檔請看vectorize
m = np.matrix([[1,2,3,4],
[5,6,7,8],
[9,10,11,12]])
fun = lambda i : i ** 2
fun_square = np.vectorize(fun)
fun_square(m)
matrix([[ 1, 4, 9, 16],
[ 25, 36, 49, 64],
[ 81, 100, 121, 144]])
這裏的fun函數使用lambda表達式定義了一個函數,vectorize將它向量化使其作用於每一個矩陣元素
而且,NumPy數組允許我們在數組之間執行操作,即使它們的維數不相同(這個過程稱爲行列擴充)。例如,我們可以創建一個更簡單的版本,實現矩陣和整數之間的 運算
m+100
matrix([[101, 102, 103, 104],
[105, 106, 107, 108],
[109, 110, 111, 112]])
1.7 找出最大最小值
np.max(m)
np.min(m)
很簡單吧,但是有時候我們會想知道每一行或者每一列的最大值最小值:
m = np.matrix([[1,2,3,4],
[5,6,7,8],
[9,1,11,12]])
# 輸出每一列最大的數的集合
print(np.max(m,axis=0))
#輸出每一行最小數的集合
print(np.min(m,axis=1))
[[ 9 6 11 12]]
[[1]
[5]
[1]]
如上所示,求出了每一行每一列的極值整合輸出
1.8 計算平均值、方差、標準差
matrix([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 1, 11, 12]])
# 平均值
print(np.mean(m))
# 方差
print(np.var(m))
# 標準差
print(np.std(m))
5.75
12.854166666666666
3.5852707940498254
就像求極值一樣,我們也可以對整行或者整列進行計算
# 每列的平均值
print(np.mean(m,axis=0))
# 每行的方差
print(np.var(m,axis=1))
[[5. 3. 7. 8.]]
[[ 1.25 ]
[ 1.25 ]
[18.6875]]
1.9 修改矩陣的行列(重塑)reshape
matrix([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 1, 11, 12]])
# 重塑爲2x6
m.reshape(2,6)
matrix([[ 1, 2, 3, 4, 5, 6],
[ 7, 8, 9, 1, 11, 12]])
# -1這個參數以爲儘可能多,所以下面意爲儘可能多的行,一列
m.reshape(-1,1)
matrix([[ 1],
[ 2],
[ 3],
[ 4],
[ 5],
[ 6],
[ 7],
[ 8],
[ 9],
[ 1],
[11],
[12]])
1.10 轉置向量和矩陣
matrix([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 1, 11, 12]])
m.T
matrix([[ 1, 5, 9],
[ 2, 6, 1],
[ 3, 7, 11],
[ 4, 8, 12]])
轉置是線性代數中一種常見的操作,它交換每個元素的行和列的索引。在線性代數課程之外,一個微妙的問題通常會被忽視,那就是,從技術上講,一個向量不能被置換,因爲它只是一個值的集合:
# Transpose vector np.array([1, 2, 3, 4, 5, 6]).T
array([1, 2, 3, 4, 5, 6])
然而,通常把轉置一個向量稱爲把一個行向量轉換成一個列向量(注意第二對括號),反之亦然:
# Tranpose row vector
np.array([[1, 2, 3, 4, 5, 6]]).T
array([[1],
[2],
[3],
[4],
[5],
[6]])
1.11 壓縮矩陣
matrix([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 1, 11, 12]])
m.flatten()
matrix([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 11, 12]])
同樣的,我們可以使用reshape方法m.reshape(1,-1)
來完成這項工作
1.12 求矩陣的秩
np.linalg.matrix_rank(m)
3
這個函數讓求矩陣的秩非常簡單
1.13 計算行列式
m = np.array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]])
np.linalg.det(m)
0.0
1.14 求主對角線的元素
m = np.array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]])
# 主對角線元素
m.diagonal()
array([1, 5, 9])
# 右上一位對角元素
m.diagonal(offset=1)
array([2, 6])
# 左下一位對角元素
m.diagonal(offset = -1)
array([4, 8])
diagonal
函數中的offset參數可以從主對角線向右上或左下移動對應的數值
1.15 計算矩陣的跡
m = np.array([[ 1, 2, 3],
[ 4, 5, 6],
[ 7, 8, 9]])
m.trace()
15
# 或者可以使用對角元素的和
sum(m.diagonal())
1.16 尋找特徵值和特徵向量
m = np.array([[ 1, 2, 3],
[ 3, 5, 6],
[ 7, 8, 2]])
eigenvalues,eigenvectors=np.linalg.eig(m)
print(eigenvalues)
print(eigenvectors)
[12.6069345 -0.01728267 -4.58965183]
[[-0.29252753 -0.70944096 -0.298811 ]
[-0.66066352 0.67328277 -0.43724833]
[-0.69134026 -0.20828785 0.84824871]]
1.17 計算點積
a = np.array([1,2,3])
b = np.array([1,2,3])
np.dot(a,b)
14
點積是每個向量中的元素對應相乘再相加
在Python3.5+中,我們還可以這樣計算點積
a @ b
14
1.18 矩陣的加減法
a = np.array([[1,2,3],
[5,2,1],
[9,5,7]])
b = np.array([[1,4,3],
[5,7,1],
[9,2,7]])
np.add(a,b)
array([[ 2, 6, 6],
[10, 9, 2],
[18, 7, 14]])
np.subtract(a,b)
array([[ 0, -2, 0],
[ 0, -5, 0],
[ 0, 3, 0]])
實際上,我們還可以使用直接的+ -
號來實現
1.19 矩陣相乘
# 矩陣中元素逐個相乘
print(a*b)
# 矩陣相乘的兩種方式
print(a @ b)
print(np.dot(a,b))
[[ 1 8 9]
[25 14 1]
[81 10 49]]
[[38 24 26]
[24 36 24]
[97 85 81]]
[[38 24 26]
[24 36 24]
[97 85 81]]
1.20 矩陣求逆
a = np.array([[1,2,3],
[5,2,1],
[9,5,7]])
np.linalg.inv(a)
array([[-0.40909091, -0.04545455, 0.18181818],
[ 1.18181818, 0.90909091, -0.63636364],
[-0.31818182, -0.59090909, 0.36363636]])
矩陣與其逆矩陣的乘積爲單位矩陣
我們來驗證一下
a @ np.linalg.inv(a)
array([[ 1.00000000e+00, -1.11022302e-16, 0.00000000e+00],
[-1.11022302e-16, 1.00000000e+00, 0.00000000e+00],
[ 1.11022302e-16, -1.11022302e-16, 1.00000000e+00]])
1.11022302e-16可以近似爲0
1.21 生成隨機值
和C++一樣,python在生成隨機值之前也需要設置種子
np.random.seed(100)
np.random.random(3)
array([0.54340494, 0.27836939, 0.42451759])
# 0-1整數
np.random.randint(1,10,3)
array([1, 5, 3])
# 以正態分佈平均值爲5,標準差爲2
np.random.normal(5,2,3)
array([0.54340494, 0.27836939, 0.42451759])