การทำงานกับเลเยอร์ก่อนการประมวลผล

ดูบน TensorFlow.org ทำงานใน Google Colab ดูแหล่งที่มาบน GitHub ดาวน์โหลดโน๊ตบุ๊ค

การประมวลผลล่วงหน้าของ Keras

API เลเยอร์การประมวลผลล่วงหน้าของ Keras ช่วยให้นักพัฒนาสามารถสร้างไปป์ไลน์การประมวลผลอินพุตของ Keras ได้ ไปป์ไลน์การประมวลผลอินพุตเหล่านี้สามารถใช้เป็นโค้ดประมวลผลล่วงหน้าอิสระในเวิร์กโฟลว์ที่ไม่ใช่ Keras รวมกับโมเดล Keras โดยตรง และส่งออกเป็นส่วนหนึ่งของ Keras SavedModel

ด้วยเลเยอร์การประมวลผลล่วงหน้าของ Keras คุณสามารถสร้างและส่งออกโมเดลที่เป็น end-to-end อย่างแท้จริง: โมเดลที่ยอมรับภาพดิบหรือข้อมูลที่มีโครงสร้างดิบเป็นอินพุต โมเดลที่จัดการการทำให้เป็นมาตรฐานของคุณลักษณะหรือการสร้างดัชนีค่าคุณลักษณะด้วยตัวเอง

การประมวลผลล่วงหน้าที่มีอยู่

การประมวลผลข้อความล่วงหน้า

  • tf.keras.layers.TextVectorization : เปลี่ยนสตริงดิบให้เป็นตัวแทนการเข้ารหัสที่สามารถอ่านได้โดย Embedding ชั้นหรือ Dense ชั้น

คุณสมบัติเชิงตัวเลข การประมวลผลล่วงหน้า

  • tf.keras.layers.Normalization : ดำเนินการมีฉลาดปกติของคุณสมบัติการป้อนข้อมูล
  • tf.keras.layers.Discretization : เปลี่ยนคุณสมบัติตัวเลขอย่างต่อเนื่องเข้าไปในจำนวนเต็มคุณสมบัติเด็ดขาด

คุณสมบัติตามหมวดหมู่การประมวลผลล่วงหน้า

  • tf.keras.layers.CategoryEncoding : ผลัดจำนวนเต็มคุณสมบัติเด็ดขาดเป็นหนึ่งร้อนหลายร้อนหรือนับการแสดงความหนาแน่นสูง
  • tf.keras.layers.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 หรือโดยการ "ปรับตัว" พวกเขาในข้อมูล

คุณตั้งค่าสถานะของชั้น preprocessing โดยการเปิดเผยข้อมูลการฝึกอบรมผ่าน 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 ชั้นและสำหรับภาพทั้งหมด preprocessing และชั้นเสริมข้อมูล

ตัวเลือกที่ 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 และข้อมูลที่มีโครงสร้างทั้งหมด preprocessing ชั้น นอกจากนี้ยังอาจเป็นทางเลือกที่ดีหากคุณกำลังฝึกเกี่ยวกับ CPU และคุณใช้เลเยอร์การประมวลผลภาพล่วงหน้า

เมื่อทำงานบน TPU คุณควรวาง preprocessing ชั้นใน tf.data ท่อ (มีข้อยกเว้นของ Normalization และ Rescaling ซึ่งทำงานได้ดีบน TPU และมีการใช้กันทั่วไปว่าเป็นชั้นแรกเป็นรูปแบบของภาพ)

ประโยชน์ของการประมวลผลล่วงหน้าภายในโมเดล ณ เวลาอนุมาน

แม้ว่าคุณจะใช้ตัวเลือก 2 ในภายหลัง คุณอาจต้องการส่งออกโมเดล end-to-end แบบอนุมานเท่านั้นที่จะรวมเลเยอร์การประมวลผลล่วงหน้า ประโยชน์ที่สำคัญในการทำเช่นนี้ก็คือว่ามันทำให้รูปแบบของคุณแบบพกพาและมันจะช่วยลด การฝึกอบรม / การให้บริการเอียง

