คำถามเกี่ยวกับ TFX? เข้าร่วมกับเราที่ Google I / O!

ส่วนประกอบของ Transform TFX Pipeline

คอมโพเนนต์ไปป์ไลน์ Transform TFX ดำเนินการวิศวกรรมคุณลักษณะบน tf ตัวอย่างที่ปล่อยออกมาจากคอมโพเนนต์ ExampleGen โดยใช้สคีมาข้อมูลที่สร้างโดยคอมโพเนนต์ SchemaGen และปล่อย SavedModel เมื่อเรียกใช้งาน SavedModel จะยอมรับ tf ตัวอย่างที่ปล่อยออกมาจากคอมโพเนนต์ ExampleGen และปล่อยข้อมูลคุณสมบัติที่ถูกแปลง

  • ใช้: tf ตัวอย่างจากคอมโพเนนต์ ExampleGen และสคีมาข้อมูลจากคอมโพเนนต์ SchemaGen
  • Emits: A SavedModel ไปยังคอมโพเนนต์ Trainer

การกำหนดค่าคอมโพเนนต์การแปลง

เมื่อเขียน preprocessing_fn ของคุณแล้วจำเป็นต้องกำหนดไว้ในโมดูล python ที่จัดเตรียมให้กับคอมโพเนนต์ Transform เป็นอินพุต โมดูลนี้จะถูกโหลดโดยการแปลงและฟังก์ชันที่ชื่อ preprocessing_fn จะถูกพบและใช้โดย Transform เพื่อสร้างไปป์ไลน์ก่อนการประมวลผล

transform = Transform(
    examples=example_gen.outputs['examples'],
    schema=schema_gen.outputs['schema'],
    module_file=os.path.abspath(_taxi_transform_module_file))

Transform และ TensorFlow Transform

Transform ใช้ประโยชน์อย่างกว้างขวางของ TensorFlow Transform สำหรับการดำเนินการวิศวกรรมคุณลักษณะบนชุดข้อมูลของคุณ TensorFlow Transform เป็นเครื่องมือที่ยอดเยี่ยมสำหรับการแปลงข้อมูลคุณสมบัติก่อนที่จะไปยังโมเดลของคุณและเป็นส่วนหนึ่งของกระบวนการฝึกอบรม การเปลี่ยนแปลงคุณสมบัติทั่วไป ได้แก่ :

  • การฝัง : การแปลงคุณลักษณะที่กระจัดกระจาย (เช่นรหัสจำนวนเต็มที่สร้างโดยคำศัพท์) เป็นคุณลักษณะที่หนาแน่นโดยการค้นหาการจับคู่ที่มีความหมายจากพื้นที่มิติสูงไปยังพื้นที่มิติต่ำ ดู หน่วย Embeddings ในหลักสูตร Machine-learning Crash สำหรับข้อมูลเบื้องต้นเกี่ยวกับการฝัง
  • การสร้างคำศัพท์ : การแปลงสตริงหรือคุณสมบัติที่ไม่ใช่ตัวเลขให้เป็นจำนวนเต็มโดยการสร้างคำศัพท์ที่จับคู่ค่าที่ไม่ซ้ำกันกับหมายเลข ID
  • Normalizing ค่า : การเปลี่ยนแปลงคุณสมบัติตัวเลขเพื่อให้ทั้งหมดอยู่ในช่วงที่ใกล้เคียงกัน
  • Bucketization : การแปลงคุณลักษณะที่มีมูลค่าต่อเนื่องเป็นคุณลักษณะที่แยกประเภทโดยการกำหนดค่าให้กับที่เก็บข้อมูลที่ไม่ต่อเนื่อง
  • การเพิ่มคุณสมบัติข้อความ : การสร้างคุณลักษณะจากข้อมูลดิบเช่นโทเค็น, n-g, เอนทิตี, ความเชื่อมั่น ฯลฯ เพื่อเพิ่มคุณค่าให้กับชุดคุณลักษณะ

