דף זה תורגם על ידי Cloud Translation API.
Switch to English

טנורים מרופטים

צפה ב- TensorFlow.org הפעל בגוגל קולאב צפה במקור ב- GitHub הורד מחברת

תיעוד API:tf.RaggedTensor tf.ragged

להכין

import math
import tensorflow as tf

סקירה כללית

הנתונים שלך מגיעים בצורות רבות; גם הטנזורים שלך צריכים. טנזורים מרופטים הם המקבילה TensorFlow לרשימות מקוננות באורך משתנה. הם מקלים על אחסון ועיבוד נתונים בצורות לא אחידות, כולל:

  • מאפיינים באורך משתנה, כמו סט השחקנים בסרט.
  • אצוותות של תשומות רציפות באורך משתנה, כגון משפטים או וידיאו קליפים.
  • תשומות היררכיות, כגון מסמכי טקסט המחולקים לחלקים, פסקאות, משפטים ומילים.
  • שדות בודדים בקלטים מובנים, כגון מאגרי פרוטוקולים.

מה אתה יכול לעשות עם טנזור מרופט

טנזורים מרופטים נתמכים על ידי יותר ממאה פעולות TensorFlow, כולל פעולות מתמטיקה (כגון tf.add ו- tf.reduce_mean ), פעולות מערך (כגון tf.concat ו- tf.tile ), אופציות למניפולציות מחרוזות (כגון tf.substr ), פעולות בקרת זרימה (כגון tf.while_loop . tf.map_fn ו- tf.map_fn ) ורבים אחרים:

digits = tf.ragged.constant([[3, 1, 4, 1], [], [5, 9, 2], [6], []])
words = tf.ragged.constant([["So", "long"], ["thanks", "for", "all", "the", "fish"]])
print(tf.add(digits, 3))
print(tf.reduce_mean(digits, axis=1))
print(tf.concat([digits, [[5, 3]]], axis=0))
print(tf.tile(digits, [1, 2]))
print(tf.strings.substr(words, 0, 2))
print(tf.map_fn(tf.math.square, digits))
<tf.RaggedTensor [[6, 4, 7, 4], [], [8, 12, 5], [9], []]>
tf.Tensor([2.25              nan 5.33333333 6.                nan], shape=(5,), dtype=float64)
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9, 2], [6], [], [5, 3]]>
<tf.RaggedTensor [[3, 1, 4, 1, 3, 1, 4, 1], [], [5, 9, 2, 5, 9, 2], [6, 6], []]>
<tf.RaggedTensor [[b'So', b'lo'], [b'th', b'fo', b'al', b'th', b'fi']]>
<tf.RaggedTensor [[9, 1, 16, 1], [], [25, 81, 4], [36], []]>

ישנן גם מספר שיטות ופעולות ספציפיות לטנורים מרופטים, כולל שיטות מפעל, שיטות המרה ופעולות מיפוי ערך. לרשימת אופציות נתמכות, עיין tf.ragged החבילה tf.ragged .

טנזרים מרופטים נתמכים על ידי ממשקי API רבים של TensorFlow, כולל Keras , Datasets , tf.function , SavedModels ו- tf.Example . לקבלת מידע נוסף, עיין בסעיף בנושא ממשקי API של TensorFlow למטה.

כמו עם טנזורים רגילים, אתה יכול להשתמש באינדקס בסגנון פיתון כדי לגשת לפרוסות ספציפיות של טנזור מרופט. לקבלת מידע נוסף, עיין בסעיף על יצירת אינדקס להלן.

print(digits[0])       # First row
tf.Tensor([3 1 4 1], shape=(4,), dtype=int32)

print(digits[:, :2])   # First two values in each row.
<tf.RaggedTensor [[3, 1], [], [5, 9], [6], []]>

print(digits[:, -2:])  # Last two values in each row.
<tf.RaggedTensor [[4, 1], [], [9, 2], [6], []]>

ובדיוק כמו טנדרים רגילים, אתה יכול להשתמש במפעילי חשבון והשוואה של פייתון כדי לבצע פעולות אלמנטיות. למידע נוסף, עיין בסעיף בנושא מפעילים עמוסים בהמשך.

print(digits + 3)
<tf.RaggedTensor [[6, 4, 7, 4], [], [8, 12, 5], [9], []]>

print(digits + tf.ragged.constant([[1, 2, 3, 4], [], [5, 6, 7], [8], []]))
<tf.RaggedTensor [[4, 3, 7, 5], [], [10, 15, 9], [14], []]>

אם עליך לבצע טרנספורמציה אלמנטית לערכים של RaggedTensor , תוכל להשתמש ב- tf.ragged.map_flat_values , אשר לוקח פונקציה בתוספת אחד או יותר ארגומנטים, ומחיל את הפונקציה כדי לשנות את RaggedTensor ה- RaggedTensor .

times_two_plus_one = lambda x: x * 2 + 1
print(tf.ragged.map_flat_values(times_two_plus_one, digits))
<tf.RaggedTensor [[7, 3, 9, 3], [], [11, 19, 5], [13], []]>

ניתן להמיר tensors Ragged כדי Python מקוננת list s ו- numpy array ים:

digits.to_list()
[[3, 1, 4, 1], [], [5, 9, 2], [6], []]
digits.numpy()
/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/ragged/ragged_tensor.py:2012: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  return np.array(rows)

array([array([3, 1, 4, 1], dtype=int32), array([], dtype=int32),
       array([5, 9, 2], dtype=int32), array([6], dtype=int32),
       array([], dtype=int32)], dtype=object)

בניית טנזור מרופט

הדרך הפשוטה ביותר לבנות טנזור מרופט היא להשתמש ב- tf.ragged.constant , הבונה את ה- RaggedTensor המתאים list פיתון מקוננת או array קהה:

sentences = tf.ragged.constant([
    ["Let's", "build", "some", "ragged", "tensors", "!"],
    ["We", "can", "use", "tf.ragged.constant", "."]])
print(sentences)
<tf.RaggedTensor [[b"Let's", b'build', b'some', b'ragged', b'tensors', b'!'], [b'We', b'can', b'use', b'tf.ragged.constant', b'.']]>

paragraphs = tf.ragged.constant([
    [['I', 'have', 'a', 'cat'], ['His', 'name', 'is', 'Mat']],
    [['Do', 'you', 'want', 'to', 'come', 'visit'], ["I'm", 'free', 'tomorrow']],
])
print(paragraphs)
<tf.RaggedTensor [[[b'I', b'have', b'a', b'cat'], [b'His', b'name', b'is', b'Mat']], [[b'Do', b'you', b'want', b'to', b'come', b'visit'], [b"I'm", b'free', b'tomorrow']]]>

