稀疏矩陣理論與實踐
1.稀疏矩陣的優化
l 多線程。使用openmp或者mpi
l numanode awareness 特性。把稀疏矩陣的存儲均勻地分配到兩顆處理器各自的本地內存中,最大程度的利用內存帶寬
l 利用硬件cache特性,對矩陣進行分塊或矩陣的循環進行限制
l 利用pipeline,多流水線並行處理
l 自適應分塊存儲結構。由於稀疏矩陣的非零元分布不一定均勻,有的分塊會非常稀疏,有的則會相對稠密。對於極稀疏的分塊(非零元數量遠小於行數),如果用和CSR相似的壓縮行存儲策略,則會浪費空間,所以用COO的方式反而更能節省存儲空間,提高訪問效率。
2. 矩陣(稀疏矩陣)壓縮存儲(3種方式)
數據結構中,提供針對某些特殊矩陣的壓縮存儲結構。
這里所說的特殊矩陣,主要分為以下兩類:
- 含有大量相同數據元素的矩陣,比如對稱矩陣;
- 含有大量 0 元素的矩陣,比如稀疏矩陣、上(下)三角矩陣;
針對以上兩類矩陣,數據結構的壓縮存儲思想是:矩陣中的相同數據元素(包括元素 0)只存儲一個。
對稱矩陣
圖 1 對稱矩陣示意圖
圖 1 的矩陣中,數據元素沿主對角線對應相等,這類矩陣稱為對稱矩陣。
矩陣中有兩條對角線,其中圖 1 中的對角線稱為主對角線,另一條從左下角到右上角的對角線為副對角線。對稱矩陣指的是各數據元素沿主對角線對稱的矩陣。
結合數據結構壓縮存儲的思想,可以使用一維數組存儲對稱矩陣。由於矩陣中沿對角線兩側的數據相等,因此數組中只需存儲對角線一側(包含對角線)的數據即可。
對稱矩陣的實現過程是,若存儲下三角中的元素,只需將各元素所在的行標 i 和列標 j 代入下面的公式:
存儲上三角的元素要將各元素的行標 i 和列標 j 代入另一個公式:
最終求得的 k 值即為該元素存儲到數組中的位置(矩陣中元素的行標和列標都從 1 開始)。
例如,在數組 skr[6] 中存儲圖 1 中的對稱矩陣,則矩陣的壓縮存儲狀態如圖 3 所示(存儲上三角和下三角的結果相同):
圖 3 對稱矩陣的壓縮存儲示意圖
注意,以上兩個公式既是用來存儲矩陣中元素的,也用來從數組中提取矩陣相應位置的元素。例如,如果想從圖 3 中的數組提取矩陣中位於 (3,1) 處的元素,由於該元素位於下三角,需用下三角公式獲取元素在數組中的位置,即:
結合圖 3,數組下標為 3 的位置存儲的是元素 3,與圖 1 對應。
上(下)三角矩陣
圖 4 上(下)三角矩陣
如圖 4 所示,主對角線下的數據元素全部相同的矩陣為上三角矩陣(圖 4a)),主對角線上元素全部相同的矩陣為下三角矩陣(圖 4b))。
對於這類特殊的矩陣,壓縮存儲的方式是:上(下)三角矩陣采用對稱矩陣的方式存儲上(下)三角的數據(元素 0 不用存儲)。
例如,壓縮存儲圖 4a) 中的上三角矩陣,矩陣最終的存儲狀態同圖 3 相同。因此可以得出這樣一個結論,上(下)三角矩陣存儲元素和提取元素的過程和對稱矩陣相同。
稀疏矩陣
圖 5 稀疏矩陣示意圖
如圖 5 所示,如果矩陣中分布有大量的元素 0,即非 0 元素非常少,這類矩陣稱為稀疏矩陣。
壓縮存儲稀疏矩陣的方法是:只存儲矩陣中的非 0 元素,與前面的存儲方法不同,稀疏矩陣非 0 元素的存儲需同時存儲該元素所在矩陣中的行標和列標。
例如,存儲圖 5 中的稀疏矩陣,需存儲以下信息:
- (1,1,1):數據元素為 1,在矩陣中的位置為 (1,1);
- (3,3,1):數據元素為 3,在矩陣中的位置為 (3,1);
- (5,2,3):數據元素為 5,在矩陣中的位置為 (2,3);
- 除此之外,還要存儲矩陣的行數 3 和列數 3;
由此,可以成功存儲一個稀疏矩陣。
注意,以上 3 種特殊矩陣的壓縮存儲,除了將數據元素存儲起來,還要存儲矩陣的行數值和列數值,具體的實現方式后續會介紹 3 種,本節僅需了解矩陣壓縮存儲的原理。
3. 矩陣壓縮存儲的 3 種方式
對於以上 3 種特殊的矩陣,對陣矩陣和上下三角矩陣的實現方法是相同的,且實現過程比較容易,僅需套用上面給出的公式即可。
稀疏矩陣的壓縮存儲,數據結構提供有 3 種具體實現方式:
l 三元組順序表;
l 行邏輯鏈接的順序表;
l 十字鏈表;
在Python中稀疏矩陣
SciPy提供了使用多種數據結構創建稀疏矩陣的工具,以及將稠密矩陣轉換為稀疏矩陣的工具。
許多在NumPy陣列上運行的線性代數NumPy和SciPy函數可以透明地操作SciPy稀疏數組。此外,使用NumPy數據結構的機器學習庫也可以在SciPy稀疏數組上透明地進行操作,例如用於一般機器學習的scikit-learn和用於深度學習的Keras。
存儲在NumPy數組中的稠密矩陣可以通過調用csr_matrix()函數將其轉換為一個稀疏矩陣。
在下面的例子中,我們將一個3×6的稀疏矩陣定義為一個稠密數組,將它轉換為CSR稀疏表示,然后通過調用todense()函數將它轉換回一個稠密數組。
運行該示例首先打印已定義的稠密數組,接着是CSR表示,然后是重新構建的稠密矩陣。
NumPy並沒有提供一個函數來計算矩陣的稀疏性。
不過,我們可以很容易地計算出矩陣的密度,然后從一個矩陣中減去它。NumPy數組中的非零元素可以由count_nonzero()函數給出,數組中元素的總數可以由數組的大小屬性給出。因此,數組的稀疏性可以被計算為:
下面的例子演示了如何計算數組的稀疏性。
運行這個例子首先打印出定義的稀疏矩陣,接着是矩陣的稀疏性。
[[1 0 0 1 0 0]
[0 0 2 0 0 1]
[0 0 0 2 0 0]]
0.7222222222222222
參考鏈接:
https://zhuanlan.zhihu.com/p/34534763
http://data.biancheng.net/view/183.html
https://blog.csdn.net/yhb1047818384/article/details/78996906