TensorFlow Transform ให้การสนับสนุนสำหรับการเปลี่ยนแปลงเหล่านี้และประเภทอื่น ๆ อีกมากมาย:

  • สร้างคำศัพท์โดยอัตโนมัติจากข้อมูลล่าสุดของคุณ

  • ทำการแปลงข้อมูลของคุณโดยพลการก่อนที่จะส่งไปยังโมเดลของคุณ TensorFlow Transform สร้างการเปลี่ยนแปลงเป็นกราฟ TensorFlow สำหรับโมเดลของคุณดังนั้นการแปลงแบบเดียวกันจะดำเนินการในเวลาฝึกอบรมและเวลาอนุมาน คุณสามารถกำหนดการแปลงที่อ้างถึงคุณสมบัติส่วนกลางของข้อมูลเช่นค่าสูงสุดของคุณลักษณะในอินสแตนซ์การฝึกอบรมทั้งหมด

คุณสามารถแปลงข้อมูลของคุณได้ตามต้องการก่อนที่จะเรียกใช้ TFX แต่ถ้าคุณทำภายใน TensorFlow Transform การแปลงจะกลายเป็นส่วนหนึ่งของกราฟ TensorFlow วิธีนี้ช่วยหลีกเลี่ยงการฝึก / เสิร์ฟเบ้

การแปลงภายในรหัสการสร้างแบบจำลองของคุณใช้ FeatureColumns การใช้ FeatureColumns คุณสามารถกำหนดที่เก็บข้อมูลจำนวนเต็มที่ใช้คำศัพท์ที่กำหนดไว้ล่วงหน้าหรือการเปลี่ยนแปลงอื่น ๆ ที่สามารถกำหนดได้โดยไม่ต้องดูข้อมูล

ในทางตรงกันข้าม TensorFlow Transform ได้รับการออกแบบมาสำหรับการแปลงที่ต้องการการส่งผ่านข้อมูลทั้งหมดเพื่อคำนวณค่าที่ไม่ทราบล่วงหน้า ตัวอย่างเช่นการสร้างคำศัพท์ต้องมีการส่งผ่านข้อมูลอย่างสมบูรณ์

นอกเหนือจากการคำนวณค่าโดยใช้ Apache Beam แล้ว TensorFlow Transform ยังช่วยให้ผู้ใช้สามารถฝังค่าเหล่านี้ลงในกราฟ TensorFlow ซึ่งสามารถโหลดลงในกราฟการฝึกอบรมได้ ตัวอย่างเช่นเมื่อทำให้คุณสมบัติเป็น tft.scale_to_z_score ฟังก์ชัน tft.scale_to_z_score จะคำนวณค่าเฉลี่ยและส่วนเบี่ยงเบนมาตรฐานของคุณลักษณะและการแทนค่าในกราฟ TensorFlow ของฟังก์ชันที่ลบค่าเฉลี่ยและหารด้วยค่าเบี่ยงเบนมาตรฐาน ด้วยการแสดงกราฟ TensorFlow ไม่ใช่แค่สถิติ TensorFlow Transform ช่วยลดความยุ่งยากในกระบวนการเขียนไปป์ไลน์ก่อนการประมวลผลของคุณ

เนื่องจากการประมวลผลล่วงหน้าแสดงเป็นกราฟจึงสามารถเกิดขึ้นได้บนเซิร์ฟเวอร์และรับประกันว่าจะสอดคล้องกันระหว่างการฝึกอบรมและการเสิร์ฟ ความสม่ำเสมอนี้จะกำจัดแหล่งฝึก / เสิร์ฟที่เบ้ออกไป

