Komponen Pipa TFX ContohGen

Komponen TFX Pipeline ExampleGen menyerap data ke dalam pipeline TFX. Ini menggunakan file/layanan eksternal untuk menghasilkan Contoh yang akan dibaca oleh komponen TFX lainnya. Ini juga menyediakan partisi yang konsisten dan dapat dikonfigurasi, dan mengacak dataset untuk praktik terbaik ML.

  • Menggunakan: Data dari sumber data eksternal seperti CSV, TFRecord , Avro, Parket, dan BigQuery.
  • Memancarkan: tf.Example record, tf.SequenceExample record, atau format proto, bergantung pada format payload.

ContohGen dan Komponen Lainnya

ExampleGen menyediakan data ke komponen yang menggunakan library Validasi Data TensorFlow , seperti SchemaGen , StatisticsGen , dan Example Validator . Ini juga menyediakan data ke Transform , yang menggunakan library Transform TensorFlow , dan akhirnya ke target penerapan selama inferensi.

Sumber dan Format Data

Saat ini, instalasi standar TFX menyertakan komponen ExampleGen lengkap untuk sumber dan format data ini:

Eksekutor khusus juga tersedia yang memungkinkan pengembangan komponen ExampleGen untuk sumber dan format data ini:

Lihat contoh penggunaan dalam kode sumber dan diskusi ini untuk informasi lebih lanjut tentang cara menggunakan dan mengembangkan pelaksana kustom.

Selain itu, sumber dan format data ini tersedia sebagai contoh komponen kustom :

Menyerap format data yang didukung oleh Apache Beam

Apache Beam mendukung penyerapan data dari berbagai sumber dan format data , ( lihat di bawah ). Kemampuan ini dapat digunakan untuk membuat komponen ExampleGen kustom untuk TFX, yang ditunjukkan oleh beberapa komponen ExampleGen yang ada ( lihat di bawah ).

Cara menggunakan Komponen ExampleGen

Untuk sumber data yang didukung (saat ini, file CSV, file TFRecord dengan tf.Example , tf.SequenceExample dan format proto, serta hasil kueri BigQuery), komponen pipeline ExampleGen dapat digunakan secara langsung dalam penerapan dan memerlukan sedikit penyesuaian. Sebagai contoh:

example_gen = CsvExampleGen(input_base='data_root')

atau seperti di bawah ini untuk mengimpor TFRecord eksternal dengan tf.Example langsung:

example_gen = ImportExampleGen(input_base=path_to_tfrecord_dir)

Rentang, Versi dan Split

Rentang adalah pengelompokan contoh pelatihan. Jika data Anda disimpan pada sistem file, setiap Span dapat disimpan dalam direktori terpisah. Semantik Span tidak di-hardcode ke TFX; a Rentang mungkin terkait dengan hari data, satu jam data, atau pengelompokan lain apa pun yang berarti bagi tugas Anda.

Setiap Rentang dapat menampung beberapa Versi data. Sebagai contoh, jika Anda menghapus beberapa contoh dari Span untuk membersihkan data berkualitas buruk, ini dapat menghasilkan Versi baru dari Span tersebut. Secara default, komponen TFX beroperasi pada Versi terbaru dalam suatu Rentang.

Setiap Versi dalam Rentang selanjutnya dapat dibagi lagi menjadi beberapa Pemisahan. Kasus penggunaan yang paling umum untuk memisahkan Span adalah dengan membaginya menjadi data pelatihan dan evaluasi.

Rentang dan Perpecahan

Pemisahan input/output khusus

Untuk menyesuaikan rasio pemisahan train/eval yang akan dikeluarkan oleh ExampleGen, setel output_config untuk komponen ExampleGen. Sebagai contoh:

# Input has a single split 'input_dir/*'.
# Output 2 splits: train:eval=3:1.
output = proto.Output(
             split_config=example_gen_pb2.SplitConfig(splits=[
                 proto.SplitConfig.Split(name='train', hash_buckets=3),
                 proto.SplitConfig.Split(name='eval', hash_buckets=1)
             ]))
example_gen = CsvExampleGen(input_base=input_dir, output_config=output)

Perhatikan bagaimana hash_buckets ditetapkan dalam contoh ini.

