@@ -87,7 +87,7 @@ are only active during training.
8787- ` layer_random_contrast() `
8888
8989
90- ## The ` adapt() ` method
90+ ## The ` adapt() ` function
9191
9292Some preprocessing layers have an internal state that can be computed based on
9393a sample of the training data. The list of stateful preprocessing layers is:
@@ -102,12 +102,12 @@ Crucially, these layers are **non-trainable**. Their state is not set during tra
102102must be set ** before training** , either by initializing them from a precomputed constant,
103103or by "adapting" them on data.
104104
105- You set the state of a preprocessing layer by exposing it to training data, via the
106- ` adapt() ` method :
105+ You set the state of a preprocessing layer by exposing it to training data, via
106+ ` adapt() ` :
107107
108108``` {r}
109- data <- rbind(c(0.1, 0.2, 0.3),
110- c(0.8, 0.9, 1.0),
109+ data <- rbind(c(0.1, 0.2, 0.3),
110+ c(0.8, 0.9, 1.0),
111111 c(1.5, 1.6, 1.7))
112112layer <- layer_normalization()
113113adapt(layer, data)
@@ -118,22 +118,25 @@ sprintf("Features std: %.2f", sd(normalized_data))
118118```
119119
120120
121- The ` adapt() ` method takes either an R array, numpy array, or a
122- ` tf.data.Dataset ` object . In the case of ` layer_string_lookup() ` and
121+ ` adapt() ` takes either an array or a
122+ ` tf.data.Dataset ` . In the case of ` layer_string_lookup() ` and
123123` layer_text_vectorization() ` , you can also pass a character vector:
124124
125125
126126``` {r}
127127data <- c(
128- "ξεῖν᾽, ἦ τοι μὲν ὄνειροι ἀμήχανοι ἀκριτόμυθοι",
129- "γίγνοντ᾽, οὐδέ τι πάντα τελείεται ἀνθρώποισι.",
130- "δοιαὶ γάρ τε πύλαι ἀμενηνῶν εἰσὶν ὀνείρων:",
131- "αἱ μὲν γὰρ κεράεσσι τετεύχαται, αἱ δ᾽ ἐλέφαντι:",
132- "τῶν οἳ μέν κ᾽ ἔλθωσι διὰ πριστοῦ ἐλέφαντος,",
133- "οἵ ῥ᾽ ἐλεφαίρονται, ἔπε᾽ ἀκράαντα φέροντες:",
134- "οἱ δὲ διὰ ξεστῶν κεράων ἔλθωσι θύραζε,",
135- "οἵ ῥ᾽ ἔτυμα κραίνουσι, βροτῶν ὅτε κέν τις ἴδηται."
128+ "Congratulations!",
129+ "Today is your day.",
130+ "You're off to Great Places!",
131+ "You're off and away!",
132+ "You have brains in your head.",
133+ "You have feet in your shoes.",
134+ "You can steer yourself",
135+ "any direction you choose.",
136+ "You're on your own. And you know what you know.",
137+ "And YOU are the one who'll decide where to go."
136138)
139+
137140layer = layer_text_vectorization()
138141layer %>% adapt(data)
139142vectorized_text <- layer(data)
@@ -170,7 +173,7 @@ There are two ways you could be using preprocessing layers:
170173
171174``` {r, eval = FALSE}
172175input <- layer_input(shape = input_shape)
173- output <- inputs %>%
176+ output <- input %>%
174177 preprocessing_layer() %>%
175178 rest_of_the_model()
176179model <- keras_model(input, output)
@@ -189,7 +192,7 @@ batches of preprocessed data, like this:
189192``` {r, eval = FALSE}
190193library(tfdatasets)
191194dataset <- ... # define dataset
192- dataset <- dataset %>%
195+ dataset <- dataset %>%
193196 dataset_map(function(x, y) list(preprocessing_layer(x), y))
194197```
195198
@@ -200,7 +203,7 @@ efficiently in parallel with training:
200203
201204``` {r, eval = FALSE}
202205dataset <- dataset %>%
203- dataset_map(function(x, y) list(preprocessing_layer(x), y)) %>%
206+ dataset_map(function(x, y) list(preprocessing_layer(x), y)) %>%
204207 dataset_prefetch()
205208model %>% fit(dataset)
206209```
@@ -209,10 +212,6 @@ This is the best option for `layer_text_vectorization()`, and all structured
209212data preprocessing layers. It can also be a good option if you're training on
210213CPU and you use image preprocessing layers.
211214
212- ** When running on TPU, you should always place preprocessing layers in the ` tf.data ` pipeline**
213- (with the exception of ` layer_normalization() ` and ` layer_rescaling ` , which run
214- fine on TPU and are commonly used as the first layer is an image model).
215-
216215
217216## Benefits of doing preprocessing inside the model at inference time
218217
@@ -226,7 +225,7 @@ your model without having to be aware of how each feature is expected to be
226225encoded & normalized. Your inference model will be able to process raw images or
227226raw structured data, and will not require users of the model to be aware of the
228227details of e.g. the tokenization scheme used for text, the indexing scheme used
229- for categorical features, whether image pixel values are normalized to ` [-1, +1] `
228+ for categorical features, whether image pixel values are normalized to ` [-1, +1] `
230229or to ` [0, 1] ` , etc. This is especially powerful if you're exporting your model
231230to another runtime, such as TensorFlow.js: you won't have to reimplement your
232231preprocessing pipeline in JavaScript.
@@ -257,7 +256,7 @@ library(keras)
257256library(tfdatasets)
258257
259258# Create a data augmentation stage with horizontal flipping, rotations, zooms
260- data_augmentation <-
259+ data_augmentation <-
261260 keras_model_sequential() %>%
262261 layer_random_flip("horizontal") %>%
263262 layer_random_rotation(0.1) %>%
@@ -281,7 +280,7 @@ resnet <- application_resnet50(weights = NULL,
281280 classes = classes)
282281
283282input <- layer_input(shape = input_shape)
284- output <- input %>%
283+ output <- input %>%
285284 layer_rescaling(1 / 255) %>% # Rescale inputs
286285 resnet()
287286
@@ -301,9 +300,9 @@ You can see a similar setup in action in the example
301300library(tensorflow)
302301library(keras)
303302c(c(x_train, y_train), ...) %<-% dataset_cifar10()
304- x_train <- x_train %>%
303+ x_train <- x_train %>%
305304 array_reshape(c(dim(x_train)[1], -1L)) # flatten each case
306-
305+
307306input_shape <- dim(x_train)[-1] # keras layers automatically add the batch dim
308307classes <- 10
309308
@@ -313,16 +312,16 @@ normalizer %>% adapt(x_train)
313312
314313# Create a model that include the normalization layer
315314input <- layer_input(shape = input_shape)
316- output <- input %>%
317- normalizer() %>%
318- layer_dense(classes, activation = "softmax")
315+ output <- input %>%
316+ normalizer() %>%
317+ layer_dense(classes, activation = "softmax")
319318
320319model <- keras_model(input, output) %>%
321- compile(optimizer = "adam",
320+ compile(optimizer = "adam",
322321 loss = "sparse_categorical_crossentropy")
323322
324323# Train the model
325- model %>%
324+ model %>%
326325 fit(x_train, y_train)
327326```
328327
@@ -331,7 +330,7 @@ model %>%
331330
332331``` {r}
333332# Define some toy data
334- data <- as_tensor(c("a", "b", "c", "b", "c", "a")) %>%
333+ data <- as_tensor(c("a", "b", "c", "b", "c", "a")) %>%
335334 k_reshape(c(-1, 1)) # reshape into matrix with shape: (6, 1)
336335
337336# Use layer_string_lookup() to build an index of the feature values and encode output.
@@ -396,8 +395,8 @@ data <- k_random_uniform(shape = c(10000, 1), dtype = "int64")
396395hasher <- layer_hashing(num_bins = 64, salt = 1337)
397396
398397# Use the CategoryEncoding layer to multi-hot encode the hashed values
399- encoder <- layer_category_encoding(num_tokens=64, output_mode="multi_hot")
400- encoded_data <- encoder(hasher(data))
398+ encoder <- layer_category_encoding(num_tokens=64, output_mode="multi_hot")
399+ encoded_data <- encoder(hasher(data))
401400print(encoded_data$shape)
402401```
403402
@@ -425,7 +424,7 @@ text_vectorizer <- layer_text_vectorization(output_mode="int")
425424text_vectorizer %>% adapt(adapt_data)
426425
427426# Try out the layer
428- cat("Encoded text:\n",
427+ cat("Encoded text:\n",
429428 as.array(text_vectorizer("The Brain is deeper than the sea")))
430429
431430# Create a simple model
@@ -434,20 +433,20 @@ input = layer_input(shape(NULL), dtype="int64")
434433output <- input %>%
435434 layer_embedding(input_dim = text_vectorizer$vocabulary_size(),
436435 output_dim = 16) %>%
437- layer_gru(8) %>%
436+ layer_gru(8) %>%
438437 layer_dense(1)
439438
440439model <- keras_model(input, output)
441440
442441# Create a labeled dataset (which includes unknown tokens)
443442train_dataset <- tensor_slices_dataset(list(
444- c("The Brain is deeper than the sea", "for if they are held Blue to Blue"),
443+ c("The Brain is deeper than the sea", "for if they are held Blue to Blue"),
445444 c(1L, 0L)
446445))
447446
448447# Preprocess the string inputs, turning them into int sequences
449- train_dataset <- train_dataset %>%
450- dataset_batch(2) %>%
448+ train_dataset <- train_dataset %>%
449+ dataset_batch(2) %>%
451450 dataset_map(~list(text_vectorizer(.x), .y))
452451
453452# Train the model on the int sequences
@@ -458,8 +457,8 @@ model %>%
458457
459458# For inference, you can export a model that accepts strings as input
460459input <- layer_input(shape = 1, dtype="string")
461- output <- input %>%
462- text_vectorizer() %>%
460+ output <- input %>%
461+ text_vectorizer() %>%
463462 model()
464463
465464end_to_end_model <- keras_model(input, output)
@@ -514,26 +513,26 @@ model <- keras_model(input, output)
514513
515514# Create a labeled dataset (which includes unknown tokens)
516515train_dataset = tensor_slices_dataset(list(
517- c("The Brain is deeper than the sea", "for if they are held Blue to Blue"),
516+ c("The Brain is deeper than the sea", "for if they are held Blue to Blue"),
518517 c(1L, 0L)
519518))
520519
521520# Preprocess the string inputs, turning them into int sequences
522- train_dataset <- train_dataset %>%
523- dataset_batch(2) %>%
521+ train_dataset <- train_dataset %>%
522+ dataset_batch(2) %>%
524523 dataset_map(~list(text_vectorizer(.x), .y))
525524
526525# Train the model on the int sequences
527526cat("Training model...\n")
528- model %>%
529- compile(optimizer="rmsprop", loss="mse") %>%
527+ model %>%
528+ compile(optimizer="rmsprop", loss="mse") %>%
530529 fit(train_dataset)
531530
532531# For inference, you can export a model that accepts strings as input
533532input <- layer_input(shape = 1, dtype="string")
534533
535- output <- input %>%
536- text_vectorizer() %>%
534+ output <- input %>%
535+ text_vectorizer() %>%
537536 model()
538537
539538end_to_end_model = keras_model(input, output)
@@ -578,27 +577,27 @@ model <- keras_model(input, output)
578577
579578# Create a labeled dataset (which includes unknown tokens)
580579train_dataset = tensor_slices_dataset(list(
581- c("The Brain is deeper than the sea", "for if they are held Blue to Blue"),
580+ c("The Brain is deeper than the sea", "for if they are held Blue to Blue"),
582581 c(1L, 0L)
583582))
584583
585584# Preprocess the string inputs, turning them into int sequences
586- train_dataset <- train_dataset %>%
587- dataset_batch(2) %>%
585+ train_dataset <- train_dataset %>%
586+ dataset_batch(2) %>%
588587 dataset_map(~list(text_vectorizer(.x), .y))
589588
590589
591590# Train the model on the int sequences
592591cat("Training model...")
593- model %>%
594- compile(optimizer="rmsprop", loss="mse") %>%
592+ model %>%
593+ compile(optimizer="rmsprop", loss="mse") %>%
595594 fit(train_dataset)
596595
597596# For inference, you can export a model that accepts strings as input
598597input <- layer_input(shape = 1, dtype="string")
599598
600- output <- input %>%
601- text_vectorizer() %>%
599+ output <- input %>%
600+ text_vectorizer() %>%
602601 model()
603602
604603end_to_end_model = keras_model(input, output)
@@ -625,12 +624,3 @@ Instead, pre-compute your vocabulary in advance
625624(you could use Apache Beam or TF Transform for this)
626625and store it in a file. Then load the vocabulary into the layer at construction
627626time by passing the filepath as the ` vocabulary ` argument.
628-
629-
630- ### Using lookup layers on a TPU pod or with ` ParameterServerStrategy ` .
631-
632- There is an outstanding issue that causes performance to degrade when using a
633- ` layer_text_vectorization() ` , ` layer_string_lookup() ` , or
634- ` layer_integer_lookup() ` layer while training on a TPU pod or on multiple
635- machines via ` ParameterServerStrategy ` . This is slated to be fixed in TensorFlow
636- 2.7.
0 commit comments