TensorFlow Transform ช่วยให้ผู้ใช้ระบุไปป์ไลน์ก่อนการประมวลผลโดยใช้รหัส TensorFlow ซึ่งหมายความว่าไปป์ไลน์ถูกสร้างขึ้นในลักษณะเดียวกับกราฟ TensorFlow หากใช้เฉพาะ TensorFlow ops ในกราฟนี้ไปป์ไลน์จะเป็นแผนที่บริสุทธิ์ที่ยอมรับแบตช์ของอินพุตและส่งคืนชุดของเอาต์พุต ไปป์ไลน์ดังกล่าวจะเทียบเท่ากับการวางกราฟนี้ไว้ใน input_fn ของคุณเมื่อใช้ tf.Estimator API เพื่อระบุการดำเนินการแบบเต็มผ่านเช่นการคำนวณควอนไทล์ TensorFlow Transform มีฟังก์ชันพิเศษที่เรียกว่า analyzers ที่ปรากฏเหมือน TensorFlow ops แต่ในความเป็นจริงระบุการคำนวณที่เลื่อนออกไปซึ่งจะกระทำโดย Apache Beam และเอาต์พุตที่แทรกลงในกราฟเป็น คงที่ ในขณะที่ TensorFlow op ธรรมดาจะใช้แบตช์เดียวเป็นอินพุตให้ทำการคำนวณบางอย่างกับแบทช์นั้นและปล่อยแบทช์ออกมา analyzer จะทำการลดระดับโลก (ใช้งานใน Apache Beam) ในทุกแบตช์และส่งคืนผลลัพธ์

ด้วยการรวม TensorFlow ops ธรรมดาและเครื่องวิเคราะห์ TensorFlow Transform ผู้ใช้สามารถสร้างไปป์ไลน์ที่ซับซ้อนเพื่อประมวลผลข้อมูลล่วงหน้าได้ ตัวอย่างเช่นฟังก์ชัน tft.scale_to_z_score รับอินพุตเทนเซอร์และส่งคืนค่าเทนเซอร์ที่ปรับมาตรฐานให้มีค่าเฉลี่ย 0 และค่าความแปรปรวน 1 ทำได้โดยการเรียก mean และตัววิเคราะห์ var ภายใต้ประทุนซึ่งจะสร้างค่าคงที่ในกราฟได้อย่างมีประสิทธิภาพเท่ากับค่าเฉลี่ยและความแปรปรวนของเทนเซอร์อินพุต จากนั้นจะใช้ TensorFlow ops เพื่อลบค่าเฉลี่ยและหารด้วยส่วนเบี่ยงเบนมาตรฐาน

TensorFlow Transform preprocessing_fn

คอมโพเนนต์ TFX Transform ช่วยลดความยุ่งยากในการใช้ Transform โดยจัดการการเรียก API ที่เกี่ยวข้องกับการอ่านและเขียนข้อมูลและเขียนเอาต์พุตที่บันทึกไว้ลงในดิสก์ ในฐานะผู้ใช้ TFX คุณต้องกำหนดฟังก์ชันเดียวที่เรียกว่า preprocessing_fn ใน preprocessing_fn คุณกำหนดชุดของฟังก์ชันที่จัดการอินพุตตามคำสั่งของเทนเซอร์เพื่อสร้างคำสั่งเอาต์พุตของเทนเซอร์ คุณสามารถค้นหาฟังก์ชันตัวช่วยเช่น scale_to_0_1 และ compute_and_apply_vocabulary TensorFlow Transform API หรือใช้ฟังก์ชัน TensorFlow ตามที่แสดงด้านล่าง