Untuk sumber input yang telah dipisah, setel input_config untuk komponen ExampleGen:


# Input train split is 'input_dir/train/*', eval split is 'input_dir/eval/*'.
# Output splits are generated one-to-one mapping from input splits.
input = proto.Input(splits=[
                example_gen_pb2.Input.Split(name='train', pattern='train/*'),
                example_gen_pb2.Input.Split(name='eval', pattern='eval/*')
            ])
example_gen = CsvExampleGen(input_base=input_dir, input_config=input)

Untuk contoh gen berbasis file (misalnya CsvExampleGen dan ImportExampleGen), pattern adalah pola file relatif glob yang memetakan ke file input dengan direktori root yang diberikan oleh jalur basis input. Untuk gen contoh berbasis kueri (mis. BigQueryExampleGen, PrestoExampleGen), pattern adalah kueri SQL.

Secara default, seluruh direktori basis input diperlakukan sebagai pemisahan input tunggal, dan pemisahan output kereta dan evaluasi dihasilkan dengan rasio 2:1.

Silakan merujuk ke proto/example_gen.proto untuk konfigurasi split input dan output ExampleGen. Dan lihat panduan komponen hilir untuk memanfaatkan pemisahan kustom di hilir.

Metode Pemisahan

Saat menggunakan metode pemisahan hash_buckets , alih-alih seluruh catatan, seseorang dapat menggunakan fitur untuk mempartisi contoh. Jika ada fitur, ExampleGen akan menggunakan sidik jari fitur tersebut sebagai kunci partisi.

Fitur ini dapat digunakan untuk mempertahankan pemisahan yang stabil dengan sifat-sifat tertentu dari contoh: misalnya, pengguna akan selalu ditempatkan dalam pemisahan yang sama jika "user_id" dipilih sebagai nama fitur partisi.

Interpretasi tentang arti "fitur" dan cara mencocokkan "fitur" dengan nama yang ditentukan bergantung pada implementasi ExampleGen dan jenis contoh.

Untuk implementasi ExampleGen yang sudah jadi:

  • Jika menghasilkan tf.Example, maka "fitur" berarti entri di tf.Example.features.feature.
  • Jika menghasilkan tf.SequenceExample, maka "fitur" berarti entri di tf.SequenceExample.context.feature.
  • Hanya fitur int64 dan byte yang didukung.

Dalam kasus berikut, ExampleGen memunculkan kesalahan runtime:

  • Nama fitur yang ditentukan tidak ada dalam contoh.
  • Fitur kosong: tf.train.Feature() .
  • Jenis fitur yang tidak didukung, misalnya fitur float.

Untuk menampilkan pemisahan train/eval berdasarkan fitur dalam contoh, setel output_config untuk komponen ExampleGen. Sebagai contoh:

# Input has a single split 'input_dir/*'.
# Output 2 splits based on 'user_id' features: train:eval=3:1.
output = proto.Output(
             split_config=proto.SplitConfig(splits=[
                 proto.SplitConfig.Split(name='train', hash_buckets=3),
                 proto.SplitConfig.Split(name='eval', hash_buckets=1)
             ],
             partition_feature_name='user_id'))
example_gen = CsvExampleGen(input_base=input_dir, output_config=output)

Perhatikan bagaimana partition_feature_name diatur dalam contoh ini.

Menjangkau

Span dapat diambil dengan menggunakan spesifikasi '{SPAN}' dalam pola glob input :

  • Spesifikasi ini mencocokkan angka dan memetakan data ke dalam nomor SPAN yang relevan. Misalnya, 'data_{SPAN}-*.tfrecord' akan mengumpulkan file seperti 'data_12-a.tfrecord', 'date_12-b.tfrecord'.
  • Secara opsional, spesifikasi ini dapat ditentukan dengan lebar bilangan bulat saat dipetakan. Misalnya, 'data_{SPAN:2}.file' memetakan ke file seperti 'data_02.file' dan 'data_27.file' (sebagai input untuk Span-2 dan Span-27 masing-masing), tetapi tidak memetakan ke 'data_1. file' atau 'data_123.file'.
  • Ketika spesifikasi SPAN tidak ada, itu dianggap selalu Span '0'.
  • Jika SPAN ditentukan, pipeline akan memproses rentang terbaru, dan menyimpan nomor rentang dalam metadata.