ניתן לבנות tf.RaggedTensor.from_value_rowids tf.RaggedTensor.from_row_lengths גם על ידי זיווג טנזורים של ערכים שטוחים עם טנזרים של מחיצת שורה המציינים כיצד יש לחלק את הערכים הללו לשורות, באמצעות שיטות כיתת מפעל כגון tf.RaggedTensor.from_value_rowids , tf.RaggedTensor.from_row_lengths ו- tf.RaggedTensor.from_row_splits .

tf.RaggedTensor.from_value_rowids

אם אתה יודע לאיזו שורה כל ערך שייך, תוכל לבנות RaggedTensor באמצעות טנסור מחיצת שורות value_rowids :

value_rowids

print(tf.RaggedTensor.from_value_rowids(
    values=[3, 1, 4, 1, 5, 9, 2],
    value_rowids=[0, 0, 0, 0, 2, 2, 3]))
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9], [2]]>

tf.RaggedTensor.from_row_lengths

אם אתה יודע כמה זמן כל שורה היא, אתה יכול להשתמש בטנזור מחיצת שורה row_lengths :

אורכי שורה

print(tf.RaggedTensor.from_row_lengths(
    values=[3, 1, 4, 1, 5, 9, 2],
    row_lengths=[4, 0, 2, 1]))
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9], [2]]>

tf.RaggedTensor.from_row_splits

אם אתה מכיר את האינדקס שבו כל שורה מתחילה ומסתיימת, תוכל להשתמש row_splits מחיצת שורה:

שורה_פיצולים

print(tf.RaggedTensor.from_row_splits(
    values=[3, 1, 4, 1, 5, 9, 2],
    row_splits=[0, 4, 4, 6, 7]))
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9], [2]]>

עייןtf.RaggedTensor המחלקהtf.RaggedTensor לרשימה מלאה של שיטות המפעל.

מה אתה יכול לאחסן בטנזור מרופט

כמו עם Tensor רגילים, הערכים ב- RaggedTensor חייבים לכלול אותו סוג; ועל הערכים להיות באותו עומק קינון ( דרגת הטנזור):

print(tf.ragged.constant([["Hi"], ["How", "are", "you"]]))  # ok: type=string, rank=2
<tf.RaggedTensor [[b'Hi'], [b'How', b'are', b'you']]>

print(tf.ragged.constant([[[1, 2], [3]], [[4, 5]]]))        # ok: type=int32, rank=3
<tf.RaggedTensor [[[1, 2], [3]], [[4, 5]]]>

try:
  tf.ragged.constant([["one", "two"], [3, 4]])              # bad: multiple types
except ValueError as exception:
  print(exception)
Can't convert Python sequence with mixed types to Tensor.

try:
  tf.ragged.constant(["A", ["B", "C"]])                     # bad: multiple nesting depths
except ValueError as exception:
  print(exception)
all scalar values must have the same nesting depth

מקרה שימוש לדוגמא

הדוגמה הבאה מדגימה כיצד ניתן להשתמש ב- RaggedTensor כדי לבנות ולשלב טבלאות Unigram ו- Bigram עבור קבוצה של שאילתות באורך משתנה, תוך שימוש בסמנים מיוחדים לתחילת וסיום כל משפט. לפרטים נוספים על האופציות המשמשות בדוגמה זו, עיין tf.ragged החבילה tf.ragged .

queries = tf.ragged.constant([['Who', 'is', 'Dan', 'Smith'],
                              ['Pause'],
                              ['Will', 'it', 'rain', 'later', 'today']])

# Create an embedding table.
num_buckets = 1024
embedding_size = 4
embedding_table = tf.Variable(
    tf.random.truncated_normal([num_buckets, embedding_size],
                       stddev=1.0 / math.sqrt(embedding_size)))

# Look up the embedding for each word.
word_buckets = tf.strings.to_hash_bucket_fast(queries, num_buckets)
word_embeddings = tf.nn.embedding_lookup(embedding_table, word_buckets)     # ①

# Add markers to the beginning and end of each sentence.
marker = tf.fill([queries.nrows(), 1], '#')
padded = tf.concat([marker, queries, marker], axis=1)                       # ②

# Build word bigrams & look up embeddings.
bigrams = tf.strings.join([padded[:, :-1], padded[:, 1:]], separator='+')   # ③

bigram_buckets = tf.strings.to_hash_bucket_fast(bigrams, num_buckets)
bigram_embeddings = tf.nn.embedding_lookup(embedding_table, bigram_buckets) # ④

# Find the average embedding for each sentence
all_embeddings = tf.concat([word_embeddings, bigram_embeddings], axis=1)    # ⑤
avg_embedding = tf.reduce_mean(all_embeddings, axis=1)                      # ⑥
print(avg_embedding)
tf.Tensor(
[[-0.07226902 -0.03359559 -0.03866251 -0.04422581]
 [-0.10786405 -0.38157812 -0.11010554 -0.07145723]
 [ 0.18454719 -0.05851733 -0.13204828  0.14964654]], shape=(3, 4), dtype=float32)

ragged_example

מידות מרופטות ואחידות

מימד מרופט הוא מימד שפרוסותיו עשויות להיות באורכים שונים. לדוגמא, הממד הפנימי (עמודה) של rt=[[3, 1, 4, 1], [], [5, 9, 2], [6], []] מרופט, מכיוון שהעמודה פורסת ( rt[0, :] rt[4, :] rt[0, :] , ..., rt[4, :] ) יש אורכים שונים. ממדים שכולם פרוסות באותו אורך נקראים מידות אחידות .

הממד החיצוני ביותר של טנזור מרופט תמיד אחיד, מכיוון שהוא מורכב מפרוסה אחת (ולכן אין אפשרות לאורכי פרוסות שונים). המידות הנותרות עשויות להיות מרופטות או אחידות. לדוגמא, אנו עשויים לאחסן את מילות הטביעה עבור כל מילה באוסף משפטים באמצעות טנזור מרופט עם צורה [num_sentences, (num_words), embedding_size] , כאשר הסוגריים מסביב (num_words) מצביעים על כך שהמימד מרופט.

sent_word_embed

