來自:
sparse
通常來說,稀疏矩陣可以和常規矩陣一樣提供相同的功能。兩者不同之處在於在記憶體中儲存矩陣和表示矩陣的方式。 在稀疏矩陣中,只有非0元素才會被儲存。這種方式帶來的優點有:首先,這可以很明顯的減少記憶體的使用『第二;通過使用指定的稀疏演算法和這種稀疏儲存方法可以減少計算時間。我們通常將常規的儲存矩陣叫做密集矩陣(dense matrices)。
theano的稀疏包提供高效的演算法,不過卻並不推薦在所有的矩陣和所有的情況下使用。正如乙個顯而易見的例子,當稀疏比例非常低的時候,就等於在常規矩陣上使用這些演算法,而且本身帶來的儲存開銷會比常規矩陣還大。稀疏比例指的是元素為0的值所佔整個矩陣上所有元素的個數比。乙個低稀疏比例會導致在記憶體上使用更多的空間,不只是需要儲存實際的資料,而且還需要儲存每個元素的位置資訊。這同樣需要更多的計算時間,然而乙個密集矩陣是使用常規優化演算法的,可能效果比這時候的稀疏表示矩陣更高效。其他例子可以在特定目的和矩陣的結構的聯絡上找到。更多的文件可以檢視 scipy sparse reference.
因為稀疏矩陣不是儲存在連續陣列上的,所以有幾種方式來儲存。這通常被設計成所謂的矩陣的格式(format)。因為 theano的稀疏矩陣包是基於scipy 稀疏包的,完整的有關稀疏矩陣的資訊可查閱 scipy的文件。就像scipy一樣, theano沒有對那些維度不等於2的陣列實現稀疏格式。
到目前為止,theano實現了兩個稀疏矩陣的格式:
cscand csr。
這些幾乎是等同的,除了csc是基於矩陣的列,而csr是基於矩陣的行的。他們都是有著相同的目的:為了提供給高效的演算法用來執行線性代數操作。不過缺點就是它們沒法通過乙個高效的方法來修改潛在矩陣的稀疏結構,例如:增加元素。這也就是說如果你在你的計算graph中會頻繁的在稀疏矩陣中增加新的元素,也許乙個tensor變數是更好的選擇。
更多的文件可以檢視 sparse library reference
.在進行下一步之前,來做做準備工作:
>>> import theano
>>> import numpy as np
>>> import scipy.sparse as sp
>>> from theano import sparse
theano支援兩種稀疏壓縮格式: csc
和 csr
, 分別是基於列和行的。他們都有著相同的屬性: data
, indices
, indptr
和 shape
.
最後,格式不會影響到data和indices屬性的長度(length)。它們都是通過你所想儲存的元素個數確定的。唯一會被格式改變的就是
indptr。在
csc格式下,該句子是按著列進行壓縮的,所以列數量更少的時候,所需要的記憶體就更少。另一方面,
csr格式下,句子是按行壓縮的,所以當乙個矩陣有著更少行數的時候,csr格式是個更好的選擇。下面就是規則的形式:
note:
if shape[0] > shape[1], 使用
csrformat. ;否則,使用
csc。
(覺得這裡和上面說的完全相反了,上面說當矩陣行少的時候用csr)。
有時候,因為稀疏模組到現在的時間還不長,ops還沒有針對兩種format的操作。所以這裡也是最相關的規則:
note:使用該矩陣格式可以相容你計算graph中的ops
。關於ops和所支援的format等文件可以查閱:
sparse library reference.
在theano中大多數的ops都是依賴於稀疏矩陣的格式(format)的。這就是為什麼有兩種稀疏變數的構造器:
csc_matrix
和 csr_matrix。這些都能被普通的name和dtype
引數所呼叫,不過沒有
broadcastable
標識。這是被禁止的,因為稀疏包(和scipy的稀疏模組一樣)不提供任何方式來處理維度不等於2的情況的矩陣。稀疏矩陣的所有可接受的dtype值可以在
sparse.all_dtypes
中找到:
>>> sparse.all_dtypes
set(['int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64',
'float32', 'float64', 'complex64', 'complex128'])
為了在稀疏矩陣和密集矩陣之間相互轉換。theano提供了
dense_from_sparse
,csr_from_dense
和 csc_from_dense
函式。不需要任何額外的細節。這裡就是從稀疏到稀疏的乙個完整轉換的例子:
>>> x = sparse.csc_matrix(name='x', dtype='float32')
>>> y = sparse.dense_from_sparse(x)
>>> z = sparse.csc_from_dense(y)
儘管稀疏變數不允許直接訪問它們的屬性,不過還是可以通過 csm_properties
來完成的。它會返回乙個一維的tensor變數的元組,用來表示稀疏矩陣的內部特徵。
為了從某些屬性上重構乙個稀疏矩陣,可以使用函式 csc
和 csr
。這會以合適的格式來建立稀疏矩陣。例如,下面的**重構乙個csc矩陣到csr格式:
>>> x = sparse.csc_matrix(name='x', dtype='int64')
>>> data, indices, indptr, shape = sparse.csm_properties(x)
>>> y = sparse.csr(data, indices, indptr, shape)
>>> f = theano.function([x], y)
>>> a = sp.csc_matrix(np.asarray([[0, 1, 1], [0, 0, 0], [1, 0, 0]]))
>>> print a.toarray()
[[0 1 1]
[0 0 0]
[1 0 0]]
>>> print f(a).toarray()
[[0 0 1]
[1 0 0]
[1 0 0]]
最後的例子顯示,格式可以從乙個轉換到另乙個。的確,當呼叫transpose函式的時候,生成的矩陣的稀疏特徵就不會和輸入的時候一樣了
2.3 結構(structured)操作
有幾個ops是用在稀疏矩陣的非常奇特的結構上的。這些ops是結構式的(structured),而且不會在稀疏矩陣的0元素上有任何的計算操作。 它們被認為是只用在後面(暫時不知道是指哪個)的資料屬性上的。 注意,這些結構操作都提供乙個結構梯度(structured gradient)。更多的解釋如下:
>>> x = sparse.csc_matrix(name='x', dtype='float32')
>>> y = sparse.structured_add(x, 2)
>>> f = theano.function([x], y)
>>> a = sp.csc_matrix(np.asarray([[0, 0, -1], [0, -2, 1], [3, 0, 0]], dtype='float32'))
>>> print a.toarray()
[[ 0. 0. -1.]
[ 0. -2. 1.]
[ 3. 0. 0.]]
>>> print f(a).toarray()
[[ 0. 0. 1.]
[ 0. 0. 3.]
[ 5. 0. 0.]]
在稀疏模組中ops的梯度同樣可以是structured。一些ops提供乙個
flag
來指定該梯度是否structured。該文件可以用來決定乙個op的梯度是否是常規的還是structured還是它的實現是否能夠被修改。相似於structured ops,當計算了乙個structured gradient的時候,該計算只會應用在係數矩陣的非0元素上。
更多有關特定op上的梯度可以查閱: sparse library reference
Theano2 1 11 基礎知識之稀疏
來自 sparse 通常來說,稀疏矩陣可以和常規矩陣一樣提供相同的功能。兩者不同之處在於在記憶體中儲存矩陣和表示矩陣的方式。在稀疏矩陣中,只有非0元素才會被儲存。這種方式帶來的優點有 首先,這可以很明顯的減少記憶體的使用 第二 通過使用指定的稀疏演算法和這種稀疏儲存方法可以減少計算時間。我們通常將常...
Theano2 1 9 基礎知識之條件
來自 conditions example from theano import tensor as t from theano.ifelse import ifelse import theano,time,numpy a,b t.scalars a b x,y t.matrices x y z ...
Theano2 1 9 基礎知識之條件
來自 conditions example from theano import tensor as t from theano.ifelse import ifelse import theano,time,numpy a,b t.scalars a b x,y t.matrices x y z ...