def preprocessing_fn(inputs):
  """tf.transform's callback function for preprocessing inputs.

  Args:
    inputs: map from feature keys to raw not-yet-transformed features.

  Returns:
    Map from string feature key to transformed feature operations.
  """
  outputs = {}
  for key in _DENSE_FLOAT_FEATURE_KEYS:
    # Preserve this feature as a dense float, setting nan's to the mean.
    outputs[_transformed_name(key)] = transform.scale_to_z_score(
        _fill_in_missing(inputs[key]))

  for key in _VOCAB_FEATURE_KEYS:
    # Build a vocabulary for this feature.
    outputs[_transformed_name(
        key)] = transform.compute_and_apply_vocabulary(
            _fill_in_missing(inputs[key]),
            top_k=_VOCAB_SIZE,
            num_oov_buckets=_OOV_SIZE)

  for key in _BUCKET_FEATURE_KEYS:
    outputs[_transformed_name(key)] = transform.bucketize(
        _fill_in_missing(inputs[key]), _FEATURE_BUCKET_COUNT)

  for key in _CATEGORICAL_FEATURE_KEYS:
    outputs[_transformed_name(key)] = _fill_in_missing(inputs[key])

  # Was this passenger a big tipper?
  taxi_fare = _fill_in_missing(inputs[_FARE_KEY])
  tips = _fill_in_missing(inputs[_LABEL_KEY])
  outputs[_transformed_name(_LABEL_KEY)] = tf.where(
      tf.is_nan(taxi_fare),
      tf.cast(tf.zeros_like(taxi_fare), tf.int64),
      # Test if the tip was > 20% of the fare.
      tf.cast(
          tf.greater(tips, tf.multiply(taxi_fare, tf.constant(0.2))), tf.int64))

  return outputs

การทำความเข้าใจอินพุตไปยัง preprocessing_fn

preprocessing_fn อธิบายชุดของการดำเนินการบนเทนเซอร์ (นั่นคือ Tensor s หรือ SparseTensor s) ดังนั้นในการเขียน preprocessing_fn อย่างถูกต้องจำเป็นต้องเข้าใจว่าข้อมูลของคุณแสดงเป็นเทนเซอร์อย่างไร อินพุตไปยัง preprocessing_fn ถูกกำหนดโดยสคีมา โปรโตส Schema ประกอบด้วยรายการ Feature s และการแปลงจะแปลงสิ่งเหล่านี้เป็น "ข้อมูลจำเพาะคุณลักษณะ" (บางครั้งเรียกว่า "ข้อมูลจำเพาะในการแยกวิเคราะห์") ซึ่งเป็นคำสั่งที่มีคีย์เป็นชื่อคุณลักษณะและมีค่าเป็นค่า FixedLenFeature หรือ VarLenFeature ตัวเลือกที่ไม่ได้ใช้โดย TensorFlow Transform)

กฎสำหรับการอนุมานคุณลักษณะเฉพาะจากส Schema คือ

  • แต่ละ feature มีชุด shape จะส่งผลให้เกิด tf.FixedLenFeature มีรูปร่างและ default_value=None presence.min_fraction tf.FixedLenFeature ต้องเป็น 1 มิฉะนั้นข้อผิดพลาดจะเกิดขึ้นเนื่องจากเมื่อไม่มีค่าเริ่มต้น tf.FixedLenFeature ต้องการให้คุณลักษณะนี้มีอยู่เสมอ
  • feature แต่ละอย่างที่ไม่ได้ตั้งค่า shape จะส่งผลให้เกิด VarLenFeature
  • sparse_feature แต่ละ sparse_feature จะทำให้เกิด tf.SparseFeature ซึ่ง size และถูกจัด is_sorted จะถูกกำหนดโดย fixed_shape และ is_sorted ของข้อความ SparseFeature
  • คุณลักษณะที่ใช้เป็น index_feature หรือ value_feature ของ sparse_feature จะไม่มีรายการของตัวเองที่สร้างขึ้นในคุณลักษณะเฉพาะ
  • ความสอดคล้องระหว่างฟิลด์ type ของ feature (หรือคุณลักษณะค่าของโปรโต sparse_feature ) และประเภท dtype ของคุณลักษณะเฉพาะกำหนดโดยตารางต่อไปนี้:
type dtype
schema_pb2.INT tf.int64
schema_pb2.FLOAT tf.float32
schema_pb2.BYTES tf.string