טנורים מרופטים עשויים להיות בעלי ממדים מרופטים מרובים. לדוגמא, נוכל לאחסן קבוצה של מסמכי טקסט מובנים באמצעות טנסור עם צורה [num_documents, (num_paragraphs), (num_sentences), (num_words)] (שם שוב משתמשים בסוגריים לציון ממדים מרופטים).

כמו עם tf.Tensor , דרגתו של טנזור מרופט היא מספר הממדים הכולל שלו (כולל מידות מרופטות ואחידות). טנזור שעלול להיות מרופט הוא ערך שעשוי להיות tf.Tensor אוtf.RaggedTensor .

כאשר מתארים את צורתו של RaggedTensor, ממדים מרופטים מסומנים באופן מקובל על ידי סגירתם בסוגריים. לדוגמא, כפי שראינו לעיל, ניתן לכתוב את הצורה של Rensed Tensor תלת-ממדי המאחסן טביעות מילים עבור כל מילה [num_sentences, (num_words), embedding_size] משפטים כ- [num_sentences, (num_words), embedding_size] .

התכונה RaggedTensor.shape מחזירה tf.TensorShape עבור טנזור מרופט, כאשר הממדים המרופטים יש גודל None :

tf.ragged.constant([["Hi"], ["How", "are", "you"]]).shape
TensorShape([2, None])

ניתן להשתמש בשיטה tf.RaggedTensor.bounding_shape למציאת צורה תוחמת הדוקה עבור RaggedTensor נתון:

print(tf.ragged.constant([["Hi"], ["How", "are", "you"]]).bounding_shape())
tf.Tensor([2 3], shape=(2,), dtype=int64)

מרופט מול דליל

אין לחשוב על טנזור מרופט כעל סוג של טנזור דליל. בפרט, טנסורים דלילים הם קידודים יעילים עבור tf.Tensor , המדגמים את אותם נתונים בפורמט קומפקטי; אך טנזור מרופט הוא הרחבה ל- tf.Tensor , המדגם סוג נתונים מורחב. הבדל זה הוא קריטי בעת הגדרת הפעולות:

  • החלת אופ על טנסור דליל או צפוף תמיד צריכה לתת את אותה התוצאה.
  • החלת אופ על טנסור מרופט או דליל עשויה לתת תוצאות שונות.

כדוגמה המחשה, לשקול כיצד פעולות מערך כגון concat , stack , ואת tile מוגדרות עבור טנזורים מרופטים לעומת דלילה. שרשור טנזורים מרופטים מצטרף לכל שורה ויוצר שורה אחת באורך המשולב:

ragged_concat

ragged_x = tf.ragged.constant([["John"], ["a", "big", "dog"], ["my", "cat"]])
ragged_y = tf.ragged.constant([["fell", "asleep"], ["barked"], ["is", "fuzzy"]])
print(tf.concat([ragged_x, ragged_y], axis=1))
<tf.RaggedTensor [[b'John', b'fell', b'asleep'], [b'a', b'big', b'dog', b'barked'], [b'my', b'cat', b'is', b'fuzzy']]>

אך שרשור של טנסורים דלילים שווה ערך לשרשור של טנסורים צפופים תואמים, כפי שמודגם בדוגמה הבאה (כאשר Ø מציין ערכים חסרים):

sparse_concat

sparse_x = ragged_x.to_sparse()
sparse_y = ragged_y.to_sparse()
sparse_result = tf.sparse.concat(sp_inputs=[sparse_x, sparse_y], axis=1)
print(tf.sparse.to_dense(sparse_result, ''))
tf.Tensor(
[[b'John' b'' b'' b'fell' b'asleep']
 [b'a' b'big' b'dog' b'barked' b'']
 [b'my' b'cat' b'' b'is' b'fuzzy']], shape=(3, 5), dtype=string)

לדוגמא נוספת מדוע הבחנה זו חשובה, שקול את ההגדרה "הערך הממוצע של כל שורה" עבור אופציה כגון tf.reduce_mean . עבור טנזור מרופט, הערך הממוצע לשורה הוא סכום ערכי השורה חלקי רוחב השורה. אך עבור טנסור דליל, הערך הממוצע לשורה הוא סכום ערכי השורה חלקי הרוחב הכללי של הטנסור הדליל (שגדול או שווה לרוחב השורה הארוכה ביותר).

ממשקי API של TensorFlow

קרס

tf.keras הוא ה- API ברמה גבוהה של TensorFlow לבניית והכשרת מודלים של למידה עמוקה. ניתן להעביר טנזורים ragged=True כקלטים למודל Keras על ידי הגדרת tf.keras.Input ragged=True ב- tf.keras.Input או tf.keras.layers.InputLayer . טנורים מרופטים עשויים לעבור גם בין שכבות קרס, ולהחזיר על ידי דגמי קרס. הדוגמה הבאה מציגה דגם LSTM צעצוע המאומן באמצעות טנורים מרופטים.

# Task: predict whether each sentence is a question or not.
sentences = tf.constant(
    ['What makes you think she is a witch?',
     'She turned me into a newt.',
     'A newt?',
     'Well, I got better.'])
is_question = tf.constant([True, False, True, False])

# Preprocess the input strings.
hash_buckets = 1000
words = tf.strings.split(sentences, ' ')
hashed_words = tf.strings.to_hash_bucket_fast(words, hash_buckets)

# Build the Keras model.
keras_model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=[None], dtype=tf.int64, ragged=True),
    tf.keras.layers.Embedding(hash_buckets, 16),
    tf.keras.layers.LSTM(32, use_bias=False),
    tf.keras.layers.Dense(32),
    tf.keras.layers.Activation(tf.nn.relu),
    tf.keras.layers.Dense(1)
])

keras_model.compile(loss='binary_crossentropy', optimizer='rmsprop')
keras_model.fit(hashed_words, is_question, epochs=5)
print(keras_model.predict(hashed_words))
WARNING:tensorflow:Layer lstm will not use cuDNN kernel since it doesn't meet the cuDNN kernel criteria. It will use generic GPU kernel as fallback when running on GPU
Epoch 1/5

/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/framework/indexed_slices.py:437: UserWarning: Converting sparse IndexedSlices(IndexedSlices(indices=Tensor("gradient_tape/sequential/lstm/RaggedToTensor/boolean_mask_1/GatherV2:0", shape=(None,), dtype=int32), values=Tensor("gradient_tape/sequential/lstm/RaggedToTensor/boolean_mask/GatherV2:0", shape=(None, 16), dtype=float32), dense_shape=Tensor("gradient_tape/sequential/lstm/RaggedToTensor/Shape:0", shape=(2,), dtype=int32))) to a dense Tensor of unknown shape. This may consume a large amount of memory.
  "shape. This may consume a large amount of memory." % value)

