עבודה עם שכבות עיבוד מראש

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

עיבוד מקדים של קרס

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

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

עיבוד מקדים זמין

עיבוד מקדים של טקסט

  • tf.keras.layers.TextVectorization : פונה מחרוזות גלם לתוך ייצוג מקודדים שניתן לקרוא על ידי Embedding שכבה או Dense שכבה.

תכונות מספריות בעיבוד מקדים

תכונות קטגוריות עיבוד מקדים

  • tf.keras.layers.CategoryEncoding : תורות שלמות תכונות קטגורים לתוך אחד-חמים, רבים-חמים, או לספור ייצוגים צפופים.
  • tf.keras.layers.Hashing : מבצע hashing תכונת קטגורים, המכונה גם "טריק hashing".
  • tf.keras.layers.StringLookup : פניות מחרוזת קטגורי ערכי ייצוג מקודדים שניתן לקרוא על ידי Embedding שכבה או Dense שכבה.
  • tf.keras.layers.IntegerLookup : תורות שלמות ערכי קטגורים לתוך ייצוג מקודדים שניתן לקרוא על ידי Embedding שכבה או Dense שכבה.

עיבוד מקדים של תמונה

שכבות אלו מיועדות לסטנדרטיזציה של הקלט של מודל תמונה.

  • tf.keras.layers.Resizing : משנה את גודל אצווה של תמונות לגודל היעד.
  • tf.keras.layers.Rescaling : rescales וקיזוזים הערכים של אצווה של התמונה (למשל לעבור תשומות [0, 255] טווח כדי תשומות [0, 1] טווח.
  • tf.keras.layers.CenterCrop : מחזיר לחתוך באמצע של אצווה של תמונות.

הגדלת נתוני תמונה

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

adapt() שיטה

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

  • TextVectorization : מחזיק מיפוי בין אסימוני מחרוזת מדדה שלם
  • StringLookup ו IntegerLookup : להחזיק מיפוי בין ערכי קלט מדדי שלם.
  • Normalization : מחזיקה סטייה הממוצעת ורמת התכונות.
  • Discretization : מחזיק מידע על גבולות דליים ערך.

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

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

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers

data = np.array([[0.1, 0.2, 0.3], [0.8, 0.9, 1.0], [1.5, 1.6, 1.7],])
layer = layers.Normalization()
layer.adapt(data)
normalized_data = layer(data)

print("Features mean: %.2f" % (normalized_data.numpy().mean()))
print("Features std: %.2f" % (normalized_data.numpy().std()))
Features mean: -0.00
Features std: 1.00

adapt() השיטה לוקחת גם מערך numpy או tf.data.Dataset אובייקט. במקרה של StringLookup ו TextVectorization , אתה יכול גם להעביר רשימה של מחרוזות:

data = [
    "ξεῖν᾽, ἦ τοι μὲν ὄνειροι ἀμήχανοι ἀκριτόμυθοι",
    "γίγνοντ᾽, οὐδέ τι πάντα τελείεται ἀνθρώποισι.",
    "δοιαὶ γάρ τε πύλαι ἀμενηνῶν εἰσὶν ὀνείρων:",
    "αἱ μὲν γὰρ κεράεσσι τετεύχαται, αἱ δ᾽ ἐλέφαντι:",
    "τῶν οἳ μέν κ᾽ ἔλθωσι διὰ πριστοῦ ἐλέφαντος,",
    "οἵ ῥ᾽ ἐλεφαίρονται, ἔπε᾽ ἀκράαντα φέροντες:",
    "οἱ δὲ διὰ ξεστῶν κεράων ἔλθωσι θύραζε,",
    "οἵ ῥ᾽ ἔτυμα κραίνουσι, βροτῶν ὅτε κέν τις ἴδηται.",
]
layer = layers.TextVectorization()
layer.adapt(data)
vectorized_text = layer(data)
print(vectorized_text)
tf.Tensor(
[[37 12 25  5  9 20 21  0  0]
 [51 34 27 33 29 18  0  0  0]
 [49 52 30 31 19 46 10  0  0]
 [ 7  5 50 43 28  7 47 17  0]
 [24 35 39 40  3  6 32 16  0]
 [ 4  2 15 14 22 23  0  0  0]
 [36 48  6 38 42  3 45  0  0]
 [ 4  2 13 41 53  8 44 26 11]], shape=(8, 9), dtype=int64)

בנוסף, שכבות ניתנות להתאמה תמיד חושפות אפשרות לקבוע מצב ישירות באמצעות ארגומנטים של בנאי או הקצאת משקל. אם ערכי המדינה נועדו ידוע בשלב הבנייה בשכבה, או מחושבים מחוץ adapt() השיחה, הם יכולים להיות מוגדרים ללא הסתמכות על החישוב הפנימי של השכבה. לדוגמא, אם קבצי אוצר מילות חיצוניים עבור TextVectorization , StringLookup , או IntegerLookup השכבות שכבר קיימים, אלה ניתן לטעון ישירות לתוך שולחנות בדיקה על ידי העברת נתיב לקובץ אוצר המילים בטיעוני הבנאי של השכבה.

הנה דוגמה שבה אנו מופע StringLookup שכבה עם אוצר מילים precomputed:

vocab = ["a", "b", "c", "d"]
data = tf.constant([["a", "c", "d"], ["d", "z", "b"]])
layer = layers.StringLookup(vocabulary=vocab)
vectorized_data = layer(data)
print(vectorized_data)
tf.Tensor(
[[1 3 4]
 [4 0 2]], shape=(2, 3), dtype=int64)

עיבוד מוקדם של נתונים לפני המודל או בתוך המודל

ישנן שתי דרכים בהן תוכל להשתמש בשכבות עיבוד מקדים:

אפשרות 1: ולהפוך אותם לחלק את המודל, כמו זה:

inputs = keras.Input(shape=input_shape)
x = preprocessing_layer(inputs)
outputs = rest_of_the_model(x)
model = keras.Model(inputs, outputs)

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

אפשרות 2: להחיל אותה על שלך tf.data.Dataset , כדי להשיג מערך נתונים יצוותו תשואות של נתונים מעובדים, כמו זה:

dataset = dataset.map(lambda x, y: (preprocessing_layer(x), y))

עם אפשרות זו, העיבוד המקדים שלך יתרחש ב-CPU, באופן אסינכרוני, ויוחזק לפני הכניסה למודל. בנוסף, אם אתה קורא dataset.prefetch(tf.data.AUTOTUNE) על בסיס נתון שלך, החל בעיבוד יקר ביעילות במקביל לאימון:

dataset = dataset.map(lambda x, y: (preprocessing_layer(x), y))
dataset = dataset.prefetch(tf.data.AUTOTUNE)
model.fit(dataset, ...)

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

כאשר פועל על TPU, אתה תמיד צריך למקם עיבוד מקדים שכבות tf.data צינור (למעט Normalization ו Rescaling , אשר לרוץ בסדר על TPU והם נפוצים כמו השכבה הראשונה היא מודל תמונה).

היתרונות של ביצוע עיבוד מקדים בתוך המודל בזמן מסקנות

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

כאשר כל עיבוד הנתונים המקדים הוא חלק מהמודל, אנשים אחרים יכולים לטעון ולהשתמש במודל שלך מבלי להיות מודעים לאופן שבו כל תכונה צפויה להיות מקודדת ומנורמלת. מודל ההסקה שלך יוכל לעבד תמונות גולמיות או נתונים מובנים גולמיים, ולא ידרוש ממשתמשי המודל להיות מודעים לפרטים של למשל סכימת האסימון המשמשת לטקסט, סכימת האינדקס המשמשת לתכונות קטגוריות, בין אם ערכי פיקסלים של תמונה מנורמלים ל [-1, +1] או [0, 1] , וכו 'זה בולט בעוצמתה אם אתה מייצא את המודל שלך ב ריצה נוספת, כגון TensorFlow.js: אתה לא צריך reimplement המקדים שלך צינור ב-JavaScript.

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

inputs = keras.Input(shape=input_shape)
x = preprocessing_layer(inputs)
outputs = training_model(x)
inference_model = keras.Model(inputs, outputs)

מתכונים מהירים

הגדלת נתוני תמונה

שים לב שכבות תמונת נתוני הגדלה פעילות בלבד במהלך אימון (בדומה Dropout השכבה).

from tensorflow import keras
from tensorflow.keras import layers

# Create a data augmentation stage with horizontal flipping, rotations, zooms
data_augmentation = keras.Sequential(
    [
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(0.1),
        layers.RandomZoom(0.1),
    ]
)

# Load some data
(x_train, y_train), _ = keras.datasets.cifar10.load_data()
input_shape = x_train.shape[1:]
classes = 10

# Create a tf.data pipeline of augmented images (and their labels)
train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
train_dataset = train_dataset.batch(16).map(lambda x, y: (data_augmentation(x), y))


# Create a model and train it on the augmented image data
inputs = keras.Input(shape=input_shape)
x = layers.Rescaling(1.0 / 255)(inputs)  # Rescale inputs
outputs = keras.applications.ResNet50(  # Add the rest of the model
    weights=None, input_shape=input_shape, classes=classes
)(x)
model = keras.Model(inputs, outputs)
model.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy")
model.fit(train_dataset, steps_per_epoch=5)
Downloading data from https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
170500096/170498071 [==============================] - 6s 0us/step
170508288/170498071 [==============================] - 6s 0us/step
5/5 [==============================] - 11s 44ms/step - loss: 8.8927
<keras.callbacks.History at 0x7f1c0c3f16d0>

אתה יכול לראות התקנה דומה בפעולה בדוגמא סיווג התמונה מאפסת .

מנרמל תכונות מספריות

# Load some data
(x_train, y_train), _ = keras.datasets.cifar10.load_data()
x_train = x_train.reshape((len(x_train), -1))
input_shape = x_train.shape[1:]
classes = 10

# Create a Normalization layer and set its internal state using the training data
normalizer = layers.Normalization()
normalizer.adapt(x_train)

# Create a model that include the normalization layer
inputs = keras.Input(shape=input_shape)
x = normalizer(inputs)
outputs = layers.Dense(classes, activation="softmax")(x)
model = keras.Model(inputs, outputs)

# Train the model
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy")
model.fit(x_train, y_train)
1563/1563 [==============================] - 3s 2ms/step - loss: 2.1304
<keras.callbacks.History at 0x7f1bc43f40d0>

קידוד מחרוזת תכונות קטגוריות באמצעות קידוד חם אחד

# Define some toy data
data = tf.constant([["a"], ["b"], ["c"], ["b"], ["c"], ["a"]])

# Use StringLookup to build an index of the feature values and encode output.
lookup = layers.StringLookup(output_mode="one_hot")
lookup.adapt(data)

# Convert new test data (which includes unknown feature values)
test_data = tf.constant([["a"], ["b"], ["c"], ["d"], ["e"], [""]])
encoded_data = lookup(test_data)
print(encoded_data)
tf.Tensor(
[[0. 0. 0. 1.]
 [0. 0. 1. 0.]
 [0. 1. 0. 0.]
 [1. 0. 0. 0.]
 [1. 0. 0. 0.]
 [1. 0. 0. 0.]], shape=(6, 4), dtype=float32)

שים לב, כאן, מדד 0 שמורה מחוץ אוצר ערכים (ערכים שלא נראו במהלך adapt() ).

אתה יכול לראות את StringLookup בפעולת סיווג הנתונים המובנה מאפס למשל.

קידוד תכונות קטגוריות של מספר שלם באמצעות קידוד חם אחד

# Define some toy data
data = tf.constant([[10], [20], [20], [10], [30], [0]])

# Use IntegerLookup to build an index of the feature values and encode output.
lookup = layers.IntegerLookup(output_mode="one_hot")
lookup.adapt(data)

# Convert new test data (which includes unknown feature values)
test_data = tf.constant([[10], [10], [20], [50], [60], [0]])
encoded_data = lookup(test_data)
print(encoded_data)
tf.Tensor(
[[0. 0. 1. 0. 0.]
 [0. 0. 1. 0. 0.]
 [0. 1. 0. 0. 0.]
 [1. 0. 0. 0. 0.]
 [1. 0. 0. 0. 0.]
 [0. 0. 0. 0. 1.]], shape=(6, 5), dtype=float32)

הערה כי המדד 0 שמורה חסר ערכים (שבו אתה צריך לציין כערך 0), ומדד 1 שמורה מחוץ אוצר ערכים (ערכים שלא נראו במהלך adapt() ). אתה יכול להגדיר זאת על ידי שימוש mask_token ו oov_token טיעוני בנאי של IntegerLookup .

אתה יכול לראות את IntegerLookup בפעולה בדוגמה סיווג נתונים מובנים מאפס .

החלת טריק הגיבוב על תכונה קטגורית במספר שלם

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

# Sample data: 10,000 random integers with values between 0 and 100,000
data = np.random.randint(0, 100000, size=(10000, 1))

# Use the Hashing layer to hash the values to the range [0, 64]
hasher = layers.Hashing(num_bins=64, salt=1337)

# Use the CategoryEncoding layer to multi-hot encode the hashed values
encoder = layers.CategoryEncoding(num_tokens=64, output_mode="multi_hot")
encoded_data = encoder(hasher(data))
print(encoded_data.shape)
(10000, 64)

קידוד טקסט כרצף של מדדי אסימון

ככה אתה צריך preprocess טקסט יועבר אל Embedding שכבה.

# Define some text data to adapt the layer
adapt_data = tf.constant(
    [
        "The Brain is wider than the Sky",
        "For put them side by side",
        "The one the other will contain",
        "With ease and You beside",
    ]
)

# Create a TextVectorization layer
text_vectorizer = layers.TextVectorization(output_mode="int")
# Index the vocabulary via `adapt()`
text_vectorizer.adapt(adapt_data)

# Try out the layer
print(
    "Encoded text:\n", text_vectorizer(["The Brain is deeper than the sea"]).numpy(),
)

# Create a simple model
inputs = keras.Input(shape=(None,), dtype="int64")
x = layers.Embedding(input_dim=text_vectorizer.vocabulary_size(), output_dim=16)(inputs)
x = layers.GRU(8)(x)
outputs = layers.Dense(1)(x)
model = keras.Model(inputs, outputs)

# Create a labeled dataset (which includes unknown tokens)
train_dataset = tf.data.Dataset.from_tensor_slices(
    (["The Brain is deeper than the sea", "for if they are held Blue to Blue"], [1, 0])
)

# Preprocess the string inputs, turning them into int sequences
train_dataset = train_dataset.batch(2).map(lambda x, y: (text_vectorizer(x), y))
# Train the model on the int sequences
print("\nTraining model...")
model.compile(optimizer="rmsprop", loss="mse")
model.fit(train_dataset)

# For inference, you can export a model that accepts strings as input
inputs = keras.Input(shape=(1,), dtype="string")
x = text_vectorizer(inputs)
outputs = model(x)
end_to_end_model = keras.Model(inputs, outputs)

# Call the end-to-end model on test data (which includes unknown tokens)
print("\nCalling end-to-end model on test string...")
test_data = tf.constant(["The one the other will absorb"])
test_output = end_to_end_model(test_data)
print("Model output:", test_output)
Encoded text:
 [[ 2 19 14  1  9  2  1]]

Training model...
1/1 [==============================] - 3s 3s/step - loss: 0.4776

Calling end-to-end model on test string...
Model output: tf.Tensor([[0.04233753]], shape=(1, 1), dtype=float32)

אתה יכול לראות את TextVectorization השכבה בפעולה, בשילוב עם Embedding מצב, בדוגמה סיווג הטקסט מאפס .

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

קידוד טקסט כמטריצה ​​צפופה של ngrams עם קידוד רב-חם

ככה אתה צריך preprocess טקסט יועבר אלי Dense שכבה.

# Define some text data to adapt the layer
adapt_data = tf.constant(
    [
        "The Brain is wider than the Sky",
        "For put them side by side",
        "The one the other will contain",
        "With ease and You beside",
    ]
)
# Instantiate TextVectorization with "multi_hot" output_mode
# and ngrams=2 (index all bigrams)
text_vectorizer = layers.TextVectorization(output_mode="multi_hot", ngrams=2)
# Index the bigrams via `adapt()`
text_vectorizer.adapt(adapt_data)

# Try out the layer
print(
    "Encoded text:\n", text_vectorizer(["The Brain is deeper than the sea"]).numpy(),
)

# Create a simple model
inputs = keras.Input(shape=(text_vectorizer.vocabulary_size(),))
outputs = layers.Dense(1)(inputs)
model = keras.Model(inputs, outputs)

# Create a labeled dataset (which includes unknown tokens)
train_dataset = tf.data.Dataset.from_tensor_slices(
    (["The Brain is deeper than the sea", "for if they are held Blue to Blue"], [1, 0])
)

# Preprocess the string inputs, turning them into int sequences
train_dataset = train_dataset.batch(2).map(lambda x, y: (text_vectorizer(x), y))
# Train the model on the int sequences
print("\nTraining model...")
model.compile(optimizer="rmsprop", loss="mse")
model.fit(train_dataset)

# For inference, you can export a model that accepts strings as input
inputs = keras.Input(shape=(1,), dtype="string")
x = text_vectorizer(inputs)
outputs = model(x)
end_to_end_model = keras.Model(inputs, outputs)

# Call the end-to-end model on test data (which includes unknown tokens)
print("\nCalling end-to-end model on test string...")
test_data = tf.constant(["The one the other will absorb"])
test_output = end_to_end_model(test_data)
print("Model output:", test_output)
WARNING:tensorflow:5 out of the last 1567 calls to <function PreprocessingLayer.make_adapt_function.<locals>.adapt_step at 0x7f1b9c5c5290> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for  more details.
Encoded text:
 [[1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 1. 0. 0. 0. 0. 0.

  0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0. 0.]]

Training model...
1/1 [==============================] - 0s 231ms/step - loss: 1.0046

Calling end-to-end model on test string...
Model output: tf.Tensor([[-0.54753447]], shape=(1, 1), dtype=float32)

קידוד טקסט כמטריצה ​​צפופה של ngrams עם שקלול TF-IDF

זוהי דרך חלופית של עיבוד מקדים טקסט לפני העברתו לבית Dense שכבה.

# Define some text data to adapt the layer
adapt_data = tf.constant(
    [
        "The Brain is wider than the Sky",
        "For put them side by side",
        "The one the other will contain",
        "With ease and You beside",
    ]
)
# Instantiate TextVectorization with "tf-idf" output_mode
# (multi-hot with TF-IDF weighting) and ngrams=2 (index all bigrams)
text_vectorizer = layers.TextVectorization(output_mode="tf-idf", ngrams=2)
# Index the bigrams and learn the TF-IDF weights via `adapt()`

with tf.device("CPU"):
    # A bug that prevents this from running on GPU for now.
    text_vectorizer.adapt(adapt_data)

# Try out the layer
print(
    "Encoded text:\n", text_vectorizer(["The Brain is deeper than the sea"]).numpy(),
)

# Create a simple model
inputs = keras.Input(shape=(text_vectorizer.vocabulary_size(),))
outputs = layers.Dense(1)(inputs)
model = keras.Model(inputs, outputs)

# Create a labeled dataset (which includes unknown tokens)
train_dataset = tf.data.Dataset.from_tensor_slices(
    (["The Brain is deeper than the sea", "for if they are held Blue to Blue"], [1, 0])
)

# Preprocess the string inputs, turning them into int sequences
train_dataset = train_dataset.batch(2).map(lambda x, y: (text_vectorizer(x), y))
# Train the model on the int sequences
print("\nTraining model...")
model.compile(optimizer="rmsprop", loss="mse")
model.fit(train_dataset)

# For inference, you can export a model that accepts strings as input
inputs = keras.Input(shape=(1,), dtype="string")
x = text_vectorizer(inputs)
outputs = model(x)
end_to_end_model = keras.Model(inputs, outputs)

# Call the end-to-end model on test data (which includes unknown tokens)
print("\nCalling end-to-end model on test string...")
test_data = tf.constant(["The one the other will absorb"])
test_output = end_to_end_model(test_data)
print("Model output:", test_output)
WARNING:tensorflow:6 out of the last 1568 calls to <function PreprocessingLayer.make_adapt_function.<locals>.adapt_step at 0x7f1b9f6eae60> triggered tf.function retracing. Tracing is expensive and the excessive number of tracings could be due to (1) creating @tf.function repeatedly in a loop, (2) passing tensors with different shapes, (3) passing Python objects instead of tensors. For (1), please define your @tf.function outside of the loop. For (2), @tf.function has experimental_relax_shapes=True option that relaxes argument shapes that can avoid unnecessary retracing. For (3), please refer to https://www.tensorflow.org/guide/function#controlling_retracing and https://www.tensorflow.org/api_docs/python/tf/function for  more details.
Encoded text:
 [[5.461647  1.6945957 0.        0.        0.        0.        0.

  0.        0.        0.        0.        0.        0.        0.
  0.        0.        1.0986123 1.0986123 1.0986123 0.        0.
  0.        0.        0.        0.        0.        0.        0.
  1.0986123 0.        0.        0.        0.        0.        0.
  0.        1.0986123 1.0986123 0.        0.        0.       ]]

Training model...
1/1 [==============================] - 0s 239ms/step - loss: 4.4868

Calling end-to-end model on test string...
Model output: tf.Tensor([[0.25670475]], shape=(1, 1), dtype=float32)

רעיונות חשובים

עבודה עם שכבות חיפוש עם אוצר מילים גדול מאוד

אתה עלול למצוא את עצמך עובד עם אוצר מילים גדול מאוד בתוך TextVectorization , A StringLookup השכבה, או IntegerLookup השכבה. בדרך כלל, אוצר מילים גדול מ-500MB ייחשב "גדול מאוד".

במקרה כזה, עבור הביצועים הטובים ביותר, כדאי להימנע משימוש adapt() . במקום זאת, חשב מראש את אוצר המילים שלך (תוכל להשתמש ב- Apache Beam או TF Transform בשביל זה) ואחסן אותו בקובץ. לאחר מכן טען את אוצר המילים לתוך השכבה בשלב הבנייה על ידי העברת נתיב הקבצים כמו vocabulary הטיעון.

שימוש בשכבות בדיקה על תרמיל TPU או עם ParameterServerStrategy .

קיימת בעיה יוצאת דופן שגורמת ביצועים להשפיל כאשר באמצעות TextVectorization , StringLookup , או IntegerLookup שכבה בעודו מתאמן על תרמיל TPU או במחשבים מרובים באמצעות ParameterServerStrategy . זה אמור להתוקן ב- TensorFlow 2.7.