Komponent inżynierii funkcji TensorFlow Extended (TFX)
Ten przykładowy notatnik colab stanowi bardzo prosty przykład tego, jak TensorFlow Transform ( tf.Transform
) może być używany do wstępnego przetwarzania danych przy użyciu dokładnie tego samego kodu zarówno do trenowania modelu, jak i obsługi wniosków w środowisku produkcyjnym.
TensorFlow Transform to biblioteka do wstępnego przetwarzania danych wejściowych dla TensorFlow, w tym tworzenia funkcji wymagających pełnego przejścia przez treningowy zestaw danych. Na przykład za pomocą TensorFlow Transform możesz:
- Normalizuj wartość wejściową, używając średniej i odchylenia standardowego
- Konwertuj łańcuchy na liczby całkowite, generując słownik dla wszystkich wartości wejściowych
- Konwertuj liczby zmiennoprzecinkowe na liczby całkowite, przypisując je do segmentów na podstawie obserwowanego rozkładu danych
TensorFlow ma wbudowaną obsługę manipulacji na pojedynczym przykładzie lub partii przykładów. tf.Transform
rozszerza te możliwości, aby obsługiwać pełne przebiegi całego zestawu danych treningowych.
Dane wyjściowe tf.Transform
są eksportowane jako wykres TensorFlow, którego można używać zarówno do trenowania, jak i obsługi. Używanie tego samego wykresu zarówno do trenowania, jak i obsługi może zapobiec przekrzywieniu, ponieważ te same przekształcenia są stosowane na obu etapach.
Ulepsz Pip
Aby uniknąć aktualizacji Pip w systemie uruchomionym lokalnie, upewnij się, że działamy w Colab. Systemy lokalne można oczywiście aktualizować oddzielnie.
try:
import colab
!pip install --upgrade pip
except:
pass
Zainstaluj TensorFlow Transform
pip install -q -U tensorflow_transform
Czy uruchomiłeś ponownie środowisko wykonawcze?
Jeśli używasz Google Colab, przy pierwszym uruchomieniu powyższej komórki musisz ponownie uruchomić środowisko wykonawcze (Runtime > Restart runtime ...). Wynika to ze sposobu, w jaki Colab ładuje paczki.
Import
import pprint
import tempfile
import tensorflow as tf
import tensorflow_transform as tft
import tensorflow_transform.beam as tft_beam
from tensorflow_transform.tf_metadata import dataset_metadata
from tensorflow_transform.tf_metadata import schema_utils
Dane: Utwórz fałszywe dane
Stworzymy kilka prostych fikcyjnych danych dla naszego prostego przykładu:
-
raw_data
to początkowe nieprzetworzone dane, które zamierzamy wstępnie przetworzyć -
raw_data_metadata
zawiera schemat, który informuje nas o typach każdej z kolumn wraw_data
. W tym przypadku sprawa jest bardzo prosta.
raw_data = [
{'x': 1, 'y': 1, 's': 'hello'},
{'x': 2, 'y': 2, 's': 'world'},
{'x': 3, 'y': 3, 's': 'hello'}
]
raw_data_metadata = dataset_metadata.DatasetMetadata(
schema_utils.schema_from_feature_spec({
'y': tf.io.FixedLenFeature([], tf.float32),
'x': tf.io.FixedLenFeature([], tf.float32),
's': tf.io.FixedLenFeature([], tf.string),
}))
Przekształć: Utwórz funkcję przetwarzania wstępnego
Funkcja przetwarzania wstępnego jest najważniejszą koncepcją tf.Transform. Funkcja przetwarzania wstępnego to miejsce, w którym naprawdę zachodzi transformacja zestawu danych. Przyjmuje i zwraca słownik tensorów, gdzie tensor oznacza Tensor
lubSparseTensor
. Istnieją dwie główne grupy wywołań API, które zazwyczaj tworzą serce funkcji przetwarzania wstępnego:
- TensorFlow Ops: Dowolna funkcja, która przyjmuje i zwraca tensory, co zwykle oznacza operacje TensorFlow. Dodają one operacje TensorFlow do wykresu, który przekształca nieprzetworzone dane w dane przekształcone po jednym wektorze cech naraz. Będą one działać na każdym przykładzie, zarówno podczas treningu, jak i podania.
- Analizatory/mapery transformacji tensorowej: Dowolne analizatory/mapery udostępniane przez tf.Transform. Akceptują one również i zwracają tensory i zazwyczaj zawierają kombinację operacji Tensorflow i obliczeń Beam, ale w przeciwieństwie do operacji TensorFlow działają one tylko w potoku Beam podczas analizy wymagającej pełnego przejścia przez cały zestaw danych treningowych. Obliczenie wiązki jest wykonywane tylko raz, podczas uczenia i zazwyczaj wykonuje pełny przebieg przez cały uczący zestaw danych. Tworzą one stałe tensorowe, które są dodawane do Twojego wykresu. Na przykład tft.min oblicza minimum tensora w uczącym zestawie danych, podczas gdy tft.scale_by_min_max najpierw oblicza min i maksimum tensora w uczącym zestawie danych, a następnie skaluje tensor tak, aby mieścił się w zakresie określonym przez użytkownika, [output_min, output_max]. tf.Transform zapewnia stały zestaw takich analizatorów/maperów, ale zostanie on rozszerzony w przyszłych wersjach.
def preprocessing_fn(inputs):
"""Preprocess input columns into transformed columns."""
x = inputs['x']
y = inputs['y']
s = inputs['s']
x_centered = x - tft.mean(x)
y_normalized = tft.scale_to_0_1(y)
s_integerized = tft.compute_and_apply_vocabulary(s)
x_centered_times_y_normalized = (x_centered * y_normalized)
return {
'x_centered': x_centered,
'y_normalized': y_normalized,
's_integerized': s_integerized,
'x_centered_times_y_normalized': x_centered_times_y_normalized,
}
Kładąc wszystko razem
Teraz jesteśmy gotowi do przekształcenia naszych danych. Użyjemy Apache Beam z bezpośrednim runnerem i dostarczymy trzy dane wejściowe:
-
raw_data
- surowe dane wejściowe, które stworzyliśmy powyżej -
raw_data_metadata
- Schemat surowych danych -
preprocessing_fn
- Funkcja, którą stworzyliśmy, aby wykonać naszą transformację
def main():
# Ignore the warnings
with tft_beam.Context(temp_dir=tempfile.mkdtemp()):
transformed_dataset, transform_fn = ( # pylint: disable=unused-variable
(raw_data, raw_data_metadata) | tft_beam.AnalyzeAndTransformDataset(
preprocessing_fn))
transformed_data, transformed_metadata = transformed_dataset # pylint: disable=unused-variable
print('\nRaw data:\n{}\n'.format(pprint.pformat(raw_data)))
print('Transformed data:\n{}'.format(pprint.pformat(transformed_data)))
if __name__ == '__main__':
main()
WARNING:apache_beam.runners.interactive.interactive_environment:Dependencies required for Interactive Beam PCollection visualization are not available, please use: `pip install apache-beam[interactive]` to install necessary dependencies to enable all data visualization features. WARNING:tensorflow:You are passing instance dicts and DatasetMetadata to TFT which will not provide optimal performance. Consider following the TFT guide to upgrade to the TFXIO format (Apache Arrow RecordBatch). WARNING:tensorflow:You are passing instance dicts and DatasetMetadata to TFT which will not provide optimal performance. Consider following the TFT guide to upgrade to the TFXIO format (Apache Arrow RecordBatch). WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_transform/tf_utils.py:289: Tensor.experimental_ref (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version. Instructions for updating: Use ref() instead. WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow_transform/tf_utils.py:289: Tensor.experimental_ref (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version. Instructions for updating: Use ref() instead. WARNING:tensorflow:You are passing instance dicts and DatasetMetadata to TFT which will not provide optimal performance. Consider following the TFT guide to upgrade to the TFXIO format (Apache Arrow RecordBatch). WARNING:tensorflow:You are passing instance dicts and DatasetMetadata to TFT which will not provide optimal performance. Consider following the TFT guide to upgrade to the TFXIO format (Apache Arrow RecordBatch). WARNING:apache_beam.options.pipeline_options:Discarding unparseable args: ['/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/ipykernel_launcher.py', '-f', '/tmp/tmp8aif_7w8.json', '--HistoryManager.hist_file=:memory:'] WARNING:root:Make sure that locally built Python SDK docker image has Python 3.7 interpreter. INFO:tensorflow:Assets written to: /tmp/tmpfvgb9_2h/tftransform_tmp/319450c9d7da4ab08741bc79e129ac38/assets 2022-02-03 10:18:41.378629: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them. INFO:tensorflow:Assets written to: /tmp/tmpfvgb9_2h/tftransform_tmp/319450c9d7da4ab08741bc79e129ac38/assets INFO:tensorflow:tensorflow_text is not available. INFO:tensorflow:tensorflow_text is not available. INFO:tensorflow:tensorflow_decision_forests is not available. INFO:tensorflow:tensorflow_decision_forests is not available. INFO:tensorflow:struct2tensor is not available. INFO:tensorflow:struct2tensor is not available. INFO:tensorflow:Assets written to: /tmp/tmpfvgb9_2h/tftransform_tmp/1f79865adbdd4ede9a3768fcac29949c/assets INFO:tensorflow:Assets written to: /tmp/tmpfvgb9_2h/tftransform_tmp/1f79865adbdd4ede9a3768fcac29949c/assets INFO:tensorflow:tensorflow_text is not available. INFO:tensorflow:tensorflow_text is not available. INFO:tensorflow:tensorflow_decision_forests is not available. INFO:tensorflow:tensorflow_decision_forests is not available. INFO:tensorflow:struct2tensor is not available. INFO:tensorflow:struct2tensor is not available. Raw data: [{'s': 'hello', 'x': 1, 'y': 1}, {'s': 'world', 'x': 2, 'y': 2}, {'s': 'hello', 'x': 3, 'y': 3}] Transformed data: [{'s_integerized': 0, 'x_centered': -1.0, 'x_centered_times_y_normalized': -0.0, 'y_normalized': 0.0}, {'s_integerized': 1, 'x_centered': 0.0, 'x_centered_times_y_normalized': 0.0, 'y_normalized': 0.5}, {'s_integerized': 0, 'x_centered': 1.0, 'x_centered_times_y_normalized': 1.0, 'y_normalized': 1.0}]
Czy to właściwa odpowiedź?
Wcześniej używaliśmy do tego tf.Transform
:
x_centered = x - tft.mean(x)
y_normalized = tft.scale_to_0_1(y)
s_integerized = tft.compute_and_apply_vocabulary(s)
x_centered_times_y_normalized = (x_centered * y_normalized)
x_centered
Z wejściem [1, 2, 3]
średnia x wynosi 2 i odejmujemy ją od x, aby wyśrodkować nasze wartości x na 0. Zatem nasz wynik [-1.0, 0.0, 1.0]
jest poprawny.
y_znormalizowane
Chcieliśmy przeskalować nasze wartości y między 0 a 1. Nasze dane wejściowe to [1, 2, 3]
, więc nasz wynik [0.0, 0.5, 1.0]
jest poprawny.
s_zintegrowany
Chcieliśmy odwzorować nasze łańcuchy na indeksy w słowniku, a w naszym słowniku były tylko 2 słowa („hello” i „world”). Tak więc przy wprowadzeniu ["hello", "world", "hello"]
nasz wynik [0, 1, 0]
jest poprawny. Ponieważ słowo „cześć” występuje w tych danych najczęściej, będzie to pierwszy wpis w słowniku.
x_centered_times_y_normalized
Chcieliśmy stworzyć nową funkcję, krzyżując x_centered
i y_normalized
za pomocą mnożenia. Zauważ, że to mnoży wyniki, a nie oryginalne wartości, a nasz nowy wynik [-0.0, 0.0, 1.0]
jest poprawny.