1/1 [==============================] - 2s 2s/step - loss: 2.7506
Epoch 2/5
1/1 [==============================] - 0s 16ms/step - loss: 1.9755
Epoch 3/5
1/1 [==============================] - 0s 15ms/step - loss: 1.8869
Epoch 4/5
1/1 [==============================] - 0s 16ms/step - loss: 1.8256
Epoch 5/5
1/1 [==============================] - 0s 19ms/step - loss: 1.7605
[[0.03648993]
 [0.00550611]
 [0.02936834]
 [0.0077349 ]]

tf. דוגמה

tf.Example הוא תקן Protobuf קידוד עבור נתוני TensorFlow. נתונים המקודדים עם tf.Example . tf.Example s כוללים לעיתים תכונות באורך משתנה. לדוגמא, הקוד הבא מגדיר אצווה של ארבעה tf.Example הודעות tf.Example תכונה שונות:

import google.protobuf.text_format as pbtext

def build_tf_example(s):
  return pbtext.Merge(s, tf.train.Example()).SerializeToString()

example_batch = [
  build_tf_example(r'''
    features {
      feature {key: "colors" value {bytes_list {value: ["red", "blue"]} } }
      feature {key: "lengths" value {int64_list {value: [7]} } } }'''),
  build_tf_example(r'''
    features {
      feature {key: "colors" value {bytes_list {value: ["orange"]} } }
      feature {key: "lengths" value {int64_list {value: []} } } }'''),
  build_tf_example(r'''
    features {
      feature {key: "colors" value {bytes_list {value: ["black", "yellow"]} } }
      feature {key: "lengths" value {int64_list {value: [1, 3]} } } }'''),
  build_tf_example(r'''
    features {
      feature {key: "colors" value {bytes_list {value: ["green"]} } }
      feature {key: "lengths" value {int64_list {value: [3, 5, 2]} } } }''')]

אנו יכולים לנתח את הנתונים המקודדים באמצעות tf.io.parse_example , שלוקח טנזור של מחרוזות tf.io.parse_example ומילון של מפרט תכונות, ומחזיר שמות של תכונות מיפוי מילון לטנזורים. כדי לקרוא את התכונות באורך המשתנה tf.io.RaggedFeature מרופטים, אנו פשוט משתמשים ב- tf.io.RaggedFeature במילון מפרט התכונות:

feature_specification = {
    'colors': tf.io.RaggedFeature(tf.string),
    'lengths': tf.io.RaggedFeature(tf.int64),
}
feature_tensors = tf.io.parse_example(example_batch, feature_specification)
for name, value in feature_tensors.items():
  print("{}={}".format(name, value))
colors=<tf.RaggedTensor [[b'red', b'blue'], [b'orange'], [b'black', b'yellow'], [b'green']]>
lengths=<tf.RaggedTensor [[7], [], [1, 3], [3, 5, 2]]>

tf.io.RaggedFeature יכול לשמש גם כדי לקרוא תכונות עם ממדים מרופטים מרובים. לפרטים, עיין בתיעוד ה- API .

מערכי נתונים

tf.data הוא ממשק API המאפשר לך לבנות צינורות קלט מורכבים מחלקים פשוטים לשימוש חוזר. מבנה נתוני הליבה שלה הואtf.data.Dataset , המייצג רצף של אלמנטים, שבו כל אלמנט מורכב מרכיב אחד או יותר.

# Helper function used to print datasets in the examples below.
def print_dictionary_dataset(dataset):
  for i, element in enumerate(dataset):
    print("Element {}:".format(i))
    for (feature_name, feature_value) in element.items():
      print('{:>14} = {}'.format(feature_name, feature_value))

בניית מערכי נתונים עם טנורים מרופטים

ניתן לבנות מערכי נתונים ממנסרים מרופטים באותן שיטות המשמשות לבנייתם ​​מ- tf.Tensor s או array Dataset.from_tensor_slices , כגון Dataset.from_tensor_slices :

dataset = tf.data.Dataset.from_tensor_slices(feature_tensors)
print_dictionary_dataset(dataset)
Element 0:
        colors = [b'red' b'blue']
       lengths = [7]
Element 1:
        colors = [b'orange']
       lengths = []
Element 2:
        colors = [b'black' b'yellow']
       lengths = [1 3]
Element 3:
        colors = [b'green']
       lengths = [3 5 2]

אצווה ונטילת מערכי נתונים עם טנורים מרופטים

ניתן לאגד מערכי נתונים עם טנזורים מרופטים (המשלבים n אלמנטים עוקבים לאלמנטים בודדים) בשיטת Dataset.batch .

batched_dataset = dataset.batch(2)
print_dictionary_dataset(batched_dataset)
Element 0:
        colors = <tf.RaggedTensor [[b'red', b'blue'], [b'orange']]>
       lengths = <tf.RaggedTensor [[7], []]>
Element 1:
        colors = <tf.RaggedTensor [[b'black', b'yellow'], [b'green']]>
       lengths = <tf.RaggedTensor [[1, 3], [3, 5, 2]]>

לעומת זאת, ניתן להפוך מערך נתונים Dataset.unbatch נתונים שטוח באמצעות Dataset.unbatch .

unbatched_dataset = batched_dataset.unbatch()
print_dictionary_dataset(unbatched_dataset)
Element 0:
        colors = [b'red' b'blue']
       lengths = [7]
Element 1:
        colors = [b'orange']
       lengths = []
Element 2:
        colors = [b'black' b'yellow']
       lengths = [1 3]
Element 3:
        colors = [b'green']
       lengths = [3 5 2]

מערכי נתונים באצווה עם טנזרים שאינם מרופטים באורך משתנה

אם יש לך מערך נתונים המכיל טנזורים לא מרופטים, ואורכי טנסור משתנים בין אלמנטים, אז אתה יכול dense_to_ragged_batch את אותם dense_to_ragged_batch לא מרופטים לטנרים מרופטים על ידי החלת טרנספורמציית dense_to_ragged_batch :

non_ragged_dataset = tf.data.Dataset.from_tensor_slices([1, 5, 3, 2, 8])
non_ragged_dataset = non_ragged_dataset.map(tf.range)
batched_non_ragged_dataset = non_ragged_dataset.apply(
    tf.data.experimental.dense_to_ragged_batch(2))
