Разработка конвейера для компиляции процессов с реализацией на Python
Table of Contents 1. Introduction 2. Pipeline 3. Pipeline with Grid Search 4. Pipeline with ColumnTransformer, GridSearchCV 5. Pipeline with Feature Selection
1. Введение
О подготовке набора данных для алгоритма, проектировании модели и настройке гиперпараметров алгоритма на усмотрение разработчика для обобщения модели и достижения оптимального значения точности упоминалось в предыдущих статьях. Как известно, в распоряжении разработчика есть альтернативные решения как для предварительной обработки модели, так и для предварительной обработки данных и настройки гиперпараметров алгоритма. Разработчик несет ответственность за применение наиболее подходящих комбинаций и поддержание оптимальности своего проекта с точки зрения как точности, так и обобщения. Эта статья включает в себя реализацию всех упомянутых операций и многое другое за один раз с помощью конвейера, предлагаемого sklearn. Все заголовки поддерживаются реализацией Python.
2. Трубопровод
В своей самой базовой форме конвейер должен реализовать указанные операции предварительной обработки данных и модель в наборе данных с помощью одной строки:
IN[1] iris=load_iris() iris_data =iris.data iris_target=iris.target IN[2] x_train,x_test,y_train,y_test = train_test_split(iris_data, iris_target,test_size=0.2, random_state=2021) pip_iris = Pipeline([("scaler", RobustScaler()),("lr",LogisticRegression())]) pip_iris.fit(x_train,y_train) iris_score=pip_iris.score(x_test,y_test) print(iris_score) OUT[2] 0.9333333333333333
Набор данных Iris был разделен знаком train_test_split
, как обычно, и RobustScaler()
был выбран в качестве метода масштабирования для набора данных, известного как числовой набор данных, а LogisticRegression была выбрана в качестве классификатора. Конвейер также содержит различные атрибуты, такие как .fit
, .score
, точно так же, как поиск по сетке. Набор данных Train был дополнен командой .fit
в созданном конвейере, а оценка была создана с помощью .score
.
3. Конвейер с поиском по сетке
Grid Search оценивал комбинации гиперпараметров в алгоритме или любую операцию с определенными гиперпараметрами, информируя пользователя о степени точности или лучших комбинациях гиперпараметров с различными атрибутами (для получения дополнительной информации нажмите здесь). Использование GridSearchCV с конвейером - очень эффективный способ устранения рабочей нагрузки и путаницы. Теперь давайте протестируем реализованный выше алгоритм логистической регрессии с различными комбинациями гиперпараметров:
IN[3] x_train,x_test,y_train,y_test = train_test_split(iris_data, iris_target,test_size=0.2, random_state=2021) pip_iris_gs = Pipeline([("scaler", RobustScaler()),("lr",LogisticRegression(solver='saga'))]) param_grids={'lr__C':[0.001,0.1,2,10], 'lr__penalty':['l1','l2']} gs=GridSearchCV(pip_iris_gs,param_grids) gs.fit(x_train,y_train) test_score = gs.score(x_test,y_test) print("test score:",test_score) print("best parameters: ",gs.best_params_) print("best score: ", gs.best_score_) OUT[3] test score: 0.9333333333333333 best parameters: {'lr__C': 2, 'lr__penalty': 'l1'} best score: 0.9583333333333334
В дополнение к вышесказанному, значения «C» и «штраф» определяются как param_grids
путем создания словаря пользователем. Позже конвейер, содержащий алгоритм и масштабирование, был добавлен в GridSearchCV в качестве средства оценки. Набор обучающих данных обучается с помощью .fit
command и оценивается с помощью .score
. Кроме того, была получена информация о модели, созданной с помощью различных атрибутов в GridSearchCV.
4. Конвейер с ColumnTransformer, GridSearchCV
До сих пор использовался только набор данных -iris dataset-, содержащий только числовые данные. Чтобы усложнить ситуацию, давайте воспользуемся набором данных игрушек, который содержит как числовые, так и категориальные данные, и применим:
- Нормализовать столбец «Доход» с помощью
MinMaxScaler()
- Кодировать категориальные столбцы с
OneHotEncoder()
- Сгруппируйте столбец «Возраст» с помощью группировки.
Во-первых, давайте быстро взглянем на набор данных:
IN[4] toy = pd.read_csv('toy_dataset.csv') toy_final=toy.drop(['Number'],axis=1) IN[5] toy_final.isna().sum() OUT[5] City 0 Gender 0 Age 0 Income 0 Illness 0 dtype: int64 IN[6] numeric_cols=toy.select_dtypes(include=np.number).columns print("numeric_cols:",numeric_cols) categorical_cols=toy.select_dtypes(exclude=np.number).columns print("categorical_cols:",categorical_cols) print("shape:",toy_final.shape) OUT[6] numeric_cols: Index(['Number', 'Age', 'Income'], dtype='object') categorical_cols: Index(['City', 'Gender', 'Illness'], dtype='object') shape: (150000, 5)
Теперь выполним указанные выше операции:
IN[7] bins = KBinsDiscretizer(n_bins=5, encode='onehot-dense', strategy='uniform') ct = ColumnTransformer([ ('normalization', MinMaxScaler(), ['Income']), ('binning', bins, ['Age']), ('categorical-to-numeric', OneHotEncoder(sparse=False, handle_unknown='ignore'), ['City','Gender']) ], remainder='drop') x_train, x_test, y_train, y_test = train_test_split(toy_final.drop('Illness', axis=1), toy_final.Illness, test_size=0.2, random_state=0) param_grid_lr=[{'lr__solver':['saga'],'lr__C':[0.1,1,10],'lr__penalty':['elasticnet','l1','l2']}, {'lr__solver':['lbfgs'],'lr__C':[0.1,1,10],'lr__penalty':['l2']}] IN[8] pipe_lr = Pipeline([ ('columntransform', ct), ('lr', LogisticRegression()), ]) gs_lr =GridSearchCV(pipe_lr,param_grid_lr,cv=5) gs_lr.fit(x_train,y_train) test_score_lr = gs_lr.score(x_test,y_test) print("test score:",test_score_lr) print("best parameters: ",gs_lr.best_params_) print("best score: ", gs_lr.best_score_) OUT[8] test score: 0.9198666666666667 best parameters: {'lr__C': 0.1, 'lr__penalty': 'l1', 'lr__solver': 'saga'} best score: 0.9188750000000001
Метод bins с KBinsDiscretizer()
, представленный в библиотеке sklearn, настроен на 5 групп и кодируется OneHotEncoder. Процессы предварительной обработки, которые будут применяться с ColumnTransformer()
, были собраны в одни руки. Это следующие операции:
-Нормализация для столбца "Доход",
-Дискретизация для столбца "Возраст",
-Кодирование с OneHotEncoder()
для категориальных столбцов
Затем набор данных был разделен на обучение и тестирование. Словарь (param_grids_lr
) был создан с выбранными гиперпараметрами для оценки комбинаций параметров. Применяемые методы предварительной обработки данных были собраны в одних руках с помощью ColumnTransformer (для получения дополнительной информации щелкните здесь), а алгоритм - LogisticRegression - был помещен в конвейер. Как и в приведенных выше примерах, модель завершается путем выбора значения перекрестной проверки 5 в GridSearchCV.
Словарь
param_grid_lr
создается как алгоритм + двойное подчеркивание + гиперпараметр.LogisticRegression()
определяется как lr, и мы знаем, что «C» - это гиперпараметр LogisticRegression, поэтому используется lr__C. Чтобы увидеть все доступные гиперпараметры, которые можно использовать, применяетсяlr.get_params().keys()
.
Теперь давайте попробуем модель, которую мы подготовили с помощью DecisionTreeClassifier()
:
IN[9] pipe_dt = Pipeline([ ('columntransform', ct), ('dt', DecisionTreeClassifier()), ]) param_grid_dt={'dt__max_depth':[2,3,4,5,6,7,8]} gs_dt =GridSearchCV(pipe_dt,param_grid_dt,cv=5) gs_dt.fit(x_train,y_train) test_score_dt = gs_dt.score(x_test,y_test) print("test score:",test_score_dt) print("best parameters: ",gs_dt.best_params_) print("best score: ", gs_dt.best_score_) OUT[9] test score: 0.9198333333333333 best parameters: {'dt__max_depth': 2} best score: 0.9188750000000001
Выбранные нами значения max_depth подходили одно за другим, и наиболее успешное из них было определено с помощью поиска по сетке.
5. Конвейер с выбором функций
Как упоминалось во введении, использование конвейера и GridSearchCV - очень эффективный способ оценивать комбинации гиперпараметров и легко их компилировать. Это очень полезно не только для предварительной обработки данных и алгоритмов, но также для очистки данных (SimpleImputer
), обработки функций (SelectKBest
, SelectPercentile
, подробнее нажмите здесь) и т. Д. Теперь давайте применим следующее к набору данных груди_cancer, содержащему 30 функций:
- Стандартизация к числовым значениям с StandardScaler()
- PolynomialFeatures()
в числовых значениях
- ANOVA с SelectPercentile()
- гиперпараметры логистической регрессии («C» и «штраф»)
- настроить Cross-Validation = 3
IN[10] cancer=load_breast_cancer() cancer_data =cancer.data cancer_target =cancer.target IN[11] anova = SelectPercentile() poly = PolynomialFeatures() lr=LogisticRegression(solver='saga') param_grid_cancer=dict(poly__degree=[2,3,4], anova__percentile=[20, 30, 40, 50], lr__C=[0.01,0.1,1,10], lr__penalty=['l1','l2'] ) pipe_cancer = Pipeline([ ('standardization',StandardScaler()), ('poly',poly), ('anova',anova), ('lr',lr) ]) gs_final = GridSearchCV(pipe_cancer,param_grid_cancer,cv=3,n_jobs=-1) x_train, x_test, y_train, y_test = train_test_split(cancer_data, cancer_target,test_size=0.2,random_state=2021) gs_final.fit(x_train,y_train) test_score_final = gs_final.score(x_test,y_test) print("test score:",test_score_final) print("best parameters: ",gs_final.best_params_) print("best score: ", gs_final.best_score_) OUT[11] test score: 0.9736842105263158 best parameters: {'anova__percentile': 20, 'lr__C': 0.1, 'lr__penalty': 'l1', 'poly__degree': 2} best score: 0.9626612059951203
Были определены комбинации гиперпараметров, которые будут проверяться с param_grid_cancer
:
степень = [2,3,4] для PolynomialFeatures()
процентиль = [20, 30, 40, 50] для SelectPercentile()
C = [0,01,0,1,1,10] для LogisticRegression()
штраф = [‘l1’, ’l2’] для LogisticRegression()
Все это было подключено к StandardScaler()
. Затем значение перекрестной проверки было установлено на 3 в GridSearchCV. Набор данных был разделен на train_test_split
и, как всегда, был дополнен .fit
. Если для параметра «процентиль» в SelectPercentile установлено значение 20%, значение «C» в LogisticRegression установлено на 0,1, параметр «штраф» в LogisticRegression имеет значение "L1", а значение "deg" в PolynomialFeatures равно 2, точность является наивысшей.
Конвейер полезен при оценке многих вещей, которые требуются при создании модели конвейера в совокупности из одного источника.
make_pipeline
можно использовать так же, как и конвейер.make_pipeline
автоматически создает необходимые имена для шагов, поэтому достаточно просто добавить процесс.