عرض على TensorFlow.org | تشغيل في Google Colab | عرض على جيثب | تحميل دفتر |
عند العمل مع الموترات التي تحتوي على الكثير من القيم الصفرية ، من المهم تخزينها بطريقة فعالة من حيث المساحة والوقت. تتيح الموترات المتفرقة التخزين الفعال ومعالجة الموترات التي تحتوي على الكثير من القيم الصفرية. تُستخدم الموترات المتفرقة على نطاق واسع في مخططات التشفير مثل TF-IDF كجزء من المعالجة المسبقة للبيانات في تطبيقات البرمجة اللغوية العصبية ومعالجة الصور مسبقًا مع الكثير من وحدات البكسل المظلمة في تطبيقات رؤية الكمبيوتر.
موترات متفرقة في TensorFlow
يمثل TensorFlow موترات متفرقة من خلال كائن tf.SparseTensor
. حاليًا ، يتم ترميز الموترات المتفرقة في TensorFlow باستخدام تنسيق قائمة الإحداثيات (COO). تم تحسين تنسيق الترميز هذا للمصفوفات شديدة التباين مثل حفلات الزفاف.
يتكون ترميز COO للموترات المتفرقة من:
-
values
: موتر 1D مع شكل[N]
يحتوي على جميع القيم غير الصفرية. -
indices
: موتر ثنائي الأبعاد ذو شكل[N, rank]
، يحتوي على مؤشرات القيم غير الصفرية. -
dense_shape
: موتر 1D بالشكل[rank]
، يحدد شكل موتر.
القيمة غير الصفرية في سياق tf.SparseTensor
هي قيمة غير مشفرة بشكل صريح. من الممكن تضمين القيم الصفرية بشكل صريح في values
مصفوفة COO المتفرقة ، ولكن هذه "الأصفار الصريحة" لا يتم تضمينها بشكل عام عند الإشارة إلى قيم غير صفرية في موتر متفرق.
إنشاء tf.SparseTensor
dense_shape
متفرقة عن طريق تحديد values
indices
وشكلها الكثيف مباشرةً.
import tensorflow as tf
st1 = tf.SparseTensor(indices=[[0, 3], [2, 4]],
values=[10, 20],
dense_shape=[3, 10])
عندما تستخدم وظيفة print()
لطباعة موتر متفرق ، فإنها تعرض محتويات الموترات الثلاثة المكونة:
print(st1)
SparseTensor(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))
من الأسهل فهم محتويات الموتر المتفرق إذا كانت values
غير الصفرية محاذاة مع indices
المقابلة. حدد دالة مساعدة لطباعة الموترات المتناثرة بشكل جيد بحيث تظهر كل قيمة غير صفرية في السطر الخاص بها.
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))
<SparseTensor shape=[3, 10] values={ [0, 3]: 10 [2, 4]: 20}>
يمكنك أيضًا إنشاء موترات متفرقة من موترات كثيفة باستخدام tf.sparse.from_dense
، وتحويلها مرة أخرى إلى موترات كثيفة باستخدام 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}>
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)
معالجة الموترات المتفرقة
استخدم الأدوات المساعدة في حزمة tf.sparse
لمعالجة موترات متفرقة. عمليات مثل tf.math.add
التي يمكنك استخدامها للمعالجة الحسابية للموترات الكثيفة لا تعمل مع الموترات المتفرقة.
أضف موترات متفرقة من نفس الشكل باستخدام tf.sparse.add
.
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))
<SparseTensor shape=[4, 10] values={ [0, 2]: 87 [3, 4]: 2 [7, 0]: 38}>
استخدم tf.sparse.sparse_dense_matmul
لمضاعفة الموترات المتفرقة بمصفوفات كثيفة.
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)
tf.Tensor( [[ 78] [162]], shape=(2, 1), dtype=int32)
ضع الموترات المتناثرة معًا باستخدام tf.sparse.concat
بينها باستخدام 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)
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 أو أعلى ، فاستخدم tf.sparse.map_values
للعمليات الأولية على القيم غير الصفرية في الموترات المتفرقة.
st2_plus_5 = tf.sparse.map_values(tf.add, st2, 5)
print(tf.sparse.to_dense(st2_plus_5))
tf.Tensor( [[ 6 0 0 13] [ 0 0 0 0] [ 0 0 8 0]], shape=(3, 4), dtype=int32)
لاحظ أنه تم تعديل القيم غير الصفرية فقط - تظل القيم الصفرية صفرية.
بالتساوي ، يمكنك اتباع نمط التصميم أدناه للإصدارات السابقة من TensorFlow:
st2_plus_5 = tf.SparseTensor(
st2.indices,
st2.values + 5,
st2.dense_shape)
print(tf.sparse.to_dense(st2_plus_5))
tf.Tensor( [[ 6 0 0 13] [ 0 0 0 0] [ 0 0 8 0]], shape=(3, 4), dtype=int32)
استخدام tf.SparseTensor
مع واجهات برمجة تطبيقات TensorFlow الأخرى
تعمل الموترات المتفرقة بشفافية مع واجهات برمجة تطبيقات TensorFlow هذه:
-
tf.keras
-
tf.data
-
tf.Train.Example
protobuf -
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
يتم عرض الأمثلة أدناه لعدد قليل من واجهات برمجة التطبيقات المذكورة أعلاه.
tf.keras
تدعم مجموعة فرعية من واجهة برمجة تطبيقات tf.keras
المتفرقة دون عمليات الصب أو عمليات التحويل باهظة الثمن. تتيح لك Keras API تمرير الموترات المتفرقة كمدخلات لنموذج Keras. تعيين sparse=True
عند استدعاء tf.keras.Input
أو tf.keras.layers.InputLayer
. يمكنك تمرير موترات متفرقة بين طبقات Keras ، وكذلك جعل نماذج Keras تعيدها كمخرجات. إذا كنت تستخدم موترات متفرقة في tf.keras.layers.Dense
طبقات كثيفة في نموذجك ، فإنها ستنتج موترات كثيفة.
يوضح لك المثال أدناه كيفية تمرير موتر متفرق كمدخل إلى نموذج Keras إذا كنت تستخدم فقط الطبقات التي تدعم المدخلات المتفرقة.
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)
array([[-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
من إنشاء خطوط إدخال معقدة من قطع بسيطة قابلة لإعادة الاستخدام. هيكل البيانات الأساسي الخاص به هو tf.data.Dataset
، والذي يمثل سلسلة من العناصر التي يتكون فيها كل عنصر من مكون واحد أو أكثر.
بناء مجموعات البيانات باستخدام الموترات المتفرقة
قم ببناء مجموعات بيانات من الموترات المتفرقة باستخدام نفس الطرق المستخدمة لبناءها من tf.Tensor
s أو NumPy ، مثل tf.data.Dataset.from_tensor_slices
. هذا المرجع يحافظ على تناثر (أو طبيعة متفرقة) من البيانات.
dataset = tf.data.Dataset.from_tensor_slices(sparse_data)
for element in 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}>
تجميع مجموعات البيانات وفكها باستخدام موترات متفرقة
يمكنك تجميع (دمج العناصر المتتالية في عنصر واحد) ومجموعات البيانات غير المجمعة باستخدام موترات متفرقة باستخدام أساليب Dataset.batch
و Dataset.unbatch
على التوالي.
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}>
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
عناصر مجموعة البيانات ذات الأشكال المختلفة في موترات متفرقة.
تحويل مجموعات البيانات باستخدام موترات متفرقة
قم بتحويل وإنشاء موترات متفرقة في مجموعات البيانات باستخدام Dataset.map
.
transform_dataset = dataset.map(lambda x: x*2)
for i in transform_dataset:
print(pprint_sparse_tensor(i))
<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.train مثال
tf.train.Example
هو ترميز protobuf قياسي لبيانات TensorFlow. عند استخدام الموترات المتفرقة مع tf.train.Example
، على سبيل المثال ، يمكنك:
قراءة البيانات متغيرة الطول في
tf.SparseTensor
باستخدامtf.io.VarLenFeature
. ومع ذلك ، يجب أن تفكر في استخدامtf.io.RaggedFeature
بدلاً من ذلك.قراءة البيانات المتفرقة العشوائية في
tf.SparseTensor
باستخدامtf.io.SparseFeature
، والذي يستخدم ثلاثة مفاتيح ميزة منفصلة لتخزينindices
values
وشكلdense_shape
.
tf.function
يحسب مصمم وظيفة tf الرسوم البيانية tf.function
لوظائف Python ، والتي يمكن أن تحسن بشكل كبير من أداء كود TensorFlow الخاص بك. تعمل tf.function
المتفرقة بشفافية مع كل من وظيفة tf ووظائف الخرسانة .
@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)
tf.Tensor( [[225 0 0] [ 0 0 0] [ 0 0 625]], shape=(3, 3), dtype=int32)
تمييز القيم المفقودة من القيم الصفرية
معظم العمليات على tf.SparseTensor
تعالج القيم المفقودة والقيم الصفرية الصريحة بشكل مماثل. هذا حسب التصميم - من المفترض أن يتصرف جهاز tf.SparseTensor
تمامًا مثل موتر كثيف.
ومع ذلك ، هناك بعض الحالات التي قد يكون من المفيد فيها التمييز بين القيم الصفرية والقيم المفقودة. على وجه الخصوص ، يتيح ذلك طريقة واحدة لتشفير البيانات المفقودة / غير المعروفة في بيانات التدريب الخاصة بك. على سبيل المثال ، ضع في اعتبارك حالة استخدام حيث يكون لديك موتر من الدرجات (يمكن أن يكون لها أي قيمة فاصلة عائمة من -Inf إلى + Inf) ، مع بعض الدرجات المفقودة. يمكنك ترميز هذا الموتر باستخدام موتر متناثر حيث تُعرف الأصفار الصريحة بدرجات صفرية ولكن القيم الصفرية الضمنية تمثل في الواقع بيانات مفقودة وليست صفراً.
لاحظ أن بعض العمليات مثل tf.sparse.reduce_max
لا تعامل القيم المفقودة كما لو كانت صفرًا. على سبيل المثال ، عند تشغيل مقطع التعليمات البرمجية أدناه ، يكون الناتج المتوقع هو 0
. ومع ذلك ، وبسبب هذا الاستثناء ، يكون الناتج -3
.
print(tf.sparse.reduce_max(tf.sparse.from_dense([-5, 0, -3])))
tf.Tensor(-3, shape=(), dtype=int32)
في المقابل ، عند تطبيق tf.math.reduce_max
على موتر كثيف ، يكون الناتج 0 كما هو متوقع.
print(tf.math.reduce_max([-5, 0, -3]))
tf.Tensor(0, shape=(), dtype=int32)
مزيد من القراءة والموارد
- الرجوع إلى دليل الموتر للتعرف على موتر.
- اقرأ دليل الموتر الخشن لتتعلم كيفية التعامل مع الموترات الخشنة ، وهي نوع من الموترات التي تتيح لك العمل مع البيانات غير الموحدة.
- تحقق من نموذج اكتشاف الكائن في TensorFlow Model Garden الذي يستخدم
tf.Example
متفرقة في وحدة فك ترميز بيانات tf مثال .