Misalnya, mari kita asumsikan ada data input:

  • '/tmp/span-1/kereta/data'
  • '/tmp/span-1/eval/data'
  • '/tmp/span-2/kereta/data'
  • '/tmp/span-2/eval/data'

dan konfigurasi input ditampilkan seperti di bawah ini:

splits {
  name: 'train'
  pattern: 'span-{SPAN}/train/*'
}
splits {
  name: 'eval'
  pattern: 'span-{SPAN}/eval/*'
}

saat memicu pipa, itu akan memproses:

  • '/tmp/span-2/train/data' sebagai kereta split
  • '/tmp/span-2/eval/data' sebagai eval split

dengan nomor rentang sebagai '2'. Jika nanti '/tmp/span-3/...' sudah siap, cukup picu kembali pipeline dan itu akan mengambil span '3' untuk diproses. Di bawah ini menunjukkan contoh kode untuk menggunakan spesifikasi rentang:

input = proto.Input(splits=[
                proto.Input.Split(name='train',
                                            pattern='span-{SPAN}/train/*'),
                proto.Input.Split(name='eval',
                                            pattern='span-{SPAN}/eval/*')
            ])
example_gen = CsvExampleGen(input_base='/tmp', input_config=input)

Mengambil rentang tertentu dapat dilakukan dengan RangeConfig, yang dirinci di bawah ini.

Tanggal

Jika sumber data Anda diatur pada sistem file berdasarkan tanggal, TFX mendukung tanggal pemetaan langsung ke nomor rentang. Ada tiga spesifikasi untuk mewakili pemetaan dari tanggal hingga rentang: {YYYY}, {MM} dan {DD}:

  • Ketiga spesifikasi harus ada dalam pola glob input jika ada yang ditentukan:
  • Spesifikasi {SPAN} atau spesifikasi tanggal ini dapat ditentukan secara eksklusif.
  • Sebuah tanggal kalender dengan tahun dari YYYY, bulan dari MM, dan hari dari bulan dari DD dihitung, kemudian nomor rentang dihitung sebagai jumlah hari sejak zaman unix (yaitu 1970-01-01). Misalnya, 'log-{YYYY}{MM}{DD}.data' cocok dengan file 'log-19700101.data' dan menggunakannya sebagai input untuk Span-0, dan 'log-20170101.data' sebagai input untuk Rentang-17167.
  • Jika kumpulan spesifikasi tanggal ini ditentukan, pipeline akan memproses tanggal terbaru terbaru, dan menyimpan nomor rentang yang sesuai dalam metadata.

Sebagai contoh, mari kita asumsikan ada data input yang diatur berdasarkan tanggal kalender:

  • '/tmp/1970-01-02/kereta/data'
  • '/tmp/1970-01-02/eval/data'
  • '/tmp/1970-01-03/kereta/data'
  • '/tmp/1970-01-03/eval/data'

dan konfigurasi input ditampilkan seperti di bawah ini:

splits {
  name: 'train'
  pattern: '{YYYY}-{MM}-{DD}/train/*'
}
splits {
  name: 'eval'
  pattern: '{YYYY}-{MM}-{DD}/eval/*'
}

saat memicu pipa, itu akan memproses:

  • '/tmp/1970-01-03/train/data' sebagai kereta split
  • '/tmp/1970-01-03/eval/data' sebagai eval split

dengan nomor rentang sebagai '2'. Jika nanti '/tmp/1970-01-04/...' sudah siap, cukup picu jalur pipa lagi dan itu akan mengambil rentang '3' untuk diproses. Di bawah ini menunjukkan contoh kode untuk menggunakan spesifikasi tanggal:

input = proto.Input(splits=[
                proto.Input.Split(name='train',
                                            pattern='{YYYY}-{MM}-{DD}/train/*'),
                proto.Input.Split(name='eval',
                                            pattern='{YYYY}-{MM}-{DD}/eval/*')
            ])
example_gen = CsvExampleGen(input_base='/tmp', input_config=input)

Versi: kapan

