Узнайте, как использовать конвейеры в рабочем процессе машинного обучения scikit-learn
В большинстве проектов машинного обучения данные, с которыми вам нужно работать, вряд ли будут в идеальном формате для создания наиболее эффективной модели. Довольно часто необходимо выполнить ряд этапов преобразования, таких как кодирование категориальных переменных, масштабирование функций и нормализация. Scikit-learn имеет встроенные функции для большинства этих часто используемых преобразований в своем пакете предварительной обработки.
Однако в типичном рабочем процессе машинного обучения вам нужно будет применить все эти преобразования как минимум дважды. Один раз при обучении модели и снова на любых новых данных, которые вы хотите спрогнозировать. Конечно, вы можете написать функцию для их применения и повторного использования, но вам все равно нужно сначала запустить ее, а затем вызывать модель отдельно. Конвейеры Scikit-learn - это инструмент, упрощающий этот процесс. У них есть несколько ключевых преимуществ:
- Они упрощают чтение и понимание вашего рабочего процесса.
- Они обеспечивают выполнение и порядок шагов в вашем проекте.
- Это, в свою очередь, делает вашу работу более воспроизводимой.
В следующем посте я собираюсь использовать набор данных, взятый из практической задачи прогнозирования ссуд Analytics Vidhya, чтобы описать, как работают конвейеры и как их реализовать.
Трансформеры
Сначала я импортировал файлы поездов и тестов в блокнот jupyter. Я убрал столбец «Loan_ID», так как он не понадобится при обучении или прогнозировании. Я использовал функцию pandas dtypes, чтобы получить небольшую информацию о наборе данных.
import pandas as pd train = pd.read_csv('train.csv') test = pd.read_csv('test.csv') train = train.drop('Loan_ID', axis=1) train.dtypes
Я вижу, что у меня есть как категориальные, так и числовые переменные, поэтому, как минимум, мне придется применить одно преобразование горячего кодирования и какой-то масштабатор. Я собираюсь использовать конвейер scikit-learn для выполнения этих преобразований и в то же время применить метод подгонки.
Перед построением конвейера я разделяю обучающие данные на набор для обучения и тестирования, чтобы я мог проверить производительность модели.
X = train.drop('Loan_Status', axis=1) y = train['Loan_Status'] from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
Первым шагом в построении трубопровода является определение каждого типа трансформатора. Обычно здесь принято создавать трансформаторы для различных типов переменных. В приведенном ниже коде я создал числовой преобразователь, который применяет StandardScaler и включает SimpleImputer для заполнения любых недостающих значений. Это действительно хорошая функция в scikit-learn, у которой есть несколько опций для заполнения пропущенных значений. Я решил использовать медиану, но другой метод может повысить производительность. Преобразователь категорий также имеет SimpleImputer с другим методом заполнения и использует OneHotEncoder для преобразования значений категорий в целые числа.
from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler, OneHotEncoder numeric_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='median')), ('scaler', StandardScaler())]) categorical_transformer = Pipeline(steps=[ ('imputer', SimpleImputer(strategy='constant', fill_value='missing')), ('onehot', OneHotEncoder(handle_unknown='ignore'))])
Затем мы используем ColumnTransformer, чтобы применить преобразования к правильным столбцам в фрейме данных. Перед созданием этого я сохранил списки числовых и категориальных столбцов, используя метод pandas dtype.
numeric_features = train.select_dtypes(include=['int64', 'float64']).columns categorical_features = train.select_dtypes(include=['object']).drop(['Loan_Status'], axis=1).columns from sklearn.compose import ColumnTransformer preprocessor = ColumnTransformer( transformers=[ ('num', numeric_transformer, numeric_features), ('cat', categorical_transformer, categorical_features)])
Установка классификатора
Следующим шагом является создание конвейера, который объединяет препроцессор, созданный выше, с классификатором. В этом случае для начала я использовал простой RandomForestClassifier.
from sklearn.ensemble import RandomForestClassifier rf = Pipeline(steps=[('preprocessor', preprocessor), ('classifier', RandomForestClassifier())])
Затем вы можете просто вызвать метод fit для необработанных данных, и будут применены шаги предварительной обработки, за которыми следует обучение классификатора.
rf.fit(X_train, y_train)
Чтобы спрогнозировать новые данные, это так же просто, как вызвать метод прогнозирования, и будут применены шаги предварительной обработки, за которыми следует прогноз.
y_pred = rf.predict(X_test)
Выбор модели
В процессе выбора модели также можно использовать конвейер. Следующий пример кода проходит через ряд классификаторов scikit-learn, применяя преобразования и обучая модель.
from sklearn.metrics import accuracy_score, log_loss from sklearn.neighbors import KNeighborsClassifier from sklearn.svm import SVC, LinearSVC, NuSVC from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier, GradientBoostingClassifier from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis classifiers = [ KNeighborsClassifier(3), SVC(kernel="rbf", C=0.025, probability=True), NuSVC(probability=True), DecisionTreeClassifier(), RandomForestClassifier(), AdaBoostClassifier(), GradientBoostingClassifier() ] for classifier in classifiers: pipe = Pipeline(steps=[('preprocessor', preprocessor), ('classifier', classifier)]) pipe.fit(X_train, y_train) print(classifier) print("model score: %.3f" % pipe.score(X_test, y_test))
Конвейер также можно использовать в поиске по сетке, чтобы найти наиболее эффективные параметры. Для этого вам сначала необходимо создать сетку параметров для выбранной вами модели. Важно отметить, что вам нужно добавить имя, которое вы дали классификатору вашего конвейера, к каждому имени параметра. В моем коде выше я назвал этот «классификатор», поэтому я добавил classifier__ к каждому параметру. Затем я создал объект поиска по сетке, который включает исходный конвейер. Когда я затем вызываю fit, преобразования применяются к данным, прежде чем поиск по сетке с перекрестной проверкой будет выполнен по сетке параметров.
param_grid = { 'classifier__n_estimators': [200, 500], 'classifier__max_features': ['auto', 'sqrt', 'log2'], 'classifier__max_depth' : [4,5,6,7,8], 'classifier__criterion' :['gini', 'entropy']} from sklearn.model_selection import GridSearchCV CV = GridSearchCV(rf, param_grid, n_jobs= 1) CV.fit(X_train, y_train) print(CV.best_params_) print(CV.best_score_)
В настоящее время я довольно много работаю над проектами машинного обучения scikit-learn. Прежде чем я начал использовать конвейеры, я обнаружил, что, когда я вернусь к проекту, чтобы снова поработать над ним, даже через короткое время, у меня снова возникнут проблемы с отслеживанием рабочего процесса. Конвейеры действительно помогли мне собрать проекты, которые легко повторять и расширять. Я надеюсь, что это руководство поможет другим, кто хочет научиться их использовать.