เมื่อการประมวลผลข้อมูลล่วงหน้าทั้งหมดเป็นส่วนหนึ่งของโมเดล บุคคลอื่นสามารถโหลดและใช้โมเดลของคุณได้โดยไม่ต้องรู้ว่าคุณลักษณะแต่ละรายการจะถูกเข้ารหัสและทำให้เป็นมาตรฐานได้อย่างไร โมเดลการอนุมานของคุณจะสามารถประมวลผลภาพดิบหรือข้อมูลที่มีโครงสร้างแบบดิบได้ และจะไม่กำหนดให้ผู้ใช้โมเดลต้องทราบรายละเอียด เช่น รูปแบบการใช้โทเค็นที่ใช้สำหรับข้อความ รูปแบบการจัดทำดัชนีที่ใช้สำหรับคุณสมบัติการจัดหมวดหมู่ ไม่ว่าจะเป็นค่าพิกเซลของภาพ จะปกติไป [-1, +1] หรือ [0, 1] ฯลฯ นี้จะมีประสิทธิภาพโดยเฉพาะอย่างยิ่งถ้าคุณกำลังส่งออกรูปแบบของคุณรันไทม์อื่นเช่น TensorFlow.js: คุณจะไม่ต้อง reimplement ประมวลผลเบื้องต้นของคุณ ไปป์ไลน์ใน JavaScript

หากคุณเริ่มใส่ชั้น preprocessing คุณในของคุณ tf.data ท่อคุณสามารถส่งออกรูปแบบการอนุมานว่าแพคเกจการ preprocessing เพียงยกตัวอย่างโมเดลใหม่ที่เชื่อมโยงเลเยอร์การประมวลผลล่วงหน้าและโมเดลการฝึกของคุณ:

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 ชั้นเป็นส่วนหนึ่งของท่อป้อนข้อมูล

การเข้ารหัสข้อความเป็นเมทริกซ์หนาแน่นของ ngram ด้วยการเข้ารหัสแบบหลายจุด

นี่คือวิธีที่คุณควร 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)

การเข้ารหัสข้อความเป็นเมทริกซ์หนาแน่นของ ngram ด้วยการให้น้ำหนัก TF-IDF

นี่คือทางเลือกของการ preprocessing ข้อความก่อนที่จะผ่านไปยัง 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)

Gotchas ที่สำคัญ

ทำงานกับเลเยอร์การค้นหาด้วยคำศัพท์ขนาดใหญ่มาก

คุณอาจพบว่าตัวเองทำงานกับคำศัพท์ที่มีขนาดใหญ่มากใน TextVectorization เป็น StringLookup ชั้นหรือ IntegerLookup ชั้น โดยปกติ คำศัพท์ที่มีขนาดใหญ่กว่า 500MB จะถือว่า "ใหญ่มาก"

ในกรณีเช่นนี้เพื่อให้ได้ประสิทธิภาพที่ดีที่สุดที่คุณควรหลีกเลี่ยงการใช้ adapt() ให้คำนวณคำศัพท์ของคุณล่วงหน้า (คุณสามารถใช้ Apache Beam หรือ TF Transform สำหรับสิ่งนี้) และจัดเก็บไว้ในไฟล์ แล้วโหลดคำศัพท์ในชั้นในเวลาการก่อสร้างโดยผ่าน filepath เป็น vocabulary โต้แย้ง

ใช้เลเยอร์การค้นหาบนฝัก TPU หรือ ParameterServerStrategy

มีปัญหาที่โดดเด่นที่ทำให้ประสิทธิภาพการทำงานลดลงเมื่อใช้เป็น TextVectorization , StringLookup หรือ IntegerLookup ชั้นในขณะที่การฝึกอบรมในฝัก TPU หรือหลายเครื่องผ่าน ParameterServerStrategy มีกำหนดจะแก้ไขใน TensorFlow 2.7