Versi dapat diambil dengan menggunakan spesifikasi '{VERSION}' dalam pola glob input :

  • Spesifikasi ini mencocokkan angka dan memetakan data ke nomor VERSION yang relevan di bawah SPAN. Perhatikan bahwa spesifikasi Versi dapat digunakan dengan kombinasi Span atau Tanggal.
  • Spesifikasi ini juga dapat ditentukan secara opsional dengan lebar dengan cara yang sama seperti spesifikasi SPAN. misalnya 'span-{SPAN}/version-{VERSION:4}/data-*'.
  • Jika spesifikasi VERSION tidak ada, versi disetel ke Tidak Ada.
  • Jika SPAN dan VERSION keduanya ditentukan, pipeline akan memproses versi terbaru untuk rentang terbaru, dan menyimpan nomor versi dalam metadata.
  • Jika VERSION ditentukan, tetapi bukan SPAN (atau spesifikasi tanggal), kesalahan akan terjadi.

Misalnya, mari kita asumsikan ada data input:

  • '/tmp/span-1/ver-1/train/data'
  • '/tmp/span-1/ver-1/eval/data'
  • '/tmp/span-2/ver-1/train/data'
  • '/tmp/span-2/ver-1/eval/data'
  • '/tmp/span-2/ver-2/train/data'
  • '/tmp/span-2/ver-2/eval/data'

dan konfigurasi input ditampilkan seperti di bawah ini:

splits {
  name: 'train'
  pattern: 'span-{SPAN}/ver-{VERSION}/train/*'
}
splits {
  name: 'eval'
  pattern: 'span-{SPAN}/ver-{VERSION}/eval/*'
}

saat memicu pipa, itu akan memproses:

  • '/tmp/span-2/ver-2/train/data' sebagai kereta split
  • '/tmp/span-2/ver-2/eval/data' sebagai eval split

dengan nomor rentang sebagai '2' dan nomor versi sebagai '2'. Jika nanti '/tmp/span-2/ver-3/...' sudah siap, cukup picu kembali pipeline dan itu akan mengambil span '2' dan versi '3' untuk diproses. Di bawah ini menunjukkan contoh kode untuk menggunakan spesifikasi versi:

input = proto.Input(splits=[
                proto.Input.Split(name='train',
                                            pattern='span-{SPAN}/ver-{VERSION}/train/*'),
                proto.Input.Split(name='eval',
                                            pattern='span-{SPAN}/ver-{VERSION}/eval/*')
            ])
example_gen = CsvExampleGen(input_base='/tmp', input_config=input)

Konfigurasi Rentang

TFX mendukung pengambilan dan pemrosesan rentang tertentu dalam ExampleGen berbasis file menggunakan konfigurasi rentang, konfigurasi abstrak yang digunakan untuk menggambarkan rentang untuk entitas TFX yang berbeda. Untuk mengambil rentang tertentu, setel range_config untuk komponen ExampleGen berbasis file. Misalnya, mari kita asumsikan ada data input:

  • '/tmp/span-01/kereta/data'
  • '/tmp/span-01/eval/data'
  • '/tmp/span-02/kereta/data'
  • '/tmp/span-02/eval/data'

Untuk secara khusus mengambil dan memproses data dengan rentang '1', kami menetapkan konfigurasi rentang selain konfigurasi input. Perhatikan bahwa ExampleGen hanya mendukung rentang statis rentang tunggal (untuk menentukan pemrosesan rentang individu tertentu). Jadi, untuk StaticRange, start_span_number harus sama dengan end_span_number. Menggunakan rentang yang disediakan, dan informasi lebar bentang (jika disediakan) untuk bantalan nol, ExampleGen akan menggantikan spesifikasi SPAN dalam pola pemisahan yang disediakan dengan nomor bentang yang diinginkan. Contoh penggunaan ditunjukkan di bawah ini:

# In cases where files have zero-padding, the width modifier in SPAN spec is
# required so TFX can correctly substitute spec with zero-padded span number.
input = proto.Input(splits=[
                proto.Input.Split(name='train',
                                            pattern='span-{SPAN:2}/train/*'),
                proto.Input.Split(name='eval',
                                            pattern='span-{SPAN:2}/eval/*')
            ])
# Specify the span number to be processed here using StaticRange.
range = proto.RangeConfig(
                static_range=proto.StaticRange(
                        start_span_number=1, end_span_number=1)
            )

