如何用三元组表表示下列稀疏矩阵_盘一盘 Python 系列特别篇21之:SciPy 稀疏矩阵...
和稠密矩陣相比,稀疏矩陣的最大好處就是節省大量的內存空間來儲存零。稀疏矩陣本質上還是矩陣,只不過多數位置是空的,那么存儲所有的 0 非常浪費。稀疏矩陣的存儲機制有很多種 (列出常用的五種):
COO (Coordinate List Format):座標格式,容易創建但是不便于矩陣計算,用?coo_matrix
CSR (Compressed Sparse Row):?壓縮行格式,不容易創建但便于矩陣計算,用?csr_matri
CSC (Compressed Sparse Column):?壓縮列格式,不容易創建但便于矩陣計算,用?csc_matrix
LIL (List of List):?內嵌列表格式,支持切片但也不便于矩陣計算,用?lil_matrix
DIA (Diagnoal):對角線格式,適合矩陣計算,用?dia_matrix
在 SciPy 中稀疏矩陣一共有七種,剩余的兩種類型 BSR 和 DOK 本貼不做研究。有興趣的讀者可以去官網去查詢。
COO采用三元組?(row, col, data)?的形式來存儲矩陣中非零元素的信息,即把非零值?data?按著行坐標?row?和縱坐標?col?寫成兩個列表。如下圖所示:
坐標 (1, 1) 對應的數據 2
坐標 (3, 4) 對應的數據 5
坐標 (0, 2) 對應的數據 9
坐標 (2, 3) 對應的數據 1
坐標 (4, 3) 對應的數據 6
在實際使用中,用?coo_matrix()?語法來創建矩陣,注意產出矩陣的格式是COOrdinate。
values = [1, 2, 3, 4]rows = [0, 1, 2, 3]cols = [1, 3, 2, 0]A = sp.coo_matrix((values, (rows, cols)), shape=[4, 4])A<4x4 sparse matrix of?type?'numpy.int32'>'with?4?stored elements?in?COOrdinate format>檢查矩陣?A?的形狀、數據類型、維度和非零值的個數。
A.shape, A.dtype, A.ndim, A.nnz((4,?4), dtype('int32'),?2,?4)檢查矩陣?A?的行坐標、列坐標和數據。
A.row, A.col, A.data(array([0,?1,?2,?3], dtype=int32),?array([1,?3,?2,?0], dtype=int32),
?array([1,?2,?3,?4]))
如果想看?A?中的元素,我們可用?toarray()?轉換成?numpy?數組顯示出來。
A.toarray()array([[0, 1, 0, 0],???????[0, 0, 0, 2],
???????[0, 0, 3, 0],
???????[4, 0, 0, 0]])
COO 矩陣的元素無法進行增刪改操作,一般創建成功之后可以轉化成其他格式的稀疏矩陣 (如 CSR, CSC) 進行轉置、矩陣乘法等操作,或者轉成轉成 LIL 做切片。
A.tocsr()<4x4 sparse matrix of?type?'numpy.intc'>'with?4?stored elements?in?Compressed Sparse Row format>A.tolil()<4x4 sparse matrix?of?type?'numpy.intc'>'with?4?stored elements?in?List?of?Lists format>可視化矩陣?A
plt.spy(A);CSR由三個一維數組?indptr,?indices,?data?組成。這種格式要求矩陣元按行順序存儲,每一行中的元素可以亂序存儲。那么對于每一行就只需要用一個指針表示該行元素的起始位置即可。
indices?存儲每行中數據的列號,與屬性?data?中的元素一一對應
indptr?存儲每行數據元素的起始位置
如下圖所示:
第 1 行:indptr 0-2?指?indices[0:2]?的值即 0 和 2,分別又指第 0 和 2?列,對應的數據 8 和 2
第 2 行:indptr 2-3?指?indices[2:3]?的值即 2,分別又指第 2?列,對應的數據 5
第 3 行:indptr 3-3?指?indices[3:3]?的值為空,無數據
第 4 行:indptr 3-3?指?indices[3:3]?的值為空,無數據
第 5 行:indptr 3-6?指?indices[3:6]?的值即 2,3 和 4,分別又指第 2,3 和 4?列,對應的數據 7,1 和 2
第 6 行:indptr 6-6?指?indices[6:6]?的值為空,無數據
第 7 行:indptr 6-7?指?indices[6:7]?的值即 3,分別又指第 3?列,對應的數據 9
規律:indptr?的長度等于矩陣行數加 1,而第?i?行的列數,就是?indices[indptr[i]:indptr[i+1]]。
用?csr_matrix()?語法用來創建矩陣,注意產出矩陣的格式是 Compressed Sparse Row。
data = np.array([1, 2, 3, 4, 5, 6])indices = np.array([0, 2, 2, 0, 1, 2])indptr = np.array([0, 2, 3, 6])A = sp.csr_matrix((data, indices, indptr), shape=(3, 3))A<3x3 sparse matrix of?type?'numpy.int32'>'with?6?stored elements?in?Compressed Sparse Row format>檢查矩陣?A?的形狀、數據類型、維度和非零值的個數。
A.shape, A.dtype, A.ndim, A.nnz((3,?3), dtype('int32'),?2,?6)檢查矩陣?A?的列索引、索引指針和數據。
A.indices, A.indptr, A.data(array([0, 2, 2, 0, 1, 2]), array([0, 2, 3, 6]), array([1, 2, 3, 4, 5, 6]))如果想看?A?中的元素,我們可用?toarray()?轉換成?numpy?數組顯示出來。
A.toarray()array([[1, 0, 2],???????[0, 0, 3],
???????[4, 5, 6]])
可視化矩陣?A
plt.spy(A);CSCcsc_matrix?和?csr_matrix?正好相反,即按列壓縮的稀疏矩陣存儲方式,同樣由三個一維數組?indptr,?indices,?data?組成,
indices?存儲每列中數據的行號,與屬性?data?中的元素一一對應
indptr?存儲每列數據元素的起始位置
如下圖所示:
第 0 列:indptr 0-1?指?indices[0:1]?的值即 0,分別又指第 0?行,對應的數據 8
第 1 列:indptr 1-1?指?indices[1:1]?的值為空,無數據
第 2 列:indptr 1-4?指?indices[1:4]?的值即 0,1 和 4,分別又指第 0,1 和 4?行,對應的數據 2,5 和 7
第 3 列:indptr 4-6?指?indices[4:6]?的值即 4 和 6,分別又指第 4 和 6?行,對應的數據 1 和 9
第 4 列:indptr 6-7?指?indices[6:7]?的值即 4,分別又指第 4?行,對應的數據 2
規律:indptr?的長度等于矩陣列數加 1,而第?i?列的行數,就是?indices[indptr[i]:indptr[i+1]]。
用?csc_matrix()?語法用來創建矩陣,注意產出矩陣的格式是 Compressed Sparse Column。
data = np.array([1, 2, 3, 4, 5, 6])indices = np.array([0, 2, 2, 0, 1, 2])indptr = np.array([0, 2, 3, 6])A?=?sp.csc_matrix((data,?indices,?indptr),?shape=(3,?3))A<3x3 sparse matrix of?type?'numpy.int32'>'with?6?stored elements?in?Compressed Sparse Column format>檢查矩陣?A?的形狀、數據類型、維度和非零值的個數。
A.shape, A.dtype, A.ndim, A.nnz((3,?3), dtype('int32'),?2,?6)檢查矩陣?A?的行索引、索引指針和數據。
A.indices, A.indptr, A.data(array([0, 2, 2, 0, 1, 2]), array([0, 2, 3, 6]), array([1, 2, 3, 4, 5, 6]))如果想看?A?中的元素,我們可用?toarray()?轉換成?numpy?數組顯示出來。
A.toarray()array([[1, 0, 4],???????[0, 0, 5],
???????[2, 3, 6]])
可視化矩陣?A
plt.spy(A);LILlil_matrix?使用兩個嵌套列表存儲稀疏矩陣:
data?保存每行中的非零元素的值
rows?保存每行非零元素所在的列號 (列號是按順序排的)。
這種格式很適合逐個添加元素,并且能快速獲取行相關的數據。如下圖所示:
第 0 行:列號為 0,2,4,對應的數據為 8,1,-1
第 1 行:列號為 1,2,對應的數據為 8,2
第 2 行:列號為 2,對應的數據為 3
第 3 行:列號為 0,2,3,4,對應的數據為 -2,4,8,-2
第 4 行:列號為 2,4,對應的數據為 5,8
第 5 行:列號為 2,對應的數據為 6
用?lil_matrix()?語法用來創建矩陣,注意產出矩陣的格式是 Lists of Lists。
data = [[8,0,1,0,-1], [0,8,2,0,0], [0,0,3,0,0], [-2,0,4,8,-2], [0,0,5,0,8], [0,0,6,0,0]]A = sp.lil_matrix(data)A<6x5 sparse matrix?of?type?'numpy.intc'>'with?13?stored elements?in?List?of?Lists format>檢查矩陣?A?的每行的非零值對應的列索引。
A.rowsarray([list([0,?2,?4]),?list([1,?2]),?list([2]),?list([0,?2,?3,?4]),???????list([2,?4]),?list([2])], dtype=object)
如果想看?A?中的元素,我們可用?toarray()?轉換成?numpy?數組顯示出來。
A.toarray()array([[?8,?0,?1,?0,?-1],???????[?0, 8, 2, 0, 0],
???????[?0, 0, 3, 0, 0],
???????[-2, 0, 4, 8, -2],
???????[?0, 0, 5, 0, 8],
???????[?0, 0, 6, 0, 0]], dtype=int32)
可視化矩陣?A
plt.spy(A);DIAdia_matrix?按對角線的存儲方式。稀疏矩陣使用?offsets?和?data?兩個矩陣來表示,其中offsets?表示?data?中每一行數據在原始稀疏矩陣中的對角線位置 k:
k > 0, 對角線往右上方移動 k 個單位
k < 0, 對角線往左下方移動 k 個單位
k = 0,主對角線
如下圖所示:
offset 0?對應的數據?[1,2,3,4,5]?在主對角線上
offset -3?對應的數據?[6,7,8,9,10]?在主對角線左下方移動 3 個單位
offset 2?對應的數據?[11,12,13,14,15]?在對角線上右上方移動 2 個單位
用?dia_matrix()?語法用來創建矩陣,注意產出矩陣的格式是 DIAgonal。
data = np.arange(1,13).reshape(3,-1)offset = [-1, 0, 1]A = sp.dia_matrix( (data, offset), shape=(4,4) )A<4x4 sparse matrix of?type?'numpy.int32'>'with?10?stored elements (3?diagonals)?in?DIAgonal format>檢查矩陣?A?的平移單位。
A.offsetsarray([-1,?0,?1], dtype=int32)如果想看?A?中的元素,我們可用?toarray()?轉換成?numpy?數組顯示出來。
A.toarray()array([[ 5, 10, 0, 0],???????[ 1, 6, 11, 0],
???????[ 0, 2, 7, 12],
???????[ 0, 0, 3, 8]])
可視化矩陣?A
plt.spy(A);此外,在?sp.sparse?模塊里還有一些直接創建稀疏矩陣的函數:
eye?生成稀疏單位對角陣
diags?構建稀疏對角陣
spdiags?構建稀疏對角陣
假設我們想生成一個方陣,主對角線上面是 -2,上下次對角線上的值為 1。
方法一:用?eye
N = 5A = sp.eye(N, k=1) - 2 * sp.eye(N) + sp.eye(N, k=-1)A.toarray()array([[-2., 1., 0., 0., 0.],???????[ 1., -2., 1., 0., 0.],
???????[ 0., 1., -2., 1., 0.],
???????[ 0., 0., 1., -2., 1.],
???????[ 0., 0., 0., 1., -2.]])
方法二:用?diags
A = sp.diags([1, -2, 1], [1, 0, -1], (N, N), format='csc')A.toarray()array([[-2., 1., 0., 0., 0.],???????[ 1., -2., 1., 0., 0.],
???????[ 0., 1., -2., 1., 0.],
???????[ 0., 0., 1., -2., 1.],
???????[ 0., 0., 0., 1., -2.]])
方法三:用?spdiags
data = np.vstack( [np.repeat(1,N), np.repeat(-2,N), np.repeat(1,N)] )A = sp.spdiags( data, [1, 0, -1], N, N )A.toarray()array([[-2., 1., 0., 0., 0.],???????[ 1., -2., 1., 0., 0.],
???????[ 0., 1., -2., 1., 0.],
???????[ 0., 0., 1., -2., 1.],
???????[ 0., 0., 0., 1., -2.]])
三種方法都得到一樣的結果,但是用??diags?方法代碼最簡潔些。但是如果對角線上的值都不一樣,那么只能用?spdiags?方法,原因是它的參數是數組,而不是元素。
在金工中一維 PDE 有限差分離散之后都是這種類型的三對角矩陣 (tri-diagnol),因此要熟練掌握用?diags/spdiags?方法來創建金工需要的“稀疏矩陣”。
總結從官網資料看出,一般使用?lil_matrix?來構建矩陣效率最高。由于?LIL 形式是基于行的,因此它能夠很高效的轉為 CSR,但是轉為 CSC 的效率相對較低。
如果要執行矩陣乘法或轉置,將它們轉換成?CSC 或 CSR 格式,效率最高。
總之,在運算稀疏矩陣時,絕對絕對不要直接使用 NumPy!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
如果覺得好,關注、轉發、在看三連發走起? 666~~~
福利來一波~~~
關注公眾號回復以下信息送免費資料
回復Jenkins?領取Jenkins學習資料回復Jmeter?領取Jmeter學習資料
回復Java? ?領取Java學習資料
回復Python?領取python入門資料
回復RobotFramework???領取RobotFramework 框架搭建資料
你可能會喜歡
Jmeter關聯系列_數據驅動中的業務邏輯關聯
docker搭建接口自動化持續集成框架
python28:迷宮游戲最短路徑算法
4300 字Python列表使用總結,用心!
盤一盤 Python 系列基礎篇十一之 機器學習 Sklearn
盤一盤 Python 系列特別篇二十之 天數計數|年限
Linux環境部署之ubuntu網絡配置
性能測試指標7:性能測試的階段性工作
jmeter之對jar包進行調用
jmeter之爬取網絡圖片
軟件質量保障體系圖
研發過程中的測試工作
APP測試流程及測試點
WEB測試范圍小結
測試交流,加我備注【測試交流】拉入交流群,更有不定期資料贈送,敬請期待
本文轉載自【公眾號:王的機器】
總結
以上是生活随笔為你收集整理的如何用三元组表表示下列稀疏矩阵_盘一盘 Python 系列特别篇21之:SciPy 稀疏矩阵...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 删除模拟器,androi
- 下一篇: python异常值删除_python数据