for element in batched_non_ragged_dataset:
  print(element)
<tf.RaggedTensor [[0], [0, 1, 2, 3, 4]]>
<tf.RaggedTensor [[0, 1, 2], [0, 1]]>
<tf.RaggedTensor [[0, 1, 2, 3, 4, 5, 6, 7]]>

שינוי מערכי נתונים עם טנורים מרופטים

ניתן ליצור או לשנות Dataset.map באמצעות Dataset.map .

def transform_lengths(features):
  return {
      'mean_length': tf.math.reduce_mean(features['lengths']),
      'length_ranges': tf.ragged.range(features['lengths'])}
transformed_dataset = dataset.map(transform_lengths)
print_dictionary_dataset(transformed_dataset)
Element 0:
   mean_length = 7
 length_ranges = <tf.RaggedTensor [[0, 1, 2, 3, 4, 5, 6]]>
Element 1:
   mean_length = 0
 length_ranges = <tf.RaggedTensor []>
Element 2:
   mean_length = 2
 length_ranges = <tf.RaggedTensor [[0], [0, 1, 2]]>
Element 3:
   mean_length = 3
 length_ranges = <tf.RaggedTensor [[0, 1, 2], [0, 1, 2, 3, 4], [0, 1]]>

פונקציה tf

tf.function הוא מעצב המחשב מראש גרפים של TensorFlow לפונקציות Python, מה שיכול לשפר משמעותית את הביצועים של קוד ה- TensorFlow שלך. ניתן להשתמש @tf.function עם @tf.function פונקציות @tf.function . לדוגמא, הפונקציה הבאה עובדת עם טנזורים מרופטים ולא מרופטים:

@tf.function
def make_palindrome(x, axis):
  return tf.concat([x, tf.reverse(x, [axis])], axis)
make_palindrome(tf.constant([[1, 2], [3, 4], [5, 6]]), axis=1)
<tf.Tensor: shape=(3, 4), dtype=int32, numpy=
array([[1, 2, 2, 1],
       [3, 4, 4, 3],
       [5, 6, 6, 5]], dtype=int32)>
make_palindrome(tf.ragged.constant([[1, 2], [3], [4, 5, 6]]), axis=1)
<tf.RaggedTensor [[1, 2, 2, 1], [3, 3], [4, 5, 6, 6, 5, 4]]>

אם ברצונך לציין במפורש את input_signature עבור input_signature tf.function , תוכל לעשות זאת באמצעות tf.RaggedTensorSpec .

@tf.function(
    input_signature=[tf.RaggedTensorSpec(shape=[None, None], dtype=tf.int32)])
def max_and_min(rt):
  return (tf.math.reduce_max(rt, axis=-1), tf.math.reduce_min(rt, axis=-1))

max_and_min(tf.ragged.constant([[1, 2], [3], [4, 5, 6]]))
(<tf.Tensor: shape=(3,), dtype=int32, numpy=array([2, 3, 6], dtype=int32)>,
 <tf.Tensor: shape=(3,), dtype=int32, numpy=array([1, 3, 4], dtype=int32)>)

פונקציות בטון

פונקציות בטון tf.function גרפים tf.function בודדים שנבנו על ידי tf.function . טנורים מרופטים יכולים לשמש בצורה שקופה עם פונקציות קונקרטיות.

@tf.function
def increment(x):
  return x + 1

rt = tf.ragged.constant([[1, 2], [3], [4, 5, 6]])
cf = increment.get_concrete_function(rt)
print(cf(rt))
<tf.RaggedTensor [[2, 3], [4], [5, 6, 7]]>

SavedModels

SavedModel היא תוכנית TensorFlow מסדרת סדרה, הכוללת גם משקולות וגם חישוב. ניתן לבנות אותו מדגם Keras או מדגם מותאם אישית. בשני המקרים ניתן להשתמש בשקיפות בטנורים מרופטים עם הפונקציות והשיטות המוגדרות על ידי SavedModel.

דוגמה: שמירת מודל Keras

import tempfile

keras_module_path = tempfile.mkdtemp()
tf.saved_model.save(keras_model, keras_module_path)
imported_model = tf.saved_model.load(keras_module_path)
imported_model(hashed_words)
INFO:tensorflow:Assets written to: /tmp/tmpyr1dlj_r/assets

<tf.Tensor: shape=(4, 1), dtype=float32, numpy=
array([[0.03648993],
       [0.00550611],
       [0.02936834],
       [0.0077349 ]], dtype=float32)>

דוגמה: שמירת דגם מותאם אישית

class CustomModule(tf.Module):
  def __init__(self, variable_value):
    super(CustomModule, self).__init__()
    self.v = tf.Variable(variable_value)

  @tf.function
  def grow(self, x):
    return x * self.v

module = CustomModule(100.0)

# Before saving a custom model, we must ensure that concrete functions are
# built for each input signature that we will need.
module.grow.get_concrete_function(tf.RaggedTensorSpec(shape=[None, None],
                                                      dtype=tf.float32))

custom_module_path = tempfile.mkdtemp()
tf.saved_model.save(module, custom_module_path)
imported_model = tf.saved_model.load(custom_module_path)
imported_model.grow(tf.ragged.constant([[1.0, 4.0, 3.0], [2.0]]))
INFO:tensorflow:Assets written to: /tmp/tmpen_1gfeg/assets

<tf.RaggedTensor [[100.0, 400.0, 300.0], [200.0]]>

מפעילים עמוסים מדי

מחלקת RaggedTensor יתר על המידה על מפעילי חשבון ופייתון סטנדרטיים, מה שמקל על ביצוע מתמטיקה בסיסית אלמנטית:

x = tf.ragged.constant([[1, 2], [3], [4, 5, 6]])
y = tf.ragged.constant([[1, 1], [2], [3, 3, 3]])
print(x + y)
<tf.RaggedTensor [[2, 3], [5], [7, 8, 9]]>

מכיוון שהמפעילים העומסים יתר על המידה מבצעים חישובים אלמנטיים, על הקלטים לכל הפעולות הבינאריות להיות באותה צורה, או להיות משודרים לאותה צורה. במקרה השידור הפשוט ביותר, סקלר יחיד משולב באופן אלמנטרי עם כל ערך בטנזור מרופט:

x = tf.ragged.constant([[1, 2], [3], [4, 5, 6]])
print(x + 3)
<tf.RaggedTensor [[4, 5], [6], [7, 8, 9]]>