# After substitution, the train and eval split patterns will be
# 'input_dir/span-01/train/*' and 'input_dir/span-01/eval/*', respectively.
example_gen = CsvExampleGen(input_base=input_dir, input_config=input,
                            range_config=range)

Konfigurasi rentang juga dapat digunakan untuk memproses tanggal tertentu, jika spesifikasi tanggal digunakan sebagai ganti spesifikasi SPAN. Sebagai contoh, mari kita asumsikan ada data input yang diatur berdasarkan tanggal kalender:

  • '/tmp/1970-01-02/kereta/data'
  • '/tmp/1970-01-02/eval/data'
  • '/tmp/1970-01-03/kereta/data'
  • '/tmp/1970-01-03/eval/data'

Untuk secara khusus mengambil dan memproses data pada tanggal 2 Januari 1970, kami melakukan hal berikut:

from  tfx.components.example_gen import utils

input = proto.Input(splits=[
                proto.Input.Split(name='train',
                                            pattern='{YYYY}-{MM}-{DD}/train/*'),
                proto.Input.Split(name='eval',
                                            pattern='{YYYY}-{MM}-{DD}/eval/*')
            ])
# Specify date to be converted to span number to be processed using StaticRange.
span = utils.date_to_span_number(1970, 1, 2)
range = proto.RangeConfig(
                static_range=range_config_pb2.StaticRange(
                        start_span_number=span, end_span_number=span)
            )

# After substitution, the train and eval split patterns will be
# 'input_dir/1970-01-02/train/*' and 'input_dir/1970-01-02/eval/*',
# respectively.
example_gen = CsvExampleGen(input_base=input_dir, input_config=input,
                            range_config=range)

Contoh KhususGen

Jika komponen ExampleGen yang tersedia saat ini tidak sesuai dengan kebutuhan Anda, Anda dapat membuat ExampleGen kustom, yang memungkinkan Anda membaca dari sumber data yang berbeda atau dalam format data yang berbeda.

Contoh Berbasis File Kustomisasi Gen (Eksperimental)

Pertama, perluas BaseExampleGenExecutor dengan Beam PTransform kustom, yang menyediakan konversi dari pemisahan input train/eval ke contoh TF. Misalnya, pelaksana CsvExampleGen menyediakan konversi dari contoh CSV split input ke TF.

Kemudian, buat komponen dengan eksekutor di atas, seperti yang dilakukan pada komponen CsvExampleGen . Atau, berikan eksekutor khusus ke dalam komponen ExampleGen standar seperti yang ditunjukkan di bawah ini.

from tfx.components.base import executor_spec
from tfx.components.example_gen.csv_example_gen import executor

example_gen = FileBasedExampleGen(
    input_base=os.path.join(base_dir, 'data/simple'),
    custom_executor_spec=executor_spec.ExecutorClassSpec(executor.Executor))

Sekarang, kami juga mendukung membaca file Avro dan Parket menggunakan metode ini.

Format Data Tambahan

Apache Beam mendukung membaca sejumlah format data tambahan . melalui Beam I/O Transforms. Anda dapat membuat komponen ExampleGen kustom dengan memanfaatkan Transformasi I/O Beam menggunakan pola yang mirip dengan contoh Avro

  return (pipeline
          | 'ReadFromAvro' >> beam.io.ReadFromAvro(avro_pattern)
          | 'ToTFExample' >> beam.Map(utils.dict_to_example))

Pada saat penulisan ini, format dan sumber data yang saat ini didukung untuk Beam Python SDK meliputi:

  • Amazon S3
  • Apache Avro
  • Apache Hadoop
  • Apache Kafka
  • Parket Apache
  • Google Cloud BigQuery
  • Google Cloud BigTable
  • Google Cloud Datastore
  • Google Cloud Pub/Sub
  • Penyimpanan Google Cloud (GCS)
  • MongoDB

Periksa dokumen Beam untuk daftar terbaru.

Contoh Berbasis Kueri Kustomisasi Gen (Eksperimental)

Pertama, perluas BaseExampleGenExecutor dengan Beam PTransform kustom, yang membaca dari sumber data eksternal. Kemudian, buat komponen sederhana dengan memperluas QueryBasedExampleGen.

