Niestandardowe komponenty funkcji Pythona

Definicja komponentów oparta na funkcjach Pythona ułatwia tworzenie niestandardowych komponentów TFX, oszczędzając wysiłku związanego z definiowaniem klasy specyfikacji komponentu, klasy modułu wykonującego i klasy interfejsu komponentu. W tym stylu definicji komponentu piszesz funkcję opatrzoną adnotacjami dotyczącymi typów. Wskazówki dotyczące typów opisują artefakty wejściowe, artefakty wyjściowe i parametry komponentu.

Napisanie komponentu niestandardowego w tym stylu jest bardzo proste, jak w poniższym przykładzie.

class MyOutput(TypedDict):
  accuracy: float

@component
def MyValidationComponent(
    model: InputArtifact[Model],
    blessing: OutputArtifact[Model],
    accuracy_threshold: Parameter[int] = 10,
) -> MyOutput:
  '''My simple custom model validation component.'''

  accuracy = evaluate_model(model)
  if accuracy >= accuracy_threshold:
    write_output_blessing(blessing)

  return {
    'accuracy': accuracy
  }

W skrócie definiuje to niestandardowy komponent będący podklasą BaseComponent oraz jego klas Spec i Executor.

Jeśli chcesz zdefiniować podklasę BaseBeamComponent tak, abyś mógł użyć potoku wiązki ze współdzieloną konfiguracją TFX-pipeline, tj. beam_pipeline_args podczas kompilacji potoku ( przykład Chicago Taxi Pipeline ), możesz ustawić use_beam=True w dekoratorze i dodać inny BeamComponentParameter z wartością domyślną None w Twojej funkcji, jak w poniższym przykładzie:

@component(use_beam=True)
def MyDataProcessor(
    examples: InputArtifact[Example],
    processed_examples: OutputArtifact[Example],
    beam_pipeline: BeamComponentParameter[beam.Pipeline] = None,
    ) -> None:
  '''My simple custom model validation component.'''

  with beam_pipeline as p:
    # data pipeline definition with beam_pipeline begins
    ...
    # data pipeline definition with beam_pipeline ends

Jeśli nie masz doświadczenia z potokami TFX, dowiedz się więcej o podstawowych koncepcjach potoków TFX .

Wejścia, wyjścia i parametry

W TFX wejścia i wyjścia są śledzone jako obiekty artefaktów, które opisują lokalizację i właściwości metadanych powiązanych z danymi źródłowymi; informacje te są przechowywane w metadanych ML. Artefakty mogą opisywać złożone typy danych lub proste typy danych, takie jak: int, float, bytes lub ciągi znaków Unicode.

Parametr jest argumentem (int, float, bytes lub ciąg znaków Unicode) komponentu znanego w czasie konstruowania potoku. Parametry są przydatne do określania argumentów i hiperparametrów, takich jak liczba iteracji szkoleniowych, współczynnik porzucania i inna konfiguracja komponentu. Parametry są przechowywane jako właściwości wykonań komponentów podczas śledzenia w metadanych ML.

Definicja