לדיון במקרים מתקדמים יותר, עיין בסעיף שידור .

Tensors Ragged להעמיס אותו הסט של מפעילים כרגיל Tensor ים: מפעילי יונארית - , ~ , ו abs() ; והמפעילים הבינאריים + , - , * , / , // , % , ** , & , | , ^ , == , < , <= , > ו- >= .

אינדקס

טנזורים מרופטים תומכים באינדקס בסגנון פיתון, כולל אינדקס רב-ממדי וחיתוך. הדוגמאות הבאות מדגימות אינדקס טנזור מרופט עם 2-D וטנזור מרופט 3-D.

דוגמאות לאינדקס: טנזור 2D מרופט

queries = tf.ragged.constant(
    [['Who', 'is', 'George', 'Washington'],
     ['What', 'is', 'the', 'weather', 'tomorrow'],
     ['Goodnight']])
print(queries[1])                   # A single query
tf.Tensor([b'What' b'is' b'the' b'weather' b'tomorrow'], shape=(5,), dtype=string)

print(queries[1, 2])                # A single word
tf.Tensor(b'the', shape=(), dtype=string)

print(queries[1:])                  # Everything but the first row
<tf.RaggedTensor [[b'What', b'is', b'the', b'weather', b'tomorrow'], [b'Goodnight']]>

print(queries[:, :3])               # The first 3 words of each query
<tf.RaggedTensor [[b'Who', b'is', b'George'], [b'What', b'is', b'the'], [b'Goodnight']]>

print(queries[:, -2:])              # The last 2 words of each query
<tf.RaggedTensor [[b'George', b'Washington'], [b'weather', b'tomorrow'], [b'Goodnight']]>

דוגמאות לאינדקס תלת ממד מרופט

rt = tf.ragged.constant([[[1, 2, 3], [4]],
                         [[5], [], [6]],
                         [[7]],
                         [[8, 9], [10]]])
print(rt[1])                        # Second row (2-D RaggedTensor)
<tf.RaggedTensor [[5], [], [6]]>

print(rt[3, 0])                     # First element of fourth row (1-D Tensor)
tf.Tensor([8 9], shape=(2,), dtype=int32)

print(rt[:, 1:3])                   # Items 1-3 of each row (3-D RaggedTensor)
<tf.RaggedTensor [[[4]], [[], [6]], [], [[10]]]>

print(rt[:, -1:])                   # Last item of each row (3-D RaggedTensor)
<tf.RaggedTensor [[[4]], [[6]], [[7]], [[10]]]>

RaggedTensor s תומך באינדקס רב-ממדי RaggedTensor , עם מגבלה אחת: לא ניתן RaggedTensor לאינדקס RaggedTensor . מקרה זה הוא בעייתי מכיוון שהערך המצוין עשוי להתקיים בשורות מסוימות אך לא באחרות. במקרים כאלה, זה לא מובן מאליו אם עלינו (1) להעלות IndexError ; (2) השתמש בערך ברירת מחדל; או (3) דלג על ערך זה והחזיר טנזור עם פחות שורות ממה שהתחלנו איתו. בעקבות העקרונות המנחים של פיתון ("לנוכח העמימות, סרב לפיתוי לנחש"), אנו כרגע לא מאפשרים פעולה זו.

המרה מסוג טנסור

הכיתה RaggedTensor מגדירה שיטות שניתן להשתמש בהן להמרה בין RaggedTensor s ל- tf.Tensor . tf.Tensor s או tf.SparseTensors :

ragged_sentences = tf.ragged.constant([
    ['Hi'], ['Welcome', 'to', 'the', 'fair'], ['Have', 'fun']])
# RaggedTensor -> Tensor
print(ragged_sentences.to_tensor(default_value='', shape=[None, 10]))
tf.Tensor(
[[b'Hi' b'' b'' b'' b'' b'' b'' b'' b'' b'']
 [b'Welcome' b'to' b'the' b'fair' b'' b'' b'' b'' b'' b'']
 [b'Have' b'fun' b'' b'' b'' b'' b'' b'' b'' b'']], shape=(3, 10), dtype=string)

# Tensor -> RaggedTensor
x = [[1, 3, -1, -1], [2, -1, -1, -1], [4, 5, 8, 9]]
print(tf.RaggedTensor.from_tensor(x, padding=-1))
<tf.RaggedTensor [[1, 3], [2], [4, 5, 8, 9]]>

#RaggedTensor -> SparseTensor
print(ragged_sentences.to_sparse())
SparseTensor(indices=tf.Tensor(
[[0 0]
 [1 0]
 [1 1]
 [1 2]
 [1 3]
 [2 0]
 [2 1]], shape=(7, 2), dtype=int64), values=tf.Tensor([b'Hi' b'Welcome' b'to' b'the' b'fair' b'Have' b'fun'], shape=(7,), dtype=string), dense_shape=tf.Tensor([3 4], shape=(2,), dtype=int64))

# SparseTensor -> RaggedTensor
st = tf.SparseTensor(indices=[[0, 0], [2, 0], [2, 1]],
                     values=['a', 'b', 'c'],
                     dense_shape=[3, 3])
print(tf.RaggedTensor.from_sparse(st))
<tf.RaggedTensor [[b'a'], [], [b'b', b'c']]>

הערכת טנורים מרופטים

כדי לגשת לערכים בטנזור מרופט, אתה יכול:

  1. השתמש ב- tf.RaggedTensor.to_list() כדי להמיר את הטנסור המרופט לרשימת tf.RaggedTensor.to_list() מקוננת.
  2. השתמש ב- tf.RaggedTensor.numpy() כדי להמיר את הטנסור המרופט למערך קהה שהערכים שלו מקוננים מערכים קהיים.
  3. tf.RaggedTensor.values את tf.RaggedTensor.values המרופט לרכיביו, תוך שימוש tf.RaggedTensor.values tf.RaggedTensor.row_splits ו- tf.RaggedTensor.row_splits , או בשיטות tf.RaggedTensor.row_lengths() כגון tf.RaggedTensor.row_lengths() ו- tf.RaggedTensor.value_rowids() .
  4. השתמש באינדקס של פייתון כדי לבחור ערכים מהטנסור המרופט.
rt = tf.ragged.constant([[1, 2], [3, 4, 5], [6], [], [7]])
print("python list:", rt.to_list())
print("numpy array:", rt.numpy())
print("values:", rt.values.numpy())
print("splits:", rt.row_splits.numpy())
print("indexed value:", rt[1].numpy())
python list: [[1, 2], [3, 4, 5], [6], [], [7]]
numpy array: [array([1, 2], dtype=int32) array([3, 4, 5], dtype=int32)
 array([6], dtype=int32) array([], dtype=int32) array([7], dtype=int32)]
