1. 程式人生 > >機器學習中稀疏矩陣的處理方式和Python實現

機器學習中稀疏矩陣的處理方式和Python實現

在矩陣中,如果數值為0的元素數目遠遠多於非0元素的數目,並且非0元素分佈無規律時,則稱該矩陣為稀疏矩陣;與之相反,若非0元素數目佔大多數時,則稱該矩陣為稠密矩陣。

大的稀疏矩陣在一般情況下是通用的,特別是在應用機器學習中,例如包含計數的資料、對映類別的資料編碼,甚至在機器學習的整個子領域,如自然語言處理(NLP)。

教程概述

本教程分為5部分;分別為:

稀疏矩陣

稀疏的問題

機器學習中的稀疏矩陣

處理稀疏矩陣

在Python中稀疏矩陣

稀疏矩陣

稀疏矩陣是一個幾乎由零值組成的矩陣。稀疏矩陣與大多數非零值的矩陣不同,非零值的矩陣被稱為稠密矩陣。

如果矩陣中的許多係數都為零,那麼該矩陣就是稀疏的。對稀疏現象有興趣是因為它的開發可以帶來巨大的計算節省,並且在許多大的實踐中都會出現矩陣稀疏的問題。

—第1頁,《稀疏矩陣的直接教學方法》(Direct Methods for Sparse Matrices),第二版,2017年。

矩陣的稀疏性可以用一個得分來量化,也就是矩陣中零值的個數除以矩陣中元素的總個數。

sparsity= count zeroelements/ totalelements

下面是一個小的3×6稀疏矩陣的例子。

1, 0, 0, 1, 0, 0

A = (0, 0, 2, 0, 0, 1)

0, 0, 0, 2, 0, 0

這個例子在矩陣中的18個元素中有13個零值,這個矩陣的得分是0.722或約72%。

稀疏的問題

稀疏矩陣會導致空間複雜度和時間複雜度的問題。

空間複雜度

非常大的矩陣需要大量的記憶體,而我們想要處理的一些非常大的矩陣是稀疏的。

在實踐中,大多數大型矩陣都是稀疏的——幾乎所有的項都為零。

—第465頁,《線性代數介紹》(Introduction to Linear Algebra),第五版,2016年。

一個非常大的矩陣的例子是,因為它太大而不能儲存在記憶體中,這是一個顯示從一個網站到另一個網站的連結的連結矩陣。一個更小的稀疏矩陣的例子可能是一個單詞或術語的出現矩陣,在一本書中與所有已知的英語單詞對應。

在這兩種情況下,所包含的矩陣都是稀疏的,其零值比資料值要多。將這些稀疏矩陣表示為稠密矩陣的問題是對記憶體的要求,並且必須為矩陣中的每個32位或64位零值做出分配。

這顯然是對記憶體資源的浪費,因為這些零值不包含任何資訊。

時間複雜度

假設一個非常大的稀疏矩陣可以適應記憶體,我們將需要對這個矩陣執行操作。

簡單地說,如果矩陣包含了大部分零值,也就是沒有資料,那麼在這個矩陣中執行操作可能需要很長時間,其中的大部分計算都需要或將零值相加或相乘。

在這樣的問題上使用線性代數的一般方法是很浪費的,因為大多數O(N^3)算術運算都用於求解方程組或反轉(invert)包含零運算元的矩陣。

—第75頁,《數值分析:科學計算的藝術》(Numerical Recipes: The Art of Scientific Computing),第三版,2007年。

這是矩陣運算的時間複雜度增加的問題,隨著矩陣的大小而增加。

當我們考慮到即使是瑣碎的機器學習方法可能需要對每一行、列甚至整個矩陣進行許多操作時,這個問題也會變得更加複雜,從而導致執行時間大大延長。

機器學習中的稀疏矩陣

稀疏矩陣在應用機器學習中經常出現。

在這一節中,我們將討論一些常見的例子,以激發你對稀疏問題的認識。

資料

稀疏矩陣在某些特定型別的資料中出現,最值得注意的是記錄活動的發生或計數的觀察。

