Рубрики
Без рубрики

Уборки трубопроводов с Dataclasses

Фон зидный код облегчает жизнь всех. Код в проекте ML, вероятно, будет … помечен трубопроводом, DataEngineering, Python, Scikit.

Фон

Tidy Code облегчает все жизнь. Код в проекте ML, вероятно, будет прочитан много раз, поэтому облегчая наш рабочий процесс, чтобы понять, будет оценен позже всем в команде. Во время ML проектов нам нужно получить доступ к данным аналогичным образом (на протяжении всего нашего рабочего процесса) для обучения, проверки и прогнозирования нашей модели и данных. Прозрачный семантический для доступа к данным позволяет облегчить управление кодом между проектами. Кроме того, соглашения о именовании также очень полезны для того, чтобы иметь возможность понять и повторно использовать код оптимальным образом. Есть несколько инструментов, которые могут помочь в этой чистоте, такой как использование трубопроводов и данных о Dataclasses.

Mlengineer составляет 10% мл 90% инженера.

Трубопровод

Трубопровод – это мета Объект, который помогает управлять процессами в модели ML. Трубопроводы могут инкапсулировать отдельные процессы, которые впоследствии могут быть объединены вместе. Принуждение рабочего процесса, который будет реализован в пределах Объекты трубопроводов Может быть неприятности в начале (особенно преобразования между Pandas dataframe и np.ndarray ), но вниз, она гарантирует качество модели (Нет утечки данных, модульность и т. Д.). Вот Кевин Маркхэм 4 мин. видео Объясняя преимущества трубопроводов.

Dataclass.

Еще один полезный Python Object Сохранить наборы данных вдоль трубопровода Dataclasses. . Перед Python 3.7 вы можете использовать NamedTuple. Однако после Python 3.7 Dataclasses были введены, и теперь есть великий кандидат для хранения таких объектов данных. Использование Dataclasses позволяет получить доступ к консистенции различных наборов данных на протяжении всего трубопровода ML.

Трубопровод

Поскольку мы не анализируем ни один набор данных, этот блог пост является примером аванс трубопровод который включает в себя нестандартные части (нет стандартных Sklearn модули). Предполагая, что у нас есть задача классификации, и наши данные имеют числовые типы столбцов и категорических столбцов, трубопровод включает в себя:

  1. Предыдущая подготовка данных Preprocess на тип столбца
  2. Обрабатывать категорично столбцы, использующие VTREAT упаковка
  3. Запустите Catboost классификатор.

Мы можем построить наш трубопровод следующим образом:

y = df.pop("label")
X = df.copy(True)

num_pipe = Pipeline([("scaler",StanderdScaler()),
                     ("variance",VarianceThreshold()),
                     ])
preprocess_pipe = ColumnTransformer(
   remainder="passthrough",
   transformers=[("num_pipe", num_pipe, X.select_dtypes("number"))]
)                     

pipe = Pipeline([("preprocess_pipe", preprocess_pipe),
               ("vtreat", BinomiaOutcomeTreatmentPlan()),
])                 

В этом Псевдо код Наш трубопровод имеет некоторую предварительную обработку цифровым столбцам, за которым следует обработка категорических колонн с пакетом VTREAT (он пройдет через все не категорические и числовые столбцы).

Примечание

  1. С Catboost Не имеет метода преобразования, мы собираемся представить его позже.
  2. Использование VTREAT является примером возможности использования нестандартных модулей в классификации (предполагая, что они следуют Sklearn Paradigms)

Так что теперь время пришло нарезать наши данные …

Тест против поезда против действительного

Общий рабочий процесс при разработке модели ML является необходимостью разделения даты в Тест/поезд/Допустимые наборы данных Отказ

Источник: Shan-Hung Wu & Datalab, Национальный университет Цин Хуа

В ореховой оболочке разница между данными:

  1. Тест – отложить в сторону – не смотри до окончательной оценки модели
  2. Поезд – DataSet для обучения модели
  3. Valid – DataSet для проверки модели во время этапа тренировки (это может быть через перекрестную итерацию проверки, GridSearch и т. Д.)

Каждый набор данных будет иметь аналогичные атрибуты, которые нам нужно будет сохранить и получить доступ по всему рабочему процессу ML. Для предотвращения путаницы давайте создадим Dataclass Сохранить наборы данных структурированным способом.

