TensorFlow.org'da görüntüleyin | Google Colab'da çalıştırın | GitHub'da görüntüle | Not defterini indir |
Çok sayıda sıfır değeri içeren tensörlerle çalışırken, bunları yer ve zaman açısından verimli bir şekilde depolamak önemlidir. Seyrek tensörler, çok sayıda sıfır değeri içeren tensörlerin verimli bir şekilde depolanmasını ve işlenmesini sağlar. Seyrek tensörler, NLP uygulamalarında veri ön işlemenin bir parçası olarak TF-IDF gibi kodlama şemalarında ve bilgisayarla görme uygulamalarında çok sayıda koyu piksel içeren görüntülerin ön işlemesi için yaygın olarak kullanılmaktadır.
TensorFlow'da seyrek tensörler
TensorFlow, tf.SparseTensor
nesnesi aracılığıyla seyrek tensörleri temsil eder. Şu anda, TensorFlow'daki seyrek tensörler, koordinat listesi (COO) formatı kullanılarak kodlanmıştır. Bu kodlama biçimi, yerleştirmeler gibi aşırı seyrek matrisler için optimize edilmiştir.
Seyrek tensörler için COO kodlaması şunlardan oluşur:
-
values
: Tüm sıfır olmayan değerleri içeren[N]
şeklinde bir 1D tensör. -
indices
: Sıfır olmayan değerlerin indekslerini içeren[N, rank]
şeklinde bir 2B tensör. -
dense_shape
: Tensörün şeklini belirten[rank]
şekilli bir 1D tensör.
tf.SparseTensor
bağlamında sıfır olmayan bir değer, açıkça kodlanmamış bir değerdir. Bir COO seyrek matrisinin values
açıkça sıfır değerleri eklemek mümkündür, ancak bu "açık sıfırlar" genellikle bir seyrek tensörde sıfır olmayan değerlere atıfta bulunulduğunda dahil edilmez.
Bir tf.SparseTensor
oluşturma
values
, indices
ve dense_shape
doğrudan belirterek seyrek tensörler oluşturun.
import tensorflow as tf
tutucu1 l10n-yerst1 = tf.SparseTensor(indices=[[0, 3], [2, 4]],
values=[10, 20],
dense_shape=[3, 10])
Bir seyrek tensörü yazdırmak için print()
işlevini kullandığınızda, üç bileşen tensörünün içeriğini gösterir:
print(st1)
tutucu3 l10n-yerSparseTensor(indices=tf.Tensor( [[0 3] [2 4]], shape=(2, 2), dtype=int64), values=tf.Tensor([10 20], shape=(2,), dtype=int32), dense_shape=tf.Tensor([ 3 10], shape=(2,), dtype=int64))
Sıfırdan farklı values
karşılık gelen indices
hizalanırsa, seyrek bir tensörün içeriğini anlamak daha kolaydır. Seyrek tensörleri, sıfırdan farklı her değer kendi satırında gösterilecek şekilde güzel bir şekilde yazdırmak için bir yardımcı işlev tanımlayın.
def pprint_sparse_tensor(st):
s = "<SparseTensor shape=%s \n values={" % (st.dense_shape.numpy().tolist(),)
for (index, value) in zip(st.indices, st.values):
s += f"\n %s: %s" % (index.numpy().tolist(), value.numpy().tolist())
return s + "}>"
print(pprint_sparse_tensor(st1))
-yer tutucu6 l10n-yer<SparseTensor shape=[3, 10] values={ [0, 3]: 10 [2, 4]: 20}>
Ayrıca tf.sparse.from_dense kullanarak yoğun tensörlerden seyrek tensörler oluşturabilir ve tf.sparse.from_dense
kullanarak bunları yoğun tensörlere tf.sparse.to_dense
.
st2 = tf.sparse.from_dense([[1, 0, 0, 8], [0, 0, 0, 0], [0, 0, 3, 0]])
print(pprint_sparse_tensor(st2))
<SparseTensor shape=[3, 4] values={ [0, 0]: 1 [0, 3]: 8 [2, 2]: 3}>yer tutucu9 l10n-yer
st3 = tf.sparse.to_dense(st2)
print(st3)
tf.Tensor( [[1 0 0 8] [0 0 0 0] [0 0 3 0]], shape=(3, 4), dtype=int32)
Seyrek tensörleri manipüle etme
Seyrek tensörleri işlemek için tf.sparse
paketindeki yardımcı programları kullanın. Yoğun tensörlerin aritmetik manipülasyonu için kullanabileceğiniz tf.math.add
gibi işlemler seyrek tensörlerle çalışmaz.
tf.sparse.add
kullanarak aynı şekle sahip seyrek tensörler ekleyin.
st_a = tf.SparseTensor(indices=[[0, 2], [3, 4]],
values=[31, 2],
dense_shape=[4, 10])
st_b = tf.SparseTensor(indices=[[0, 2], [7, 0]],
values=[56, 38],
dense_shape=[4, 10])
st_sum = tf.sparse.add(st_a, st_b)
print(pprint_sparse_tensor(st_sum))
tutucu12 l10n-yer<SparseTensor shape=[4, 10] values={ [0, 2]: 87 [3, 4]: 2 [7, 0]: 38}>
Seyrek tensörleri yoğun matrislerle çarpmak için tf.sparse.sparse_dense_matmul
kullanın.
st_c = tf.SparseTensor(indices=([0, 1], [1, 0], [1, 1]),
values=[13, 15, 17],
dense_shape=(2,2))
mb = tf.constant([[4], [6]])
product = tf.sparse.sparse_dense_matmul(st_c, mb)
print(product)
tutucu14 l10n-yertf.Tensor( [[ 78] [162]], shape=(2, 1), dtype=int32)
Seyrek tensörleri tf.sparse.concat kullanarak bir araya getirin ve tf.sparse.concat
kullanarak tf.sparse.slice
.
sparse_pattern_A = tf.SparseTensor(indices = [[2,4], [3,3], [3,4], [4,3], [4,4], [5,4]],
values = [1,1,1,1,1,1],
dense_shape = [8,5])
sparse_pattern_B = tf.SparseTensor(indices = [[0,2], [1,1], [1,3], [2,0], [2,4], [2,5], [3,5],
[4,5], [5,0], [5,4], [5,5], [6,1], [6,3], [7,2]],
values = [1,1,1,1,1,1,1,1,1,1,1,1,1,1],
dense_shape = [8,6])
sparse_pattern_C = tf.SparseTensor(indices = [[3,0], [4,0]],
values = [1,1],
dense_shape = [8,6])
sparse_patterns_list = [sparse_pattern_A, sparse_pattern_B, sparse_pattern_C]
sparse_pattern = tf.sparse.concat(axis=1, sp_inputs=sparse_patterns_list)
print(tf.sparse.to_dense(sparse_pattern))
tf.Tensor( [[0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0] [0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0] [0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0] [0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0] [0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0] [0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0]], shape=(8, 17), dtype=int32)yer tutucu17 l10n-yer
sparse_slice_A = tf.sparse.slice(sparse_pattern_A, start = [0,0], size = [8,5])
sparse_slice_B = tf.sparse.slice(sparse_pattern_B, start = [0,5], size = [8,6])
sparse_slice_C = tf.sparse.slice(sparse_pattern_C, start = [0,10], size = [8,6])
print(tf.sparse.to_dense(sparse_slice_A))
print(tf.sparse.to_dense(sparse_slice_B))
print(tf.sparse.to_dense(sparse_slice_C))
tf.Tensor( [[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 1] [0 0 0 1 1] [0 0 0 1 1] [0 0 0 0 1] [0 0 0 0 0] [0 0 0 0 0]], shape=(8, 5), dtype=int32) tf.Tensor( [[0] [0] [1] [1] [1] [1] [0] [0]], shape=(8, 1), dtype=int32) tf.Tensor([], shape=(8, 0), dtype=int32)
TensorFlow 2.4 veya üstünü kullanıyorsanız, seyrek tensörlerde sıfır olmayan değerler üzerinde eleman bazında işlemler için tf.sparse.map_values
kullanın.
st2_plus_5 = tf.sparse.map_values(tf.add, st2, 5)
print(tf.sparse.to_dense(st2_plus_5))
tutucu20 l10n-yertf.Tensor( [[ 6 0 0 13] [ 0 0 0 0] [ 0 0 8 0]], shape=(3, 4), dtype=int32)
Yalnızca sıfır olmayan değerlerin değiştirildiğini unutmayın - sıfır değerleri sıfır olarak kalır.
Benzer şekilde, TensorFlow'un önceki sürümleri için aşağıdaki tasarım modelini takip edebilirsiniz:
st2_plus_5 = tf.SparseTensor(
st2.indices,
st2.values + 5,
st2.dense_shape)
print(tf.sparse.to_dense(st2_plus_5))
tutucu22 l10n-yertf.Tensor( [[ 6 0 0 13] [ 0 0 0 0] [ 0 0 8 0]], shape=(3, 4), dtype=int32)
Diğer TensorFlow API'leri ile tf.SparseTensor
kullanma
Seyrek tensörler, bu TensorFlow API'leriyle şeffaf bir şekilde çalışır:
-
tf.keras
-
tf.data
-
tf.Train.Example
-
tf.function
-
tf.while_loop
-
tf.cond
-
tf.identity
-
tf.cast
-
tf.print
-
tf.saved_model
-
tf.io.serialize_sparse
-
tf.io.serialize_many_sparse
-
tf.io.deserialize_many_sparse
-
tf.math.abs
-
tf.math.negative
-
tf.math.sign
-
tf.math.square
-
tf.math.sqrt
-
tf.math.erf
-
tf.math.tanh
-
tf.math.bessel_i0e
-
tf.math.bessel_i1e
Yukarıdaki API'lerden birkaçı için örnekler aşağıda gösterilmiştir.
tf.keras
tf.keras
API'sinin bir alt kümesi, pahalı döküm veya dönüştürme işlemleri olmadan seyrek tensörleri destekler. Keras API, seyrek tensörleri bir Keras modeline girdi olarak geçirmenizi sağlar. tf.keras.Input
veya tf.keras.layers.InputLayer
çağrılırken sparse=True
ayarlayın. Seyrek tensörleri Keras katmanları arasında geçirebilir ve ayrıca Keras modellerinin bunları çıktı olarak döndürmesini sağlayabilirsiniz. tf.keras.layers.Dense
katmanlarında seyrek tensörler kullanırsanız, bunlar yoğun tensörler verir.
Aşağıdaki örnek, yalnızca seyrek girdileri destekleyen katmanlar kullanıyorsanız, bir Keras modeline girdi olarak seyrek bir tensörü nasıl ileteceğinizi gösterir.
x = tf.keras.Input(shape=(4,), sparse=True)
y = tf.keras.layers.Dense(4)(x)
model = tf.keras.Model(x, y)
sparse_data = tf.SparseTensor(
indices = [(0,0),(0,1),(0,2),
(4,3),(5,0),(5,1)],
values = [1,1,1,1,1,1],
dense_shape = (6,4)
)
model(sparse_data)
model.predict(sparse_data)
tutucu24 l10n-yerarray([[-1.3111044 , -1.7598825 , 0.07225233, -0.44544357], [ 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. ], [ 0. , 0. , 0. , 0. ], [ 0.8517609 , -0.16835624, 0.7307872 , -0.14531797], [-0.8916302 , -0.9417639 , 0.24563438, -0.9029659 ]], dtype=float32)
tf.data
tf.data
API, basit, yeniden kullanılabilir parçalardan karmaşık girdi ardışık düzenleri oluşturmanıza olanak tanır. Temel veri yapısı, her öğenin bir veya daha fazla bileşenden oluştuğu bir dizi öğeyi temsil eden tf.data.Dataset
.
Seyrek tensörlerle veri kümeleri oluşturma
Veri kümelerini tf.Tensor
s veya NumPy dizilerinden oluşturmak için kullanılan yöntemlerin aynısını kullanarak seyrek tensörlerden veri kümeleri oluşturun, örneğin tf.data.Dataset.from_tensor_slices
. Bu işlem, verilerin seyrekliğini (veya seyrek doğasını) korur.
dataset = tf.data.Dataset.from_tensor_slices(sparse_data)
for element in dataset:
print(pprint_sparse_tensor(element))
tutucu26 l10n-yer<SparseTensor shape=[4] values={ [0]: 1 [1]: 1 [2]: 1}> <SparseTensor shape=[4] values={}> <SparseTensor shape=[4] values={}> <SparseTensor shape=[4] values={}> <SparseTensor shape=[4] values={ [3]: 1}> <SparseTensor shape=[4] values={ [0]: 1 [1]: 1}>
Seyrek tensörlerle veri kümelerini gruplama ve gruplamadan çıkarma
Sırasıyla Dataset.batch
ve Dataset.unbatch
yöntemlerini kullanarak toplu işleyebilir (ardışık öğeleri tek bir öğede birleştirebilir) ve seyrek tensörlerle veri kümelerini çözebilirsiniz.
batched_dataset = dataset.batch(2)
for element in batched_dataset:
print (pprint_sparse_tensor(element))
<SparseTensor shape=[2, 4] values={ [0, 0]: 1 [0, 1]: 1 [0, 2]: 1}> <SparseTensor shape=[2, 4] values={}> <SparseTensor shape=[2, 4] values={ [0, 3]: 1 [1, 0]: 1 [1, 1]: 1}>yer tutucu29 l10n-yer
unbatched_dataset = batched_dataset.unbatch()
for element in unbatched_dataset:
print (pprint_sparse_tensor(element))
<SparseTensor shape=[4] values={ [0]: 1 [1]: 1 [2]: 1}> <SparseTensor shape=[4] values={}> <SparseTensor shape=[4] values={}> <SparseTensor shape=[4] values={}> <SparseTensor shape=[4] values={ [3]: 1}> <SparseTensor shape=[4] values={ [0]: 1 [1]: 1}>
tf.data.experimental.dense_to_sparse_batch
, farklı şekillerdeki veri kümesi öğelerini seyrek tensörler halinde gruplamak için de kullanabilirsiniz.
Seyrek tensörlerle Veri Kümelerini Dönüştürme
Dataset.map
kullanarak Veri Kümelerinde seyrek tensörleri dönüştürün ve oluşturun.
transform_dataset = dataset.map(lambda x: x*2)
for i in transform_dataset:
print(pprint_sparse_tensor(i))
tutucu32 l10n-yer<SparseTensor shape=[4] values={ [0]: 2 [1]: 2 [2]: 2}> <SparseTensor shape=[4] values={}> <SparseTensor shape=[4] values={}> <SparseTensor shape=[4] values={}> <SparseTensor shape=[4] values={ [3]: 2}> <SparseTensor shape=[4] values={ [0]: 2 [1]: 2}>
tf.tren.Örnek
tf.train.Example
, TensorFlow verileri için standart bir protobuf kodlamasıdır. tf.train.Example
ile seyrek tensörler kullanırken şunları yapabilirsiniz:
tf.SparseTensor
kullanarak değişken uzunluklu verileri birtf.io.VarLenFeature
. Ancak bunun yerinetf.io.RaggedFeature
kullanmayı düşünmelisiniz.indices
,values
vedense_shape
depolamak için üç ayrı özellik anahtarı kullanantf.io.SparseFeature
kullanarak rastgele seyrek verileri birtf.SparseTensor
okuyun.
tf.function
tf.function
dekoratörü, TensorFlow kodunuzun performansını önemli ölçüde artırabilen Python işlevleri için TensorFlow grafiklerini önceden hesaplar. Seyrek tensörler hem tf.function
hem de somut işlevlerle şeffaf bir şekilde çalışır.
@tf.function
def f(x,y):
return tf.sparse.sparse_dense_matmul(x,y)
a = tf.SparseTensor(indices=[[0, 3], [2, 4]],
values=[15, 25],
dense_shape=[3, 10])
b = tf.sparse.to_dense(tf.sparse.transpose(a))
c = f(a,b)
print(c)
tutucu34 l10n-yertf.Tensor( [[225 0 0] [ 0 0 0] [ 0 0 625]], shape=(3, 3), dtype=int32)
Eksik değerleri sıfır değerlerinden ayırt etme
tf.SparseTensor
s üzerindeki çoğu işlem, eksik değerleri ve açık sıfır değerlerini aynı şekilde ele alır. Bu tasarım gereğidir — bir tf.SparseTensor
tıpkı yoğun bir tensör gibi davranması gerekir.
Ancak, sıfır değerleri eksik değerlerden ayırmanın faydalı olabileceği birkaç durum vardır. Özellikle, bu, eğitim verilerinizdeki eksik/bilinmeyen verileri kodlamanın bir yolunu sağlar. Örneğin, puanların tensörünün (-Inf ile +Inf arasında herhangi bir kayan nokta değerine sahip olabilen) ve bazı eksik puanların olduğu bir kullanım durumunu düşünün. Bu tensörü, açık sıfırların bilinen sıfır puanları olduğu ancak örtülü sıfır değerlerinin aslında eksik verileri temsil ettiği ve sıfırı temsil etmediği seyrek bir tensör kullanarak kodlayabilirsiniz.
tf.sparse.reduce_max gibi bazı işlemlerin eksik değerleri tf.sparse.reduce_max
gibi işlemediğini unutmayın. Örneğin, aşağıdaki kod bloğunu çalıştırdığınızda, beklenen çıktı 0
. Ancak, bu istisna nedeniyle çıktı -3
.
print(tf.sparse.reduce_max(tf.sparse.from_dense([-5, 0, -3])))
tutucu36 l10n-yertf.Tensor(-3, shape=(), dtype=int32)
Buna karşılık, yoğun bir tf.math.reduce_max
uyguladığınızda, çıktı beklendiği gibi 0 olur.
print(tf.math.reduce_max([-5, 0, -3]))
tutucu38 l10n-yertf.Tensor(0, shape=(), dtype=int32)
Daha fazla okuma ve kaynaklar
- Tensörler hakkında bilgi edinmek için tensör kılavuzuna bakın.
- Düzgün olmayan verilerle çalışmanıza olanak tanıyan bir tür tensör olan düzensiz tensörlerle nasıl çalışılacağını öğrenmek için düzensiz tensör kılavuzunu okuyun.
- Bir
tf.Example
veri kod çözücüde seyrek tensörler kullanan TensorFlow Model Garden'daki bu nesne algılama modeline göz atın.