Praca z warstwami przetwarzania wstępnego

Zobacz na TensorFlow.org Uruchom w Google Colab Wyświetl źródło na GitHub Pobierz notatnik

Wstępne przetwarzanie Keras

Interfejs API warstw przetwarzania wstępnego Keras umożliwia programistom tworzenie natywnych potoków przetwarzania danych wejściowych Keras. Te potoki przetwarzania danych wejściowych mogą być używane jako niezależny kod przetwarzania wstępnego w przepływach pracy innych niż Keras, połączone bezpośrednio z modelami Keras i eksportowane jako część Keras SavedModel.

Dzięki warstwom przetwarzania wstępnego Keras można budować i eksportować modele, które są naprawdę kompleksowe: modele, które akceptują nieprzetworzone obrazy lub nieprzetworzone dane strukturalne jako dane wejściowe; modele, które samodzielnie obsługują normalizację funkcji lub indeksowanie wartości funkcji.

Dostępne przetwarzanie wstępne

Wstępne przetwarzanie tekstu

  • tf.keras.layers.TextVectorization : zamienia surowe ciągi znaków na zakodowaną reprezentację, która może być odczytana przez Embedding warstwy lub Dense warstwie.

Wstępne przetwarzanie cech numerycznych

Wstępne przetwarzanie cech kategorialnych

  • tf.keras.layers.CategoryEncoding : obroty całkowite kategorycznych funkcji w jednym gorące, multi-gorące, albo liczyć gęstych przedstawień.
  • tf.keras.layers.Hashing : Wykonuje kategoryczny cecha mieszaja, znany również jako „mieszający trick”.
  • tf.keras.layers.StringLookup : Włącza kategoryczny łańcuch wartości zakodowanej reprezentacji, które mogą być odczytywane przez Embedding warstwy lub Dense warstwie.
  • tf.keras.layers.IntegerLookup : zwojów całkowitymi wartościami kategoryczne język zakodowanej reprezentacji, która może być odczytywana przez Embedding warstwy lub Dense warstwy.

Wstępne przetwarzanie obrazu

Te warstwy służą do standaryzacji danych wejściowych modelu obrazu.

Powiększanie danych obrazu

Warstwy te stosują losowe transformacje rozszerzające do partii obrazów. Są aktywne tylko podczas treningu.

adapt() Sposób

Niektóre warstwy przetwarzania wstępnego mają stan wewnętrzny, który można obliczyć na podstawie próbki danych uczących. Lista stanowych warstw przetwarzania wstępnego to:

  • TextVectorization : posiada odwzorowanie między tokeny ciąg i indeksów całkowitych
  • StringLookup i IntegerLookup : przytrzymaj mapowanie pomiędzy wartościami wejściowymi i indeksów całkowitych.
  • Normalization : posiada średnią i odchylenie standardowe cech.
  • Discretization : zawiera informacje o wartości granic wiadra.

Co najważniejsze, te warstwy są dla elastyczność. Ich stan nie jest ustalany podczas treningu; musi być ustawiony przed treningiem, albo poprzez inicjowanie je z precomputed stałej, lub „dostosowania” ich danych.

Ustawienie stanu warstwy przerób wystawiając go do danych treningowych, poprzez adapt() metody:

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() sposobie, albo tablicę NumPy lub tf.data.Dataset obiektu. W przypadku StringLookup i TextVectorization , można również przekazać listę ciągów:

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)

Ponadto warstwy adaptowalne zawsze udostępniają opcję bezpośredniego ustawienia stanu za pomocą argumentów konstruktora lub przypisania wagi. Jeżeli zamierzone wartości stanu są znane w warstwie czas budowy, lub są obliczane zewnątrz adapt() połączenia, mogą być ustawione bez polegania na wewnętrznym obliczeń warstwy. Na przykład, jeśli zewnętrzne pliki słownictwo dla TextVectorization , StringLookup lub IntegerLookup warstw już istnieje, te mogą być ładowane bezpośrednio do tabel odnośników przekazując ścieżkę do pliku słownika w argumentów konstruktora warstwy.

Oto przykład, gdzie instancji StringLookup warstwę precomputed słownictwa:

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)

Wstępne przetwarzanie danych przed modelem lub wewnątrz modelu

Istnieją dwa sposoby używania warstw przetwarzania wstępnego:

Wariant 1: uczynić je częścią modelu, podobnie jak to:

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

Dzięki tej opcji wstępne przetwarzanie będzie odbywać się na urządzeniu synchronicznie z resztą wykonania modelu, co oznacza, że ​​będzie ono korzystać z akceleracji GPU. Jeśli jesteś szkolenie na GPU, to najlepszym rozwiązaniem dla Normalization warstwy, a dla wszystkich warstw obrazu przerób i powiększanie danych.

Opcja 2: zastosować go do tf.data.Dataset , tak aby uzyskać zbiór danych, które przynosi partie wstępnie przygotowane dane w następujący sposób:

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

Dzięki tej opcji wstępne przetwarzanie będzie odbywać się na procesorze, asynchronicznie i zostanie zbuforowane przed wejściem do modelu. Ponadto, jeśli zadzwonisz dataset.prefetch(tf.data.AUTOTUNE) na zbiorze danych, wstępne przetwarzanie stanie efektywnie równolegle ze szkolenia:

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

Jest najlepszym rozwiązaniem dla TextVectorization , a wszystkie dane strukturyzowane przerób warstw. Może to być również dobra opcja, jeśli trenujesz na procesorze i używasz warstw wstępnego przetwarzania obrazu.

Podczas pracy w TPU, należy zawsze umieszczać przerób warstw w tf.data rurociągu (z wyjątkiem Normalization i Rescaling , które działają dobrze na TPU i są powszechnie stosowane jako pierwsza warstwa jest modelem obrazu).