values: [1 2 3 4 5 6 7]
splits: [0 2 5 6 6 7]
indexed value: [3 4 5]

/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/ragged/ragged_tensor.py:2012: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  return np.array(rows)

שידור

שידור הוא תהליך של יצירת טנזורים עם צורות שונות בעלי צורות תואמות לפעולות אלמנטיות. לקבלת רקע נוסף בנושא שידור, ראה:

השלבים הבסיסיים לשידור שתי כניסות x ו- y יהיו בעלות צורות תואמות הן:

  1. אם ל- x ו- y אין מספר זהה של מידות, הוסף מידות חיצוניות (עם גודל 1) עד שיהיה.

  2. לכל מימד שבו x ו- y יש גדלים שונים:

    • אם ל- x או y יש גודל 1 בממד d , חזור על ערכיו על פני ממד d כדי להתאים לגודל הקלט האחר.

    • אחרת, העלה חריג ( x ו- y אינם תואמים לשידור).

כאשר גודלו של טנסור בממד אחיד הוא מספר יחיד (גודל הפרוסות על פני אותו ממד); וגודל של טנסור בממד מרופט הוא רשימה של אורכי פרוסות (עבור כל הפרוסות על פני מימד זה).

דוגמאות שידור

# x       (2D ragged):  2 x (num_rows)
# y       (scalar)
# result  (2D ragged):  2 x (num_rows)
x = tf.ragged.constant([[1, 2], [3]])
y = 3
print(x + y)
<tf.RaggedTensor [[4, 5], [6]]>

# x         (2d ragged):  3 x (num_rows)
# y         (2d tensor):  3 x          1
# Result    (2d ragged):  3 x (num_rows)
x = tf.ragged.constant(
   [[10, 87, 12],
    [19, 53],
    [12, 32]])
y = [[1000], [2000], [3000]]
print(x + y)
<tf.RaggedTensor [[1010, 1087, 1012], [2019, 2053], [3012, 3032]]>

# x      (3d ragged):  2 x (r1) x 2
# y      (2d ragged):         1 x 1
# Result (3d ragged):  2 x (r1) x 2
x = tf.ragged.constant(
    [[[1, 2], [3, 4], [5, 6]],
     [[7, 8]]],
    ragged_rank=1)
y = tf.constant([[10]])
print(x + y)
<tf.RaggedTensor [[[11, 12], [13, 14], [15, 16]], [[17, 18]]]>

# x      (3d ragged):  2 x (r1) x (r2) x 1
# y      (1d tensor):                    3
# Result (3d ragged):  2 x (r1) x (r2) x 3
x = tf.ragged.constant(
    [
        [
            [[1], [2]],
            [],
            [[3]],
            [[4]],
        ],
        [
            [[5], [6]],
            [[7]]
        ]
    ],
    ragged_rank=2)
y = tf.constant([10, 20, 30])
print(x + y)
<tf.RaggedTensor [[[[11, 21, 31], [12, 22, 32]], [], [[13, 23, 33]], [[14, 24, 34]]], [[[15, 25, 35], [16, 26, 36]], [[17, 27, 37]]]]>

להלן מספר דוגמאות לצורות שאינן משודרות:

