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

רכיב הנדסת התכונות של TensorFlow Extended (TFX)

מחברת Colab לדוגמה מספקת דוגמה פשוטה מאוד לאופן שבו ניתן להשתמש ב- TensorFlow Transform ( tf.Transform ) לעיבוד מוקדם של נתונים תוך שימוש בדיוק באותו קוד הן להכשרת מודל והן להגשת מסקנות בייצור.

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

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

ל- TensorFlow יש תמיכה מובנית למניפולציות על דוגמה אחת או אצווה של דוגמאות. tf.Transform מרחיב את היכולות הללו כדי לתמוך במעברים מלאים על כל מערך ההדרכה.

הפלט של tf.Transform מיוצא כגרף TensorFlow שבו אתה יכול להשתמש הן להדרכה והן להגשה. שימוש באותו גרף גם לאימון וגם להגשה יכול למנוע הטיה, שכן אותן טרנספורמציות מיושמות בשני השלבים.

שדרוג פיפ

כדי להימנע משדרוג Pip במערכת בעת הפעלה מקומית, בדוק כדי לוודא שאנו פועלים ב-Colab. ניתן כמובן לשדרג מערכות מקומיות בנפרד.

try:
  import colab
  !pip install --upgrade pip
except:
  pass

התקן את TensorFlow Transform

pip install -q -U tensorflow_transform

הפעלת מחדש את זמן הריצה?

אם אתה משתמש ב-Google Colab, בפעם הראשונה שאתה מפעיל את התא שלמעלה, עליך להפעיל מחדש את זמן הריצה (Runtime > Restart runtime...). זה בגלל האופן שבו קולאב טוען חבילות.

יבוא

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

נתונים: צור כמה נתוני דמה

ניצור כמה נתוני דמה פשוטים עבור הדוגמה הפשוטה שלנו:

  • raw_data הוא הנתונים הגולמיים הראשוניים שאנו הולכים לעבד מראש
  • raw_data_metadata מכיל את הסכימה שאומרת לנו את הסוגים של כל אחת מהעמודות ב- raw_data . במקרה הזה, זה מאוד פשוט.
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),
    }))

טרנספורמציה: צור פונקציית עיבוד מקדים

פונקציית העיבוד המקדים היא הרעיון החשוב ביותר של tf.Transform. פונקציית עיבוד מקדים היא המקום שבו באמת מתרחשת השינוי של מערך הנתונים. הוא מקבל ומחזיר מילון טנסורים, כאשר טנסור פירושו Tensor או טנסורSparseTensor . ישנן שתי קבוצות עיקריות של קריאות API המהוות בדרך כלל את הלב של פונקציית עיבוד מקדים:

  1. TensorFlow Ops: כל פונקציה שמקבלת ומחזירה טנסורים, שמשמעותה בדרך כלל TensorFlow ops. אלה מוסיפים פעולות TensorFlow לגרף שהופך נתונים גולמיים לנתונים שעברו טרנספורמציה וקטור תכונה אחד בכל פעם. אלה יפעלו עבור כל דוגמה, הן במהלך ההדרכה והן במהלך ההגשה.
  2. מנתחי/מפות טרנספורמציה של Tensorflow: כל אחד מהנתחים/מפות המסופקים על ידי tf.Transform. אלה גם מקבלים ומחזירים טנזורים, ובדרך כלל מכילים שילוב של Tensorflow ops ו-Beam computing, אבל בניגוד ל- TensorFlow ops, הם פועלים רק בצינור Beam במהלך ניתוח המצריך מעבר מלא על כל מערך האימון. חישוב ה-Beam פועל רק פעם אחת, במהלך האימון, ובדרך כלל מבצע מעבר מלא על כל מערך האימון. הם יוצרים קבועי טנזור, שמתווספים לגרף שלך. לדוגמה, tft.min מחשב את המינימום של טנזור על מערך האימון בעוד ש-tft.scale_by_min_max מחשב תחילה את המינימום והמקסימום של טנזור על מערך האימון ולאחר מכן משנה את הטנזור כך שיהיה בטווח שצוין על ידי המשתמש, [output_min, output_max]. tf.Transform מספק קבוצה קבועה של מנתחים/מפה כאלה, אך זה יורחב בגרסאות עתידיות.
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,
    }

מחברים את הכל ביחד

עכשיו אנחנו מוכנים לשנות את הנתונים שלנו. נשתמש ב-Apache Beam עם רץ ישיר, ונספק שלוש כניסות:

  1. raw_data - נתוני הקלט הגולמיים שיצרנו למעלה
  2. raw_data_metadata - הסכימה של הנתונים הגולמיים
  3. preprocessing_fn - הפונקציה שיצרנו כדי לבצע את השינוי שלנו
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}]

האם זו התשובה הנכונה?

בעבר, השתמשנו 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_מרוכז

עם קלט של [1, 2, 3] הממוצע של x הוא 2, ונחסיר אותו מ-x כדי למרכז את ערכי ה-x שלנו ב-0. אז התוצאה שלנו של [-1.0, 0.0, 1.0] נכונה.

y_נורמליזציה

רצינו לשנות את קנה המידה של ערכי ה-y שלנו בין 0 ל-1. הקלט שלנו היה [1, 2, 3] כך שהתוצאה שלנו של [0.0, 0.5, 1.0] נכונה.

s_integerized

רצינו למפות את המחרוזות שלנו לאינדקסים באוצר מילים, והיו רק 2 מילים באוצר המילים שלנו ("שלום" ו"עולם"). אז עם קלט של ["hello", "world", "hello"] התוצאה שלנו של [0, 1, 0] נכונה. מכיוון ש"שלום" מופיע בתדירות הגבוהה ביותר בנתונים אלה, זה יהיה הערך הראשון באוצר המילים.

x_centered_times_y_normalized

רצינו ליצור תכונה חדשה על ידי הצלבה של x_centered ו- y_normalized באמצעות כפל. שימו לב שזה מכפיל את התוצאות, לא את הערכים המקוריים, והתוצאה החדשה שלנו של [-0.0, 0.0, 1.0] נכונה.