Ini mungkin atau mungkin tidak memerlukan konfigurasi koneksi tambahan. Misalnya, pelaksana BigQuery membaca menggunakan konektor beam.io default, yang mengabstraksi detail konfigurasi koneksi. Eksekutor Presto , memerlukan PTransform Beam kustom dan protobuf konfigurasi koneksi kustom sebagai input.

Jika konfigurasi koneksi diperlukan untuk komponen ExampleGen kustom, buat protobuf baru dan teruskan melalui custom_config, yang sekarang menjadi parameter eksekusi opsional. Di bawah ini adalah contoh cara menggunakan komponen yang dikonfigurasi.

from tfx.examples.custom_components.presto_example_gen.proto import presto_config_pb2
from tfx.examples.custom_components.presto_example_gen.presto_component.component import PrestoExampleGen

presto_config = presto_config_pb2.PrestoConnConfig(host='localhost', port=8080)
example_gen = PrestoExampleGen(presto_config, query='SELECT * FROM chicago_taxi_trips')

Contoh Komponen Hilir Gen

Konfigurasi pemisahan khusus didukung untuk komponen hilir.

StatistikGen

Perilaku default adalah melakukan pembuatan statistik untuk semua pemisahan.

Untuk mengecualikan pemisahan apa pun, setel exclude_splits untuk komponen StatisticsGen. Sebagai contoh:

# Exclude the 'eval' split.
statistics_gen = StatisticsGen(
             examples=example_gen.outputs['examples'],
             exclude_splits=['eval'])

SkemaGen

Perilaku default adalah menghasilkan skema berdasarkan semua pemisahan.

Untuk mengecualikan pemisahan apa pun, setel exception_splits untuk komponen exclude_splits . Sebagai contoh:

# Exclude the 'eval' split.
schema_gen = SchemaGen(
             statistics=statistics_gen.outputs['statistics'],
             exclude_splits=['eval'])

Contoh Validator

Perilaku default adalah untuk memvalidasi statistik dari semua pemisahan pada contoh input terhadap skema.

Untuk mengecualikan pemisahan apa pun, setel exception_splits untuk komponen exclude_splits . Sebagai contoh:

# Exclude the 'eval' split.
example_validator = ExampleValidator(
             statistics=statistics_gen.outputs['statistics'],
             schema=schema_gen.outputs['schema'],
             exclude_splits=['eval'])

Mengubah

Perilaku default adalah menganalisis dan menghasilkan metadata dari pemisahan 'melatih' dan mengubah semua pemisahan.

Untuk menentukan pemisahan analisis dan pemisahan transformasi, setel splits_config untuk komponen Transform. Sebagai contoh:

# Analyze the 'train' split and transform all splits.
transform = Transform(
      examples=example_gen.outputs['examples'],
      schema=schema_gen.outputs['schema'],
      module_file=_taxi_module_file,
      splits_config=proto.SplitsConfig(analyze=['train'],
                                               transform=['train', 'eval']))

Pelatih dan Tuner

Perilaku default adalah melatih pada pemisahan 'kereta' dan mengevaluasi pada pemisahan 'eval'.

Untuk menentukan pemisahan kereta dan mengevaluasi pemisahan, setel komponen train_args dan eval_args untuk Trainer. Sebagai contoh:

# Train on the 'train' split and evaluate on the 'eval' split.
Trainer = Trainer(
      module_file=_taxi_module_file,
      examples=transform.outputs['transformed_examples'],
      schema=schema_gen.outputs['schema'],
      transform_graph=transform.outputs['transform_graph'],
      train_args=proto.TrainArgs(splits=['train'], num_steps=10000),
      eval_args=proto.EvalArgs(splits=['eval'], num_steps=5000))

Penilai

Perilaku default adalah menyediakan metrik yang dihitung pada pemisahan 'eval'.

Untuk menghitung statistik evaluasi pada pemisahan khusus, setel example_splits untuk komponen Evaluator. Sebagai contoh:

# Compute metrics on the 'eval1' split and the 'eval2' split.
evaluator = Evaluator(
      examples=example_gen.outputs['examples'],
      model=trainer.outputs['model'],
      example_splits=['eval1', 'eval2'])

Detail selengkapnya tersedia di referensi API CsvExampleGen , referensi API FileBasedExampleGen , dan referensi API ImportExampleGen .