Korzyści z wykonywania przetwarzania wstępnego wewnątrz modelu w czasie wnioskowania

Nawet jeśli wybierzesz opcję 2, możesz później wyeksportować model typu end-to-end tylko wnioskowania, który będzie zawierał warstwy przetwarzania wstępnego. Kluczową korzyścią tego rozwiązania jest to, że to sprawia, że model przenośny i pomaga zmniejszyć szkolenia / służąc pochylać .

Gdy wszystkie wstępne przetwarzanie danych jest częścią modelu, inne osoby mogą załadować i używać Twojego modelu bez konieczności zdawania sobie sprawy z tego, jak każda funkcja ma być zakodowana i znormalizowana. Twój model wnioskowania będzie w stanie przetwarzać nieprzetworzone obrazy lub nieprzetworzone dane strukturalne i nie będzie wymagał od użytkowników modelu znajomości szczegółów np. schematu tokenizacji używanego dla tekstu, schematu indeksowania używanego dla cech kategorialnych, czy wartości pikseli obrazu są znormalizowane do [-1, +1] lub [0, 1] , itd. jest to szczególnie mocny jeśli eksportowania modelu do innego wykonywania, takie jak TensorFlow.js: nie będzie musiał reimplement swoje wstępne przetwarzanie potok w JavaScript.

Jeśli początkowo umieścić swoje przerób warstw w tf.data rurociągu, można wyeksportować model wnioskowania, że pakiety przebiegiem wyprzedzającym. Po prostu stwórz instancję nowego modelu, który łączy warstwy przetwarzania wstępnego z modelem szkoleniowym:

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

Szybkie przepisy

Powiększanie danych obrazu

Należy zauważyć, że warstwy powiększania dane obrazu są aktywne jedynie w czasie treningu (podobnie do Dropout warstwy).

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>

Można zobaczyć podobną konfigurację w akcji na przykładzie klasyfikacji obrazu od podstaw .

Normalizowanie cech liczbowych

# 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>

Kodowanie funkcji kategorycznych ciągów za pomocą kodowania jednorazowego

# 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)

Zauważ, że tutaj, indeks 0 jest zarezerwowana dla out-of-słownictwo wartości (wartości, które nie były widoczne podczas adapt() ).

Można zobaczyć StringLookup w akcji w Structured klasyfikacji danych od podstaw np.

Kodowanie funkcji kategorycznych liczb całkowitych za pomocą kodowania jednorazowego

# 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)

Należy zauważyć, że indeks 0 jest zarezerwowana dla brakujących wartości (które należy określić jako wartość 0), a indeks 1 jest zarezerwowany dla out-of-słownictwo wartości (wartości, które nie były widoczne podczas adapt() ). Można skonfigurować to za pomocą mask_token i oov_token argumenty konstruktora IntegerLookup .

Można zobaczyć IntegerLookup w akcji w przykładowej strukturze klasyfikacji danych od podstaw .

Stosowanie sztuczki haszującej do funkcji kategorycznej liczby całkowitej

Jeśli masz funkcję kategoryczną, która może przyjmować wiele różnych wartości (rzędu 10e3 lub wyższych), gdzie każda wartość pojawia się w danych tylko kilka razy, indeksowanie i kodowanie wartości funkcji na gorąco staje się niepraktyczne i nieefektywne. Zamiast tego dobrym pomysłem może być zastosowanie „sztuczki haszującej”: mieszaj wartości do wektora o stałym rozmiarze. Pozwala to na zarządzanie rozmiarem przestrzeni funkcji i eliminuje potrzebę jawnego indeksowania.

# 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)

Kodowanie tekstu jako ciągu indeksów tokenów

W ten sposób należy Preprocesuj tekst mają być przekazane do Embedding warstwy.

# 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)

Można zobaczyć TextVectorization warstwy w działaniu, w połączeniu z Embedding trybie, na przykład klasyfikacji tekstowej od zera .

Należy pamiętać, że podczas treningu taki model, aby uzyskać najlepszą wydajność, należy zawsze używać TextVectorization warstwę jako część rurociągu wejściowym.

Kodowanie tekstu jako gęsta macierz ngramów z kodowaniem multi-hot

W ten sposób należy Preprocesuj tekst ma być przekazany do Dense warstwy.

# 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)

Kodowanie tekstu jako gęstej macierzy ngramów z ważeniem TF-IDF

Jest to alternatywny sposób przeróbki tekstu przed przekazaniem go do Dense warstwy.

# 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)

Ważne uwagi

Praca z warstwami wyszukiwania z bardzo dużymi słownikami

Może znaleźć się pracy z bardzo dużym słownictwo w TextVectorization , a StringLookup warstwy, albo IntegerLookup warstwy. Zazwyczaj słownictwo większe niż 500 MB będzie uważane za „bardzo duże”.

W takim przypadku, aby uzyskać najlepszą wydajność, należy unikać adapt() . Zamiast tego z góry oblicz swoje słownictwo (możesz użyć do tego Apache Beam lub TF Transform) i zapisz je w pliku. Załaduj słownictwo do warstwy w czasie budowy przepuszczając filepath jako vocabulary argumentu.

Korzystanie z wyszukiwania warstw na podcastów TPU lub ParameterServerStrategy .

Jest wybitnym problem, który powoduje, że wydajność do rozkładu przy stosowaniu TextVectorization , StringLookup lub IntegerLookup warstwa podczas treningu na podcastów TPU lub na wielu komputerach za pomocą ParameterServerStrategy . Zostanie to naprawione w TensorFlow 2.7.