# x      (2d ragged): 3 x (r1)
# y      (2d tensor): 3 x    4  # trailing dimensions do not match
x = tf.ragged.constant([[1, 2], [3, 4, 5, 6], [7]])
y = tf.constant([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
try:
  x + y
except tf.errors.InvalidArgumentError as exception:
  print(exception)
Expected 'tf.Tensor(False, shape=(), dtype=bool)' to be true. Summarized data: b'Unable to broadcast: dimension size mismatch in dimension'
1
b'lengths='
4
b'dim_size='
2, 4, 1

# x      (2d ragged): 3 x (r1)
# y      (2d ragged): 3 x (r2)  # ragged dimensions do not match.
x = tf.ragged.constant([[1, 2, 3], [4], [5, 6]])
y = tf.ragged.constant([[10, 20], [30, 40], [50]])
try:
  x + y
except tf.errors.InvalidArgumentError as exception:
  print(exception)
Expected 'tf.Tensor(False, shape=(), dtype=bool)' to be true. Summarized data: b'Unable to broadcast: dimension size mismatch in dimension'
1
b'lengths='
2, 2, 1
b'dim_size='
3, 1, 2

# x      (3d ragged): 3 x (r1) x 2
# y      (3d ragged): 3 x (r1) x 3  # trailing dimensions do not match
x = tf.ragged.constant([[[1, 2], [3, 4], [5, 6]],
                        [[7, 8], [9, 10]]])
y = tf.ragged.constant([[[1, 2, 0], [3, 4, 0], [5, 6, 0]],
                        [[7, 8, 0], [9, 10, 0]]])
try:
  x + y
except tf.errors.InvalidArgumentError as exception:
  print(exception)
Expected 'tf.Tensor(False, shape=(), dtype=bool)' to be true. Summarized data: b'Unable to broadcast: dimension size mismatch in dimension'
2
b'lengths='
3, 3, 3, 3, 3
b'dim_size='
2, 2, 2, 2, 2

קידוד RaggedTensor

RaggedTensor מקודדים באמצעות הכיתה RaggedTensor . באופן פנימי, כל RaggedTensor מורכב מ:

  • טנזור values , המשרשר את השורות באורך המשתנה לרשימה שטוחה.
  • row_partition , המציינת כיצד אותם ערכים שטוחים מחולקים לשורות.

ragged_encoding_2

ניתן לאחסן את row_partition באמצעות ארבעה קידודים שונים:

  • row_splits הוא וקטור שלם המציין את נקודות הפיצול בין השורות.
  • value_rowids הוא וקטור שלם המציין את אינדקס השורה עבור כל ערך.
  • row_lengths הוא וקטור שלם המציין את אורך כל שורה.
  • uniform_row_length הוא סקלר שלם המציין אורך יחיד לכל השורות.

מחיצות_קידודים

סקלר שלם nrows יכול גם להיכלל row_partition הקידוד, לתת דין וחשבון על שורות נגררות ריקות עם value_rowids , או שורות ריקות עם uniform_row_length .

rt = tf.RaggedTensor.from_row_splits(
    values=[3, 1, 4, 1, 5, 9, 2],
    row_splits=[0, 4, 4, 6, 7])
print(rt)
<tf.RaggedTensor [[3, 1, 4, 1], [], [5, 9], [2]]>

הבחירה באיזה קידוד להשתמש עבור מחיצות שורה מנוהלת באופן פנימי על ידי טנורים מרופטים, כדי לשפר את היעילות בהקשרים מסוימים. בפרט, חלק מהיתרונות והחסרונות של תוכניות חלוקת השורות השונות הם:

  • אינדקס יעיל : קידוד row_splits מאפשר יצירת אינדקס בזמן קבוע row_splits מרופטים.

  • שרשור יעיל : קידוד row_lengths יעיל יותר לשרשור טנזורים מרופטים, מכיוון שאורכי השורה אינם משתנים כששני טנסורים משורשרים יחד.

  • גודל קידוד קטן: קידוד ה- value_rowids יעיל יותר בעת אחסון value_rowids מרופטים בעלי מספר רב של שורות ריקות, מכיוון שגודל הטנסור תלוי רק במספר הערכים הכולל. מצד שני, את row_splits ו row_lengths קידודים הם יעילים יותר כאשר לאחסון tensors מרופט עם שורות יותר, שכן הם דורשים רק ערך סקלרי אחד עבור כל שורה.

  • תאימות : ערכת value_rowids תואמת לפורמט הפילוח המשמש פעולות כגון tf.segment_sum . התוכנית row_limits תואמת את הפורמט בו משתמשים אופ כמו tf.sequence_mask .

  • מידות אחידות : כפי שיפורט להלן, קידוד uniform_row_length משמש לקידוד uniform_row_length מרופטים עם ממדים אחידים.

מידות מרופטות מרובות

טנזור מרופט בעל ממדים מרופטים מרובים מקודד באמצעות RaggedTensor מקונן עבור טנזור values . כל RaggedTensor מקונן מוסיף מימד מרופט אחד.

ragged_rank_2

rt = tf.RaggedTensor.from_row_splits(
    values=tf.RaggedTensor.from_row_splits(
        values=[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
        row_splits=[0, 3, 3, 5, 9, 10]),
    row_splits=[0, 1, 1, 5])
print(rt)
print("Shape: {}".format(rt.shape))
print("Number of partitioned dimensions: {}".format(rt.ragged_rank))
<tf.RaggedTensor [[[10, 11, 12]], [], [[], [13, 14], [15, 16, 17, 18], [19]]]>
Shape: (3, None, None)
Number of partitioned dimensions: 2

פונקציית המפעל tf.RaggedTensor.from_nested_row_splits עשויה לשמש לבניית RaggedTensor עם מספר רב של ממדים מרופטים ישירות, על ידי מתן רשימה של טנזורי row_splits :

rt = tf.RaggedTensor.from_nested_row_splits(
    flat_values=[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
    nested_row_splits=([0, 1, 1, 5], [0, 3, 3, 5, 9, 10]))
print(rt)
<tf.RaggedTensor [[[10, 11, 12]], [], [[], [13, 14], [15, 16, 17, 18], [19]]]>

דרגה מרופטת וערכים שטוחים

דרגה מרופטת של טנזור מרופט היא מספר הפעמים RaggedTensor values הבסיסיים ש- Tensor חולק (כלומר, עומק הקינון של אובייקטים RaggedTensor ). טנזור values הפנימי ביותר ידוע כערכים השטוחים שלו. בדוגמה הבאה, conversations יש ragged_rank = 3, ו שלה flat_values הוא 1D Tensor עם 24 מיתרים:

# shape = [batch, (paragraph), (sentence), (word)]
conversations = tf.ragged.constant(
    [[[["I", "like", "ragged", "tensors."]],
      [["Oh", "yeah?"], ["What", "can", "you", "use", "them", "for?"]],
      [["Processing", "variable", "length", "data!"]]],
     [[["I", "like", "cheese."], ["Do", "you?"]],
      [["Yes."], ["I", "do."]]]])
conversations.shape
TensorShape([2, None, None, None])
assert conversations.ragged_rank == len(conversations.nested_row_splits)
conversations.ragged_rank  # Number of partitioned dimensions.
3
conversations.flat_values.numpy()
array([b'I', b'like', b'ragged', b'tensors.', b'Oh', b'yeah?', b'What',
       b'can', b'you', b'use', b'them', b'for?', b'Processing',
       b'variable', b'length', b'data!', b'I', b'like', b'cheese.', b'Do',
       b'you?', b'Yes.', b'I', b'do.'], dtype=object)

ממדים פנימיים אחידים

טנזורים מרופטים עם ממדים פנימיים אחידים מקודדים באמצעות tf.Tensor רב מימדי. tf.Tensor עבור tf.Tensor השטוחים (כלומר, values הפנימיים ביותר).

מדים_פנים

rt = tf.RaggedTensor.from_row_splits(
    values=[[1, 3], [0, 0], [1, 3], [5, 3], [3, 3], [1, 2]],
    row_splits=[0, 3, 4, 6])
print(rt)
print("Shape: {}".format(rt.shape))
print("Number of partitioned dimensions: {}".format(rt.ragged_rank))
print("Flat values shape: {}".format(rt.flat_values.shape))
print("Flat values:\n{}".format(rt.flat_values))
<tf.RaggedTensor [[[1, 3], [0, 0], [1, 3]], [[5, 3]], [[3, 3], [1, 2]]]>
Shape: (3, None, 2)
Number of partitioned dimensions: 1
Flat values shape: (6, 2)
Flat values:
[[1 3]
 [0 0]
 [1 3]
 [5 3]
 [3 3]
 [1 2]]

מידות אחידות שאינן פנימיות

טנזורים uniform_row_length עם uniform_row_length אחידים שאינם פנימיים מקודדים על ידי מחיצת שורות בעלות uniform_row_length .

אחיד_אאוטר

rt = tf.RaggedTensor.from_uniform_row_length(
    values=tf.RaggedTensor.from_row_splits(
        values=[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
        row_splits=[0, 3, 5, 9, 10]),
    uniform_row_length=2)
print(rt)
print("Shape: {}".format(rt.shape))
print("Number of partitioned dimensions: {}".format(rt.ragged_rank))
<tf.RaggedTensor [[[10, 11, 12], [13, 14]], [[15, 16, 17, 18], [19]]]>
Shape: (2, 2, None)
Number of partitioned dimensions: 2