การใช้ TensorFlow Transform เพื่อจัดการกับป้ายชื่อสตริง

โดยปกติแล้วเราต้องการใช้ TensorFlow Transform เพื่อสร้างคำศัพท์และใช้คำศัพท์นั้นเพื่อแปลงสตริงเป็นจำนวนเต็ม เมื่อทำตามเวิร์กโฟลว์นี้ input_fn สร้างในแบบจำลองจะส่งออกสตริงจำนวนเต็ม อย่างไรก็ตามเลเบลเป็นข้อยกเว้นเนื่องจากเพื่อให้โมเดลสามารถแม็พป้ายกำกับเอาต์พุต (จำนวนเต็ม) กลับไปยังสตริงได้โมเดลต้องใช้ input_fn เพื่อเอาต์พุตเลเบลสตริงพร้อมกับรายการค่าที่เป็นไปได้ของเลเบล เช่นถ้าป้ายกำกับเป็น cat และ dog เอาต์พุตของ input_fn ควรเป็นสตริงดิบเหล่านี้และต้องส่งคีย์ ["cat", "dog"] ไปยังตัวประมาณค่าเป็นพารามิเตอร์ (ดูรายละเอียดด้านล่าง)

ในการจัดการการแมปป้ายชื่อสตริงกับจำนวนเต็มคุณควรใช้ TensorFlow Transform เพื่อสร้างคำศัพท์ เราแสดงให้เห็นในข้อมูลโค้ดด้านล่าง:

def _preprocessing_fn(inputs):
  """Preprocess input features into transformed features."""

  ...


  education = inputs[features.RAW_LABEL_KEY]
  _ = tft.uniques(education, vocab_filename=features.RAW_LABEL_KEY)

  ...

ฟังก์ชันก่อนการประมวลผลด้านบนใช้คุณสมบัติอินพุตดิบ (ซึ่งจะถูกส่งคืนเป็นส่วนหนึ่งของเอาต์พุตของฟังก์ชันก่อนการประมวลผลด้วย) และเรียกใช้ tft.uniques ส่งผลให้มีการสร้างคำศัพท์เพื่อ education ที่สามารถเข้าถึงได้ในแบบจำลอง

ตัวอย่างนี้ยังแสดงวิธีการเปลี่ยนป้ายชื่อและสร้างคำศัพท์สำหรับป้ายกำกับที่แปลงแล้ว โดยเฉพาะอย่างยิ่งจะใช้การ education ฉลากดิบและแปลงป้ายกำกับ 5 อันดับแรกทั้งหมด (ตามความถี่) เป็น UNKNOWN โดยไม่ต้องแปลงป้ายกำกับเป็นจำนวนเต็ม

ในรหัสแบบจำลองลักษณนามต้องได้รับคำศัพท์ที่สร้างโดย tft.uniques เป็นอาร์กิวเมนต์ label_vocabulary ทำได้โดยการอ่านคำศัพท์นี้เป็นรายการที่มีฟังก์ชันตัวช่วยก่อน สิ่งนี้แสดงในตัวอย่างด้านล่าง โปรดทราบว่าโค้ดตัวอย่างจะใช้เลเบลที่แปลงแล้วที่กล่าวถึงข้างต้น แต่ที่นี่เราจะแสดงโค้ดสำหรับการใช้เลเบลดิบ

def create_estimator(pipeline_inputs, hparams):

  ...

  tf_transform_output = trainer_util.TFTransformOutput(
      pipeline_inputs.transform_dir)

  # vocabulary_by_name() returns a Python list.
  label_vocabulary = tf_transform_output.vocabulary_by_name(
      features.RAW_LABEL_KEY)

  return tf.contrib.learn.DNNLinearCombinedClassifier(
      ...
      n_classes=len(label_vocab),
      label_vocabulary=label_vocab,
      ...)