作者:chen_h
微訊號 & QQ:862251340
微信公眾號:coderpai
我的部落格:請點選這裡
計劃現將 tensorflow 中的 Python API 做一個學習,這樣方便以後的學習。
原文連結
該章介紹有關稀疏張量的API
稀疏張量表示
對於多維稀疏資料,TensorFlow提供了稀疏張量表示。稀疏張量裡面的值都是採用IndexedSlices
索引來表示,這樣能更加高效的表示資料。
class tf.SparseTensor
解釋:這個函式的作用是表示一個稀疏張量。
Tensorflow使用三個密集張量:indices
,values
,dense_shape
,來表示一個稀疏張量。在Python介面中,這三個張量被整合到一個SparseTensor
類中,如果你調換了這三個密集張量的位置,那麼在進行操作之前,SparseTensor
類會自動調換三個張量的位置。
具體的說,稀疏張量表示為SparseTensor(values, indices, dense_shape)
:
indices
: 一個二維的張量,資料型別是int64
,資料維度是[N, ndims]
。values
: 一個一維的張量,資料型別是任意的,資料維度是[N]
。dense_shape
: 一個一維的張量,資料型別是int64
,資料維度是[ndims]
。
其中,N
表示稀疏張量中存在N
個值,ndims
表示SparseTensor
的維度。
相應的密集張量滿足:
dense.shape = dense_shape
dense[tuple(indices[i])] = values[i]複製程式碼
按照慣例,indices
中的索引應該按照從小到大的順序排序。SparseTensor
中三個密集張量的順序不是強制的,你可以亂序,SparseTensor
會自動將它排序。
比如:
SparseTensor(values=[1, 2], indices=[[0, 0], [1, 2]], shape=[3, 4])複製程式碼
那麼密集張量就是:
[[1, 0, 0, 0]
[0, 0, 2, 0]
[0, 0, 0, 0]]複製程式碼
tf.SparseTensor.__init__(indices, values, shape)
解釋:這個函式的作用是構建一個SparseTensor
。
輸入引數:
indices
: 一個二維的張量,資料型別是int64
,資料維度是[N, ndims]
。values
: 一個一維的張量,資料型別是任意的,資料維度是[N]
。dense_shape
: 一個一維的張量,資料型別是int64
,資料維度是[ndims]
。
輸出引數:
* 一個稀疏張量SparseTensor
。
tf.SparseTensor.indices
解釋:這個函式的作用是取出密集矩陣中非零值得索引。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices=[[4, 1], [1, 2]], values=[1, 2], shape=[3, 4])
b = a.indices
sess = tf.Session()
print sess.run(a)
print sess.run(b)
sess.close()複製程式碼
輸出引數:
* 一個二維的張量,資料型別是int64
,資料維度是[N, ndims]
。其中,N
表示在稀疏張量中非零值的個數,ndims
表示稀疏張量的秩。
tf.SparseTensor.values
解釋:這個函式的作用是取出密集矩陣中非零值。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices=[[4, 1], [1, 2]], values=[1, 2], shape=[3, 4])
b = a.values
sess = tf.Session()
print sess.run(a)
print sess.run(b)
sess.close()複製程式碼
輸出引數:
* 一個一維的張量,資料型別是任意的。
tf.SparseTensor.dtype
解釋:這個函式的作用是返回張量中元素的型別。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices=[[4, 1], [1, 2]], values=tf.constant([1, 2]), shape=[3, 4])
b = a.dtype
sess = tf.Session()
print b
sess.close()複製程式碼
輸出引數:
- 返回張量中元素的型別。
tf.SparseTensor.shape
解釋:這個函式的作用是返回稀疏張量的維度。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices=[[4, 1], [1, 2]], values=tf.constant([1, 2]), shape=[3, 4])
b = a.shape
sess = tf.Session()
print sess.run(b)
sess.close()複製程式碼
輸出引數:
- 返回稀疏張量的維度。
tf.SparseTensor.graph
解釋:這個函式的作用是返回包含該稀疏張量的圖。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices=[[4, 1], [1, 2]], values=tf.constant([1, 2]), shape=[3, 4])
b = a.graph
sess = tf.Session()
print b
sess.close()複製程式碼
輸出引數:
- 返回包含該稀疏張量的圖。
class tf.SparseTensorValue
解釋:這個函式的作用是檢視設定稀疏張量的值。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensorValue(indices=[[4, 1], [1, 2]], values=tf.constant([1, 2]), shape=[3, 4])
sess = tf.Session()
print a
print a[0]
print a[1]
print a[2]
sess.close()複製程式碼
tf.SparseTensorValue.indices
解釋:這個函式的作用是返回稀疏張量中值的存在位置。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensorValue(indices=[[4, 1], [1, 2]], values=tf.constant([1, 2]), shape=[3, 4])
sess = tf.Session()
print a.indices
sess.close()複製程式碼
輸出引數:
- 返回稀疏張量中值的存在位置。
tf.SparseTensorValue.shape
解釋:這個函式的作用是返回稀疏張量的維度。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensorValue(values=tf.constant([1, 2]), indices=[[4, 1], [1, 2]], shape=[3, 4])
sess = tf.Session()
print a.shape
sess.close()複製程式碼
輸出引數:
- 返回稀疏張量的維度。
tf.SparseTensorValue.shape
解釋:這個函式的作用是返回稀疏張量中的元素。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensorValue(values=tf.constant([1, 2]), indices=[[4, 1], [1, 2]], shape=[3, 4])
sess = tf.Session()
print sess.run(a.values) # 這是一個張量,所以用sess.run()
sess.close()複製程式碼
輸出引數:
- 返回稀疏張量中的元素。
稀疏張量與密集張量的轉換
TensorFlow提供了稀疏張量與密集張量之間的轉換操作。
tf.sparse_to_dense(sparse_indices, output_shape, sparse_values, default_value, name=None)
解釋:這個函式的作用是將一個稀疏表示轉換成一個密集張量。具體將稀疏張量sparse
轉換成密集張量dense
如下:
# If sparse_indices is scalar
dense[i] = (i == sparse_indices ? sparse_values : default_value)
# If sparse_indices is a vector, then for each i
dense[sparse_indices[i]] = sparse_values[i]
# If sparse_indices is an n by d matrix, then for each i in [0, n)
dense[sparse_indices[i][0], ..., sparse_indices[i][d-1]] = sparse_values[i]複製程式碼
預設情況下,dense
中的填充值default_value
都是0
,除非該值被設定成一個標量。
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.sparse_to_dense(sparse_indices = [[1,2],[2,1]], output_shape = [3,3],
sparse_values = [2,3], default_value = 1)
sess = tf.Session()
print sess.run(a)
sess.close()複製程式碼
輸入引數:
sparse_indices
: 一個Tensor
,資料型別必須是int32
或者int64
。資料維度0維,一維或者二維都可以,或者更加高緯度的sparse_indices[i]
。output_shape
: 一個Tensor
,資料型別必須和sparse_indices
相同。資料維度是一維,表示輸出密集張量的維度。sparse_values
: 一個Tensor
,資料維度是一維,其中的每一個元素對應sparse_indices
中座標的值。default_value
: 一個Tensor
,資料型別必須和sparse_values
相同,資料維度是一個標量。設定稀疏索引不指定的值。name
: (可選)為這個操作取一個名字。
輸出引數:
- 一個
Tensor
,資料型別和sparse_values
相同。密集張量的資料維度是output_shape
。
tf.sparse_tensor_to_dense(sp_input, default_value, name=None)
解釋:這個函式的作用是將一個稀疏張量SparseTensor
轉換成一個密集張量。
這個操作是一個便利的將稀疏張量轉換成密集張量的方法。
比如,sp_input
的資料維度是[3, 5]
,非空值為:
[0, 1]: a
[0, 3]: b
[2, 0]: c複製程式碼
default_value
值為x
,那麼輸出的密集張量的維度是[3, 5]
,具體的展示形式如下:
[[x a x b x]
[x x x x x]
[c x x x x]]複製程式碼
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices = [[0, 1], [0, 3], [2, 0]], values=[1,2,3], shape=[3, 5])
b = tf.sparse_tensor_to_dense(a, default_value = 11)
sess = tf.Session()
print sess.run(b)
sess.close()複製程式碼
輸入引數:
sp_input
: 一個SparseTensor
。default_value
: 資料維度是一個標量,設定稀疏索引不指定的值。name
: (可選)設定返回張量名稱的字首。
輸出引數:
- 一個密集張量,資料維度是
sp_input.shape
,密集張量裡面的值為sp_input
中指定的值,沒有索引的值為default_value
值。
異常:
型別錯誤
: 如果sp_input
不是一個SparseTensor
,將報錯。
tf.sparse_to_indicator(sp_input, vocab_size, name=None)
解釋:這個函式的作用是將稀疏張量SparseTensor
的座標轉換成密集張量中的布林座標。
sp_input
中的最後一維被丟棄,並且用sp_input
在該位的值來代替,如果sp_input.shape = [D0, D1, D2, ..., Dn, K]
,其中K
是最後一維,那麼output.shape = [D0, D1, D2, ..., Dn, vocab_size]
,其中:
output[d_0, d_1, ..., d_n, sp_input[d_0, d_1, ..., d_n, k]] = True複製程式碼
output
中其餘值為False
。
比如,sp_input.shape = [2, 3, 4]
,非空值如下:
[0, 0, 0]: 0
[0, 1, 0]: 10
[1, 0, 3]: 103
[1, 1, 2]: 112
[1, 1, 3]: 113
[1, 2, 1]: 121複製程式碼
並且vocab_size = 200
,那麼輸出output.shape = [2, 3, 200]
,並且output
中的值都是False
,除了以下位置:
(0, 0, 0), (0, 1, 10), (1, 0, 103), (1, 1, 112), (1, 1, 113), (1, 2, 121).複製程式碼
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices = [[0, 1], [0, 3], [2, 0]], values=[1,2,3], shape=[3, 5])
b = tf.sparse_to_indicator(a, 10)
sess = tf.Session()
print sess.run(b)
sess.close()複製程式碼
輸入引數:
sp_input
: 一個SparseTensor
,資料型別是int32
或者int64
。vocab_size
:sp_Input
最後一維的新的維度,並且0 <= sp_input.shape > vocab_size
。name
: (可選)設定返回張量名稱的字首。
輸出引數:
- 一個經過修改的密集布林張量。
異常:
型別錯誤
: 如果sp_input
不是一個SparseTensor
,將報錯。
稀疏張量的操作
TensorFlow提供了一些對於稀疏張量的操作函式。
tf.sparse_concat(concat_dim, sp_inputs, name=None)
解釋:這個函式的作用是將一系列的SparseTensor
,按照指定的維度進行合併。
具體合併思路是,先將稀疏張量看成是一個密集張量,然後按照指定的維度進行張量合併,最後將合併成的密集張量看成是一個稀疏張量。
輸入的資料中,SparseTensor
的資料維度必須是相同的,並且indices
,values
和shapes
的長度必須相同。
輸出資料的維度將由輸入資料的維度決定,除了需要合併的那一維度,這一維度是所有資料該維度的相加總和。
輸出張量中的元素將會被重新儲存在稀疏張量中,並且按照原來的順序進行排序。
這個操作的時間複雜度是O(M log M)
,其中,M
是輸入資料中所有非空元素的個數總和。
比如,當concat_dim = 1
時:
sp_inputs[0]: shape = [2, 3]
[0, 2]: "a"
[1, 0]: "b"
[1, 1]: "c"
sp_inputs[1]: shape = [2, 4]
[0, 1]: "d"
[0, 2]: "e"複製程式碼
那麼輸出資料為:
shape = [2, 7]
[0, 2]: "a"
[0, 4]: "d"
[0, 5]: "e"
[1, 0]: "b"
[1, 1]: "c"複製程式碼
用圖形表示,如下:
[ a] concat [ d e ] = [ a d e ]
[b c ] [ ] [b c ]複製程式碼
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices = [[0, 1], [0, 3], [2, 0]], values=[1,2,3], shape=[3, 5])
aa = tf.SparseTensor(indices = [[1, 1], [1, 3], [2, 1]], values=[11,12,13], shape=[3, 5])
b = tf.sparse_concat(0, [a, aa])
sess = tf.Session()
print sess.run(b)
print sess.run(tf.sparse_tensor_to_dense(b))
sess.close()複製程式碼
輸入引數:
concat_dim
: 需要合併的維度。sp_inputs
: 一個需要合併的SparseTensor
列表。name
: (可選)設定返回張量名稱的字首。
輸出引數:
- 一個經過合併的
SparseTensor
。
異常:
型別錯誤
: 如果sp_inputs
不是一個SparseTensor
列表。
tf.sparse_reorder(sp_input, name=None)
解釋:這個函式的作用是將SparseTensor
中的元素進行重新排列,按照索引從小到大進行排序。
重排列不會影響SparseTensor
的維度。
比如,如果sp_input
的維度是[4, 5]
,indices
/ values
如下:
[0, 3]: b
[0, 1]: a
[3, 1]: d
[2, 0]: c複製程式碼
那麼輸出的SparseTensor
的維度還是[4, 5]
,indices
/ values
如下:
[0, 1]: a
[0, 3]: b
[2, 0]: c
[3, 1]: d複製程式碼
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices = [[2, 1], [0, 3], [2, 0]], values=[1,2,3], shape=[3, 5])
b = tf.sparse_reorder(a)
sess = tf.Session()
print sess.run(b)
sess.close()複製程式碼
輸入引數:
sp_input
: 一個SparseTensor
。name
: (可選)設定返回張量名稱的字首。
輸出引數:
- 一個
SparseTensor
,資料維度和資料型別都不變,只有其中的值進行了有序的排序。
異常:
型別錯誤
: 如果sp_input
不是一個SparseTensor
。
tf.sparse_retain(sp_input, to_retain, name=None)
解釋:這個函式的作用是保留SparseTensor
中指定的非空元素。
比如,如果sp_input
的資料維度是[4, 5]
,並且擁有4個非空值如下:
[0, 1]: a
[0, 3]: b
[2, 0]: c
[3, 1]: d複製程式碼
而且to_retain = [True, False, False, True]
,那麼最後輸出資料SparseTensor
的資料維度是[4, 5]
,並且保留兩個非空值如下:
[0, 1]: a
[3, 1]: d複製程式碼
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices = [[2, 1], [0, 3], [2, 0]], values=[1,2,3], shape=[3, 5])
b = tf.sparse_retain(a, [False, False, True])
sess = tf.Session()
print sess.run(b)
sess.close()複製程式碼
輸入引數:
sp_input
: 一個SparseTensor
,包含N
個非空元素。to_retain
: 一個布林型別的向量,向量長度是N
,並且其中包含M
個True
值。
輸出引數:
- 一個
SparseTensor
,資料維度和輸入資料相同,其中包含M
個非空值,該值的位置根據True
的位置來決定。
異常:
型別錯誤
: 如果sp_input
不是一個SparseTensor
。
tf.sparse_fill_empty_rows(sp_input, default_value, name=None)
解釋:這個函式的作用是將二維的SparseTensor
中,將空的行中填充指定元素的值。
如果一行中不存在元素,那麼就將改行的座標[row, 0]
填上default_value
。
比如,我們假設sp_input
的資料維度是[5, 6]
,並且非空值如下:
[0, 1]: a
[0, 3]: b
[2, 0]: c
[3, 1]: d複製程式碼
因為在稀疏張量中,第一行和第四行中不存在值,那麼我們需要在[1, 0]
和[4, 0]
座標填上default_value
,如下:
[0, 1]: a
[0, 3]: b
[1, 0]: default_value
[2, 0]: c
[3, 1]: d
[4, 0]: default_value複製程式碼
請注意,輸入可能有空列在最後,但對這個操作沒有任何影響。
輸出的SparseTensor
將是一個按照從小到大的順序進行排序,並且輸出資料和輸入資料擁有相同的資料維度。
這個操作還會返回一個布林向量,其中的布林值,如果是True
值,那麼表示該行新增了一個default_value
,計算公式如下:
empty_row_indicator[i] = True iff row i was an empty row.複製程式碼
使用例子:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tensorflow as tf
import numpy as np
a = tf.SparseTensor(indices = [[2, 1], [0, 3], [2, 0]], values=[1,2,3], shape=[6, 5])
b, bb = tf.sparse_fill_empty_rows(a, 10)
sess = tf.Session()
print sess.run(b)
print `----`
print sess.run(bb)
sess.close()複製程式碼
輸入引數:
sp_input
: 一個SparseTensor
,資料維度是[N, M]
。default_value
: 需要向空行填充的值,資料型別和sp_input
相同。name
: (可選)設定返回張量名稱的字首。
輸出引數:
sp_ordered_output
: 一個SparseTensor
,資料維度是[N, M]
,並且其中所有空行填充了default_value
。empty_row_indicator
: 一個布林型別的向量,資料長度是N
,如果該行填充了default_value
,那麼該位置的布林值為True
。
異常:
型別錯誤
: 如果sp_input
不是一個SparseTensor
。
CoderPai 是一個專注於演算法實戰的平臺,從基礎的演算法到人工智慧演算法都有設計。如果你對演算法實戰感興趣,請快快關注我們吧。加入AI實戰微信群,AI實戰QQ群,ACM演算法微信群,ACM演算法QQ群。詳情請關注 “CoderPai” 微訊號(coderpai) 。