Aby utworzyć niestandardowy komponent, napisz funkcję implementującą niestandardową logikę i udekoruj ją dekoratorem @component z modułu tfx.dsl.component.experimental.decorators . Aby zdefiniować schemat wejścia i wyjścia komponentu, dodaj adnotacje do argumentów funkcji i zwróć wartość, korzystając z adnotacji z modułu tfx.dsl.component.experimental.annotations :

  • Dla każdego wejściowego artefaktu zastosuj adnotację dotyczącą typu InputArtifact[ArtifactType] . Zastąp ArtifactType typem artefaktu, który jest podklasą tfx.types.Artifact . Te dane wejściowe mogą być argumentami opcjonalnymi.

  • Dla każdego artefaktu wyjściowego zastosuj adnotację dotyczącą typu OutputArtifact[ArtifactType] . Zastąp ArtifactType typem artefaktu, który jest podklasą tfx.types.Artifact . Artefakty wyjściowe komponentu należy przekazywać jako argumenty wejściowe funkcji, aby komponent mógł zapisywać dane wyjściowe w lokalizacji zarządzanej przez system i ustawiać odpowiednie właściwości metadanych artefaktów. Argument ten może być opcjonalny lub można go zdefiniować za pomocą wartości domyślnej.

  • Dla każdego parametru użyj adnotacji wskazówki dotyczącej typu Parameter[T] . Zamień T na typ parametru. Obecnie obsługujemy tylko prymitywne typy Pythona: bool , int , float , str lub bytes .

  • W przypadku rurociągu belki użyj adnotacji wskazówki dotyczącej typu BeamComponentParameter[beam.Pipeline] . Ustaw wartość domyślną na None . Wartość None zostanie zastąpiona przez utworzony potok belek utworzony przez _make_beam_pipeline() programu BaseBeamExecutor

  • Dla każdego prostego typu danych wejściowych ( int , float , str lub bytes ), które nie są znane w czasie konstruowania potoku, użyj podpowiedzi typu T Należy zauważyć, że w wersji TFX 0.22 nie można przekazywać konkretnych wartości w czasie budowy rurociągu dla tego typu danych wejściowych (zamiast tego użyj adnotacji Parameter , jak opisano w poprzedniej sekcji). Argument ten może być opcjonalny lub można go zdefiniować za pomocą wartości domyślnej. Jeśli Twój komponent ma proste dane wyjściowe ( int , float , str lub bytes ), możesz zwrócić te dane wyjściowe, używając adnotacji TypedDict jako typu zwracanego i zwracając odpowiedni obiekt dict.

W treści funkcji artefakty wejściowe i wyjściowe są przekazywane jako obiekty tfx.types.Artifact ; możesz sprawdzić jego .uri , aby uzyskać jego lokalizację zarządzaną przez system i odczytać/ustawić dowolne właściwości. Parametry wejściowe i proste dane wejściowe są przekazywane jako obiekty określonego typu. Dane wyjściowe prostego typu danych powinny być zwracane w formie słownika, gdzie klucze to odpowiednie nazwy wyników, a wartości to żądane wartości zwracane.

Gotowy komponent funkcyjny może wyglądać następująco:

from typing import TypedDict
import tfx.v1 as tfx
from tfx.dsl.component.experimental.decorators import component

class MyOutput(TypedDict):
  loss: float
  accuracy: float

@component
def MyTrainerComponent(
    training_data: tfx.dsl.components.InputArtifact[tfx.types.standard_artifacts.Examples],
    model: tfx.dsl.components.OutputArtifact[tfx.types.standard_artifacts.Model],
    dropout_hyperparameter: float,
    num_iterations: tfx.dsl.components.Parameter[int] = 10
) -> MyOutput:
  '''My simple trainer component.'''

  records = read_examples(training_data.uri)
  model_obj = train_model(records, num_iterations, dropout_hyperparameter)
  model_obj.write_to(model.uri)

  return {
    'loss': model_obj.loss,
    'accuracy': model_obj.accuracy
  }

# Example usage in a pipeline graph definition:
# ...
trainer = MyTrainerComponent(
    examples=example_gen.outputs['examples'],
    dropout_hyperparameter=other_component.outputs['dropout'],
    num_iterations=1000)
pusher = Pusher(model=trainer.outputs['model'])
# ...

W powyższym przykładzie zdefiniowano MyTrainerComponent jako komponent niestandardowy oparty na funkcjach języka Python. Ten komponent wykorzystuje examples artefakt jako dane wejściowe i generuje artefakt model jako swoje dane wyjściowe. Komponent używa pliku artifact_instance.uri do odczytu lub zapisu artefaktu w jego lokalizacji zarządzanej przez system. Komponent przyjmuje parametr wejściowy num_iterations i wartość prostego typu danych dropout_hyperparameter , a składnik wyprowadza metryki loss i accuracy jako wartości wyjściowe prostego typu danych. Artefakt model wyjściowego jest następnie używany przez komponent Pusher .