В этом руководстве мы рассмотрим TensorFlow Extended (TFX). TFX был разработан Google как комплексная платформа для развертывания производственных конвейеров машинного обучения. Здесь мы увидим, как мы можем построить его с нуля. Мы рассмотрим различные встроенные компоненты, которые мы можем использовать и которые охватывают весь жизненный цикл машинного обучения. От исследований и разработок до обучения и развертывания.
Но сначала давайте начнем с некоторых основных понятий и терминологии, чтобы убедиться, что мы все на одной странице.
Я настоятельно рекомендую Конвейеры машинного обучения в Google Cloud курс облачной команды Google или Расширенные сценарии развертывания с TensorFlow DeepLearning.ai, чтобы улучшить свои навыки с помощью целостного курса.
Глоссарий TFX
Компоненты являются строительными блоками конвейера и выполняют всю работу. Компоненты могут быть использованы без изменений или могут быть заменены нашим собственным кодом.
Хранилище метаданных является единственным источником достоверной информации для всех компонентов. Он содержит 3 вещи в основном:
-
Артефакты и их свойства: это могут быть обученные модели, данные, метрики
-
Записи об исполнении компонентов и конвейеров
-
Метаданные о рабочем процессе (порядок компонентов, входы, выходы и т. д.)
Конвейер TFX — это переносимая реализация рабочего процесса машинного обучения, состоящая из экземпляров компонентов и входных параметров.
Оркестраторы — это системы, которые выполняют конвейеры TFX. По сути, это платформы для создания, планирования и мониторинга рабочих процессов. Обычно они представляют конвейер в виде направленного ациклического графа и следят за тем, чтобы каждое задание (или рабочий процесс) выполнялось в нужное время с правильным входом.
Примеры популярных оркестраторов, работающих с TFX: Воздушный поток Apache, Луч Апача, Трубопроводы Kubeflow
Основываясь на различных этапах жизненного цикла машинного обучения, TFX предоставляет набор различных компонентов со стандартной функциональностью. Эти компоненты могут быть переопределены. Например, мы можем захотеть расширить их функциональность. Их также можно заменить совершенно новыми. Однако в большинстве случаев встроенные компоненты помогут большинству из нас пройти долгий путь.
Давайте кратко рассмотрим их все, начиная с загрузки данных и заканчивая развертыванием. Обратите внимание, что мы не будем углубляться в код, потому что есть много новых библиотек и пакетов, с которыми большинство незнакомо.
Весь смысл в том, чтобы дать вам обзор TFX и его модулей и помочь вам понять, зачем нам нужны такие комплексные решения.
Прием данных
Первым этапом процесса разработки ML является загрузка данных. ExampleGen
компонент принимает данные в конвейер TFX, преобразовывая различные типы данных в tf.Record
или tf.Example
(оба поддерживаются TFX). Пример кода можно найти ниже:
from tfx.proto import example_gen_pb2
from tfx.components import ImportExampleGen
input_config = example_gen_pb2.Input(splits=(
example_gen_pb2.Input.Split(name='train', pattern='train/*'),
example_gen_pb2.Input.Split(name='eval', pattern='test/*')
))
example_gen = ImportExampleGen(
input_base=data_root, input_config=input_config)
ImportExampleGen
является особым типом ExampleGen
который получает путь к данным и конфигурацию того, как обрабатывать наши данные. В этом случае мы разделяем их на обучающие и тестовые наборы данных.
Валидация данных
Следующим шагом является изучение наших данных, их визуализация и проверка на наличие возможных неточностей и аномалий.
StatisticsGen
Компонент генерирует набор полезных статистических данных, описывающих наше распределение данных. Как видите, он получает вывод ExampleGen
from tfx.components import StatisticsGen
statistics_gen = StatisticsGen(examples=example_gen.outputs('examples'))
Проверка данных Tensorflow это встроенная библиотека TFX, которая, среди прочего, может помочь нам визуализировать статистику, созданную StatisticsGen
. Это использовано внутри к StatisticsGen
но также может использоваться как самостоятельный инструмент.
import tensorflow_data_validation as tfdv
tfdv.visualize_statistics(stats)
Эта же библиотека используется SchemaGen
, который сгенерировал примитивную схему для наших данных. Это, конечно, можно скорректировать на основе наших знаний в предметной области, но это достойная отправная точка.
from tfx.components import SchemaGen
schema_gen = SchemaGen( statistics=statistics_gen.outputs('statistics'), infer_feature_shape=True)
Схему и полученную статику теперь можно использовать для выполнения той или иной формы валидация данных который будет обнаруживать выбросы, аномалии и ошибки в нашем наборе данных.
from tfx.components import ExampleValidator
example_validator = ExampleValidator(
statistics=statistics_gen.outputs('statistics'),
schema=schema_gen.outputs('schema'))
Разработка функций
Одним из наиболее важных шагов в любом конвейере машинного обучения является разработка функций. По сути, мы предварительно обрабатываем наши данные, чтобы их можно было передать в нашу модель. TFX обеспечивает Transform
компонент и tensorflow_transform
библиотека, которая поможет нам с задачей. Шаг преобразования может быть выполнен следующим образом:
from tfx.components import Transform
transform = Transform(
examples=example_gen.outputs('examples'),
schema=schema_gen.outputs('schema'),
module_file=module_file)
Но это не вся история.
Нам нужно как-то определить нашу функциональность предварительной обработки. Вот где аргумент module_file
приходит. Самый обычный способ сделать это — иметь другой файл со всеми нашими преобразованиями. По сути, нам нужно реализовать preprocessing_fn
функция, которая является точкой входа для TFX.
Вот образец, который я позаимствовал из официальных примеров TFX:
def preprocessing_fn(inputs):
"""tf.transform's callback function for preprocessing inputs."""
outputs = {}
image_features = tf.map_fn(
lambda x: tf.io.decode_png(x(0), channels=3),
inputs(_IMAGE_KEY),
dtype=tf.uint8)
image_features = tf.cast(image_features, tf.float32)
image_features = tf.image.resize(image_features, (224, 224))
image_features = tf.keras.applications.mobilenet.preprocess_input(
image_features)
outputs(_transformed_name(_IMAGE_KEY)) = image_features
outputs(_transformed_name(_LABEL_KEY)) = inputs(_LABEL_KEY)
return outputs
Обычный код Tensorflow и Keras, как вы можете видеть.
Обучение модели
Обучение модели является жизненно важной частью процесса и, в отличие от того, что считают многие люди, не является одноразовой операцией.
Модели необходимо постоянно переобучать, чтобы они оставались актуальными и обеспечивали максимально возможную точность результатов.
from tfx.dsl.components.base import executor_spec
from tfx.proto import trainer_pb2
from tfx.components.trainer.executor import GenericExecutor
from tfx.components import Trainer
trainer = Trainer(
module_file=module_file,
custom_executor_spec=executor_spec.ExecutorClassSpec(GenericExecutor),
examples=transform.outputs('transformed_examples'),
transform_graph=transform.outputs('transform_graph'),
schema=schema_gen.outputs('schema'),
train_args=trainer_pb2.TrainArgs(num_steps=160),
eval_args=trainer_pb2.EvalArgs(num_steps=4),
custom_config={'labels_path': labels_path})
Как и прежде, логика обучения находится в отдельном файле модуля. На этот раз мы должны реализовать run_fn
функция, которая обычно определяет модель и цикл обучения. Снова заимствовано из официальных примеров и очищено от лишнего, вот пример:
import tensorflow_transform as tft
def run_fn(fn_args: FnArgs):
tf_transform_output = tft.TFTransformOutput(fn_args.transform_output)
train_dataset = _input_fn(
fn_args.train_files,
tf_transform_output,
is_train=True,
batch_size=_TRAIN_BATCH_SIZE)
eval_dataset = _input_fn(
fn_args.eval_files,
tf_transform_output,
is_train=False,
batch_size=_EVAL_BATCH_SIZE)
model, base_model = _build_keras_model()
model.compile(
loss='sparse_categorical_crossentropy',
optimizer=tf.keras.optimizers.RMSprop(lr=_FINETUNE_LEARNING_RATE),
metrics=('sparse_categorical_accuracy'))
model.summary(print_fn=absl.logging.info)
model.fit(
train_dataset,
epochs=_CLASSIFIER_EPOCHS,
steps_per_epoch=steps_per_epoch,
validation_data=eval_dataset,
validation_steps=fn_args.eval_steps,
callbacks=(tensorboard_callback))
Обратите внимание, что _build_keras_model
возвращает ваниль tf.keras.Sequential
модель, пока input_fn
возвращает пакетный набор обучающих примеров и меток.
Проверить официальное репозиторий git для полного кода. Также убедитесь, что с правильными обратными вызовами мы можем воспользоваться преимуществами Tensorfboard
визуализировать процесс обучения.
Проверка модели
Далее на очереди проверка модели. Как только мы обучим модель, мы должны оценить ее и проанализировать ее производительность, прежде чем запустить ее в производство. Анализ модели TensorFlow (TFMA) — это библиотека для этой конкретной вещи. Обратите внимание, что эта фактическая оценка модели уже произошла во время обучения.
Этот шаг предназначен для записи показателей оценки для будущих запусков и сравнения их с предыдущими моделями.
Таким образом, мы можем быть уверены, что наша текущая модель — лучшая из имеющихся на данный момент.
Я не буду вдаваться в подробности TFMA, но вот код для дальнейшего использования:
import tensorflow_model_analysis as tfma
eval_config = tfma.EvalConfig(
model_specs=(tfma.ModelSpec(label_key='label_xf', model_type='tf_lite')),
slicing_specs=(tfma.SlicingSpec()),
metrics_specs=(
tfma.MetricsSpec(metrics=(
tfma.MetricConfig(
class_name='SparseCategoricalAccuracy',
threshold=tfma.MetricThreshold(
value_threshold=tfma.GenericValueThreshold(
lower_bound={'value': 0.55}),
change_threshold=tfma.GenericChangeThreshold(
direction=tfma.MetricDirection.HIGHER_IS_BETTER,
absolute={'value': -1e-3})))
))
))
Важная часть заключается в том, где мы определяем Evaluator
компонент как часть нашего пайплайна
from tfx.components import Evaluator
evaluator = Evaluator(
examples=transform.outputs('transformed_examples'),
model=trainer.outputs('model'),
baseline_model=model_resolver.outputs('model'),
eval_config=eval_config)
Нажмите модель
После успешной проверки модели пришло время запустить модель в производство. Это работа Pusher
компонент, который обрабатывает все материалы для развертывания в зависимости от нашей среды.
from tfx.components import Pusher
pusher = Pusher(
model=trainer.outputs('model'),
model_blessing=evaluator.outputs('blessing'),
push_destination=pusher_pb2.PushDestination(
filesystem=pusher_pb2.PushDestination.Filesystem(
base_directory=serving_model_dir)))
Создайте конвейер TFX
Хорошо, мы определили ряд компонентов, которые содержат все, что нам нужно. Но как мы свяжем их вместе? Конвейеры TFX определяются с помощью pipeline
class, который получает среди прочего список компонентов.
from tfx.orchestration import metadata
from tfx.orchestration import pipeline
components = (
example_gen, statistics_gen, schema_gen, example_validator, transform,
trainer, model_resolver, evaluator, pusher
)
pipeline = pipeline.Pipeline(
pipeline_name=pipeline_name,
pipeline_root=pipeline_root,
components=components,
enable_cache=True)
Экземпляры компонентов создают артефакты в качестве выходных данных и обычно зависят от артефактов, создаваемых вышестоящими экземплярами компонентов в качестве входных данных. Порядок выполнения компонентов определяется прямым ациклическим графом (DAG) на основе зависимостей каждого артефакта. Вот типичный конвейер TFX:
Источник: Документы облачной платформы Google
Запустите конвейер TFX
Наконец, мы достигаем той части, где мы будем запускать конвейер. Как мы уже говорили, конвейеры выполняются оркестратором, который будет заниматься всем планированием заданий и сетью. Здесь я выбрал Apache Beam, используя BeamDagRunner
но те же принципы справедливы для Kubeflow или Airflow.
from tfx.orchestration.beam.beam_dag_runner import BeamDagRunner
if __name__ == '__main__':
BeamDagRunner().run( pipeline)
Также отмечу, что аналогичные команды можно выполнять из командной строки с помощью Интерфейс командной строки TFX.
Я уверен, само собой разумеется, что оркестраторы, такие как луч Apache, в 99% случаев использования будут работать на облачных ресурсах.
Это означает, что Beam будет запускать облачные экземпляры/воркеры и передавать данные через них. Это будет зависеть от среды и конвейера.
Типичные бегуны ниже Apache Beam включают Spark, Flink, Google Dataflow. С другой стороны, такие фреймворки, как Kubeflow, полагаются на Kubernetes. Таким образом, одна из важных задач инженеров MLOps — найти наилучшую среду для своих нужд.
Заключение
В последние годы большое внимание уделяется системам сквозного машинного обучения. MLOps становится все более и более актуальным по мере рождения множества различных стартапов и фреймворков. Прекрасным примером является TFX. Должен признать, что построение таких пайплайнов — непростая задача и требует глубокого погружения в тонкости TFX. Но я думаю, что это один из лучших инструментов в нашем арсенале на данный момент. Так что в следующий раз, когда вы захотите развернуть модель машинного обучения, возможно, стоит попробовать.
В качестве примечания, я должен снова предложить вам Конвейеры машинного обучения в Google Cloud курс облачной команды Google или Расширенные сценарии развертывания с TensorFlow от DeepLearning.ai.
* Раскрытие информации: обратите внимание, что некоторые из приведенных выше ссылок могут быть партнерскими ссылками, и мы без дополнительных затрат для вас получим комиссию, если вы решите совершить покупку после перехода по ссылке.