# basic dataclass 
import numpy as np
from dataclasses import dataclass

@dataclass
class Split:
    X: np.ndarray = None
    y: np.array = None
    idx: np.array = None
    pred_class: np.array = None
    pred_proba: np.ndarray = None
    kwargs: Dict = None

    def __init__(self, name:str):
        self.name = name

Теперь мы можем создавать наборы наборах обучения и тестирования следующим образом:

train = Split(name='train')   
test = Split(name='test')  

Каждый Dataclass будет иметь следующее поля :

  1. Х – NDARRay NDARRay, хранящую все функции
  2. y – Numpy Array, хранящая классификацию маркировки
  3. IDX – индекс для хранения оригинальных индексов, полезных для ссылки на конец трубопроводной линии
  4. pred_class – Numpy Array, хранящая предсказанную классификацию
  5. pred_proba – NDARRAY NDARRAY для хранения вероятностей классификаций

Кроме того, мы будем хранить Имя Для Dataclass (в функции init Функция), чтобы легко ссылаться на него вдоль трубопровода.

Расщепление в действии

Существует несколько методов, которые можно использовать для разделения наборов данных. Когда данные дисбалансны, важно разделить данные со стратифицированным методом. В нашем случае мы решили использовать Streatifiedshufflesplit Однако в отличие от простого Train-Test Split Что возвращает сами наборы данных, StreatifiedshuffleSplit возвращает только индексы для каждой группы, поэтому нам понадобится функция помощника, чтобы получить функцию набора данных (наша функция HELPER – это приятно и минимально для использования наших Dataclasses ).

def get_split_from_idx(X, y, split1: Split, split2: Split):
    split1.X, split2.X = X.iloc[split1.idx], X.iloc[split2.idx]
    split1.y, split2.y = y.iloc[split1.idx], y.iloc[split2.idx]
    return split1, split2  

for fold_name, (train.idx, test.idx) in enumerate( StratifiedSplitValid(X, y, n_split=5, train_size=0.8) ):
    train, test = get_split_from_idx(X, y, train, test)  # a helper function

Трубопровод в действии

Теперь мы можем запустить первую часть нашего трубопровода

_train_X = pipe.fit_transform(train.X)  

Как только у нас есть fit_transform Наши данные (позволяющие VTREAT MAGY на работу), мы можем представить Catboost классификатор в наш трубопровод.

catboost_clf = CatBoostClassifier()

train_valid = Split(name="train_valid")
valid = Split(name="valid")
for fold_name, (train_valid.idx, valid.idx) in enumerate(StratifiedSplitValid(_train_X, train.y, n_split=10, train_size=0.9) ):
    train_valid, valid = get_split_from_idx(_train_X, train.y, train_valid, valid)

    pipe.steps.append(("catboost_clf",catboost_clf))

    pipe.fit(train_size.X, train_valid.y,
            catboost_clf__eval_set=[(valid.X, valid.y)],
    )

Обратите внимание на два следующих пункта:

  1. Использование Pipe.steps.append. Мы можем представить шаги в трубопровод, который не может быть изначально частью рабочего процесса.
  2. Добавление параметров в шаги в трубопроводе требуется использование двойного разъема для Вложенные параметры Отказ

Наконец мы можем получить некоторые результаты

test.pred_class = pipe.(test.X)  
test.pred_proba = pipe.pred_proba(test.X)[:,1]

Теперь, когда мы анализируем нашу модель, мы можем генерировать наши метрики (например, confusucy_matrix), путем легко ссылаться на соответствующий набор данных следующим образом:

from sklearn.metrics import confusion_matrix
conf_matrix_test = confusion_matrix(y_true=test.y, y_pred=test.pred_class )

Заключение

Этот блог пост описывает преимущества для использования трубопроводов и датчасов. Работа с DataClasses действительно не является мозгом, поскольку он очень прост и может быть легко включен в любую базу кода. Трубопроводы требуют больше усилий при интеграции их в код, но преимущества являются существенными и оно того стоит. Я надеюсь, что пример проиллюстрировал потенциал для такого использования и вдохновляет и поощряет вас попробовать.

Оригинал: “https://dev.to/sephib/tidying-up-pipelines-with-dataclasses-2bde”