三個例子包括:

使用者是否在一個電影目錄中有曾經看過的電影。

使用者是否在一個產品目錄中有已經購買過的產品。

在一個歌曲目錄中數出收聽過的歌曲的數量。

資料準備

在準備資料時,稀疏矩陣會出現在編碼方案中。

三種常見的例子包括:

獨熱編碼,用來表示分類資料為稀疏的二進位制向量。

計數編碼,用於表示文件中詞彙的頻率。

TF-IDF編碼,用於表示詞彙中標準化的單詞頻率得分。

領域研究

機器學習中的一些領域必須開發專門的方法來解決稀疏問題,因為輸入的資料幾乎總是稀疏的。

三個例子包括:

用於處理文字文件的自然語言處理。

推薦系統在一個目錄中進行產品使用。

當處理影象時計算機視覺包含許多黑色畫素(black pixel)。

如果在語言模型中有100,000個單詞,那麼特徵向量長度為100,000,但是對於一個簡短的電子郵件來說,幾乎所有的特徵都是0。

—第22頁,《人工智慧:一種現代方法》(Artificial Intelligence: A Modern Approach),第三版,2009年。

處理稀疏矩陣

表示和處理稀疏矩陣的解決方案是使用另一個數據結構來表示稀疏資料。

零值可以被忽略,只有在稀疏矩陣中的資料或非零值需要被儲存或執行。

多個數據結構可以用來有效地構造一個稀疏矩陣;下面列出了三個常見的例子。

Dictionary of Keys。在將行和列索引對映到值時使用字典。

List of Lists。矩陣的每一行儲存為一個列表,每個子列表包含列索引和值。

Coordinate List。一個元組的列表儲存在每個元組中,其中包含行索引、列索引和值。

還有一些更適合執行高效操作的資料結構;下面列出了兩個常用的示例。

壓縮的稀疏行。稀疏矩陣用三個一維陣列表示非零值、行的範圍和列索引。

壓縮的稀疏列。與壓縮的稀疏行方法相同,除了列索引外,在行索引之前被壓縮和讀取。

被壓縮的稀疏行,也稱為CSR,通常被用來表示機器學習中的稀疏矩陣,因為它支援的是有效的訪問和矩陣乘法。

在Python中稀疏矩陣

SciPy提供了使用多種資料結構建立稀疏矩陣的工具,以及將稠密矩陣轉換為稀疏矩陣的工具。

許多在NumPy陣列上執行的線性代數NumPy和SciPy函式可以透明地操作SciPy稀疏陣列。此外,使用NumPy資料結構的機器學習庫也可以在SciPy稀疏陣列上透明地進行操作,例如用於一般機器學習的scikit-learn和用於深度學習的Keras。

儲存在NumPy陣列中的稠密矩陣可以通過呼叫csr_matrix函式將其轉換為一個稀疏矩陣。

在下面的例子中,我們將一個3×6的稀疏矩陣定義為一個稠密陣列,將它轉換為CSR稀疏表示,然後通過呼叫todense函式將它轉換回一個稠密陣列。

執行該示例首先列印已定義的稠密陣列,接著是CSR表示,然後是重新構建的稠密矩陣。

NumPy並沒有提供一個函式來計算矩陣的稀疏性。

不過,我們可以很容易地計算出矩陣的密度,然後從一個矩陣中減去它。NumPy陣列中的非零元素可以由count_nonzero函式給出,陣列中元素的總數可以由陣列的大小屬性給出。因此,陣列的稀疏性可以被計算為:

sparsity = 1.0 - count_nonzero(A) / A.size

下面的例子演示瞭如何計算陣列的稀疏性。

總結

在學習了這篇教程之後,你知道了:

稀疏矩陣幾乎包含全部零值,並且與稠密矩陣不同。

你可能會在資料、資料準備和機器學習的子領域中遇到稀疏矩陣。

有許多有效的方法可以儲存和使用稀疏矩陣,而SciPy提供了你可以直接使用的實現。