Использование методов fit_transform и transform
Функция score_dataset() возвращает среднюю абсолютную ошибку. Вопрос: Почему для данных обучения мы используем метод fit_transform() , а для тестовых данных просто transform() ? fit_transform() сначала вызывает метод fit потом transform , кого мы обучаем в этом случае? мы же просто создаем датафрейм.
Отслеживать
задан 13 мая 2020 в 15:30
573 6 6 серебряных знаков 19 19 бронзовых знаков
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Если вдруг этот вопрос ещё для кого-то актуален, хотел бы дополнить ответ уважаемого passant.
Вопрос: Почему для данных обучения мы используем метод fit_transform() , а для тестовых данных просто transform() ?
По-хорошему такой методики нужно придерживаться всегда. Обучение любых моделей, включая такие прострые штуки как скейлеры, импутеры, нужно проводить исключительно на тренировочных данных. Модель не должна видеть тестовой и валидационной части данных на этапе обучения. Даже если речь о заполнении пропусков или масштабировании. Любое нарушение этого правила рано или поздно закончится «утечкой данных», в результате чего модель будет показывать на тестовой/валидационной части данных результаты лучше, чем они есть на самом деле.
Ну и кроме того, как уже было упомянуто, даже скейлеры и импутеры обучаются. Скейлер может запомнить минимум и максимум значений каждой фичи, импутер может запомнить, например, медианы фич. Поэтому на тренировочных данных делаем fit_transform — одновременно и обучаемся и преобразуем тренировочные данные. А на тестовых/валидационных данных делаем уже только transform — преобразуем данные согласно ранее запомненным параметрам, полученным на тренировочной выборке.
6.3. Предварительная обработка данных ¶
Пакет sklearn.preprocessing обеспечивает несколько функций общей полезности и трансформаторные классы для изменения необработанных векторов характеристик в представление , которое является более подходящим для нисходящих потока оценок.
В целом алгоритмы обучения выигрывают от стандартизации набора данных. Если в наборе присутствуют какие-то выбросы, более подходящими являются надежные скейлеры или трансформаторы. Поведение различных средств масштабирования, преобразователей и нормализаторов в наборе данных, содержащем предельные выбросы, выделено в разделе «Сравнить влияние различных средств масштабирования на данные с выбросами» .
6.3.1. Стандартизация или удаление среднего и масштабирование дисперсии
Стандартизация наборов данных является общим требованием для многих оценщиков машинного обучения, реализованных в scikit-learn; они могут вести себя плохо, если отдельные функции не более или менее выглядят как стандартные нормально распределенные данные: гауссовские с нулевым средним и единичной дисперсией .
На практике мы часто игнорируем форму распределения и просто преобразуем данные для их центрирования, удаляя среднее значение каждой функции, а затем масштабируем ее, деля непостоянные характеристики на их стандартное отклонение.
Например, многие элементы, используемые в целевой функции алгоритма обучения (такие как ядро RBF машин опорных векторов или регуляризаторы l1 и l2 линейных моделей), предполагают, что все функции сосредоточены вокруг нуля и имеют дисперсию в том же порядке. Если характеристика имеет дисперсию, которая на порядки больше, чем у других, она может доминировать над целевой функцией и сделать оценщик неспособным правильно учиться на других функциях, как ожидалось.
Модуль preprocessing предоставляет StandardScaler вспомогательный класс, который является быстрым и простым способом , чтобы выполнить следующую операцию на массив-типа набора данных:
>>> from sklearn import preprocessing >>> import numpy as np >>> X_train = np.array([[ 1., -1., 2.], . [ 2., 0., 0.], . [ 0., 1., -1.]]) >>> scaler = preprocessing.StandardScaler().fit(X_train) >>> scaler StandardScaler() >>> scaler.mean_ array([1. . 0. . 0.33. ]) >>> scaler.scale_ array([0.81. 0.81. 1.24. ]) >>> X_scaled = scaler.transform(X_train) >>> X_scaled array([[ 0. . -1.22. 1.33. ], [ 1.22. 0. . -0.26. ], [-1.22. 1.22. -1.06. ]])
Масштабированные данные имеют нулевое среднее значение и единичную дисперсию:
>>> X_scaled.mean(axis=0) array([0., 0., 0.]) >>> X_scaled.std(axis=0) array([1., 1., 1.])
Этот класс реализует Transformer API для вычисления среднего и стандартного отклонения на обучающем наборе, чтобы иметь возможность позже повторно применить то же преобразование к набору тестирования. Таким образом, этот класс подходит для использования на ранних этапах Pipeline :
>>> from sklearn.datasets import make_classification >>> from sklearn.linear_model import LogisticRegression >>> from sklearn.model_selection import train_test_split >>> from sklearn.pipeline import make_pipeline >>> from sklearn.preprocessing import StandardScaler >>> X, y = make_classification(random_state=42) >>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42) >>> pipe = make_pipeline(StandardScaler(), LogisticRegression()) >>> pipe.fit(X_train, y_train) # apply scaling on training data Pipeline(steps=[('standardscaler', StandardScaler()), ('logisticregression', LogisticRegression())]) >>> pipe.score(X_test, y_test) # apply scaling on testing data, without leaking training data. 0.96
Можно отключить центрирование или масштабирование, передав with_mean=False или with_std=False в конструктор StandardScaler .
6.3.1.1. Масштабирование функций до диапазона
Альтернативная стандартизация — это масштабирование функций таким образом, чтобы они находились между заданным минимальным и максимальным значением, часто между нулем и единицей, или так, чтобы максимальное абсолютное значение каждой функции масштабировалось до размера единицы. Этого можно добиться с помощью MinMaxScaler или MaxAbsScaler соответственно.
Мотивация к использованию этого масштабирования включает устойчивость к очень небольшим стандартным отклонениям функций и сохранение нулевых записей в разреженных данных.
Вот пример масштабирования матрицы данных игрушки до диапазона [0, 1]:
>>> X_train = np.array([[ 1., -1., 2.], . [ 2., 0., 0.], . [ 0., 1., -1.]]) . >>> min_max_scaler = preprocessing.MinMaxScaler() >>> X_train_minmax = min_max_scaler.fit_transform(X_train) >>> X_train_minmax array([[0.5 , 0. , 1. ], [1. , 0.5 , 0.33333333], [0. , 1. , 0. ]])
Тот же экземпляр преобразователя затем можно применить к некоторым новым тестовым данным, невидимым во время вызова подгонки: будут применены те же операции масштабирования и сдвига, чтобы они согласовывались с преобразованием, выполняемым с данными поезда:
>>> X_test = np.array([[-3., -1., 4.]]) >>> X_test_minmax = min_max_scaler.transform(X_test) >>> X_test_minmax array([[-1.5 , 0. , 1.66666667]])
Можно проанализировать атрибуты масштабатора, чтобы узнать точную природу преобразования, полученного на обучающих данных:
>>> min_max_scaler.scale_ array([0.5 , 0.5 , 0.33. ]) >>> min_max_scaler.min_ array([0. , 0.5 , 0.33. ])
Если MinMaxScaler дано явное указание, полная формула будет иметь следующий вид : feature_range=(min, max)
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0)) X_scaled = X_std * (max - min) + min
MaxAbsScaler работает очень похожим образом, но масштабируется таким образом, что обучающие данные лежат в пределах диапазона [-1, 1], путем деления на наибольшее максимальное значение в каждой функции. Он предназначен для данных, которые уже сосредоточены на нуле или разреженных данных.
Вот как использовать данные игрушки из предыдущего примера с этим скейлером:
>>> X_train = np.array([[ 1., -1., 2.], . [ 2., 0., 0.], . [ 0., 1., -1.]]) . >>> max_abs_scaler = preprocessing.MaxAbsScaler() >>> X_train_maxabs = max_abs_scaler.fit_transform(X_train) >>> X_train_maxabs array([[ 0.5, -1. , 1. ], [ 1. , 0. , 0. ], [ 0. , 1. , -0.5]]) >>> X_test = np.array([[ -3., -1., 4.]]) >>> X_test_maxabs = max_abs_scaler.transform(X_test) >>> X_test_maxabs array([[-1.5, -1. , 2. ]]) >>> max_abs_scaler.scale_ array([2., 1., 2.])
6.3.1.2. Масштабирование разреженных данных
Центрирование разреженных данных разрушило бы структуру разреженности данных, и поэтому редко бывает разумным делом. Однако может иметь смысл масштабировать разреженные входные данные, особенно если функции находятся в разных масштабах.
MaxAbsScaler был специально разработан для масштабирования разреженных данных, и это рекомендуемый способ сделать это. Однако StandardScaler может принимать scipy.sparse матрицы в качестве входных данных, если with_mean=False явно передается в конструктор. В противном случае ValueError будет поднят a , поскольку тихое центрирование нарушит разреженность и часто приведет к сбою выполнения из-за непреднамеренного выделения чрезмерного количества памяти. RobustScaler не может быть приспособлен к разреженным входам, но вы можете использовать этот transform метод для разреженных входных данных.
Обратите внимание, что средства масштабирования принимают форматы сжатых разреженных строк и сжатых разреженных столбцов (см. scipy.sparse.csr_matrix и scipy.sparse.csc_matrix ). Любой другой разреженный ввод будет преобразован в представление сжатых разреженных строк . Чтобы избежать ненужных копий памяти, рекомендуется выбирать восходящее представление CSR или CSC.
Наконец, если ожидается, что центрированные данные будут достаточно маленькими, toarray еще один вариант — явное преобразование входных данных в массив с использованием метода разреженных матриц.
6.3.1.3. Масштабирование данных с помощью выбросов
Если ваши данные содержат много выбросов, масштабирование с использованием среднего значения и дисперсии данных, вероятно, не будет работать очень хорошо. В этих случаях вы можете использовать RobustScaler вместо него замену. Он использует более надежные оценки для центра и диапазона ваших данных.
Дальнейшее обсуждение важности центрирования и масштабирования данных доступно в этом FAQ: Следует ли нормализовать / стандартизировать / масштабировать данные?
Масштабирование против отбеливания
Иногда недостаточно центрировать и масштабировать элементы независимо, поскольку последующая модель может дополнительно сделать некоторые предположения о линейной независимости функций.
Чтобы решить эту проблему, вы можете использовать PCA с whiten=True для дальнейшего удаления линейной корреляции между функциями.
6.3.1.4. Центрирование ядерных матриц
Если у вас есть матрица ядра ядра $K$ который вычисляет скалярное произведение в пространстве функций, определяемом функцией $\phi$, a KernelCenterer может преобразовать матрицу ядра так, чтобы она содержала внутренние продукты в пространстве функций, определяемом $\phi$ с последующим удалением среднего в этом пространстве.
6.3.2. Нелинейное преобразование
Доступны два типа преобразований: квантильные преобразования и степенные преобразования. И квантильные, и степенные преобразования основаны на монотонных преобразованиях характеристик и, таким образом, сохраняют ранг значений по каждой характеристике.
Квантильные преобразования помещают все функции в одно и то же желаемое распределение на основе формулы $G^(F(X))$ где $F$ — кумулятивная функция распределения признака и $G^$ функция квантиля требуемого распределения выходного $G$. В этой формуле используются два следующих факта: (i) если $X$ случайная величина с непрерывной кумулятивной функцией распределения $F$ тогда $F(X)$ равномерно распределяется по [0,1]; (ii) еслиU — случайная величина с равномерным распределением на $[0,1]$ тогда $G^(U)$ имеет распространение $G$. Выполняя ранговое преобразование, квантильное преобразование сглаживает необычные распределения и меньше подвержено влиянию выбросов, чем методы масштабирования. Однако это искажает корреляции и расстояния внутри и между объектами.
Преобразования мощности — это семейство параметрических преобразований, цель которых — сопоставить данные из любого распределения как можно ближе к гауссовскому распределению.
6.3.2.1. Отображение в равномерное распределение
QuantileTransformer обеспечивает непараметрическое преобразование для отображения данных в равномерное распределение со значениями от 0 до 1:
>>> from sklearn.datasets import load_iris >>> from sklearn.model_selection import train_test_split >>> X, y = load_iris(return_X_y=True) >>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0) >>> quantile_transformer = preprocessing.QuantileTransformer(random_state=0) >>> X_train_trans = quantile_transformer.fit_transform(X_train) >>> X_test_trans = quantile_transformer.transform(X_test) >>> np.percentile(X_train[:, 0], [0, 25, 50, 75, 100]) array([ 4.3, 5.1, 5.8, 6.5, 7.9])
Эта особенность соответствует длине чашелистиков в см. После применения квантильного преобразования эти ориентиры близко подходят к ранее определенным процентилям:
>>> np.percentile(X_train_trans[:, 0], [0, 25, 50, 75, 100]) . array([ 0.00. , 0.24. 0.49. 0.73. 0.99. ])
Это можно подтвердить на независимом тестовом наборе с аналогичными замечаниями:
>>> np.percentile(X_test[:, 0], [0, 25, 50, 75, 100]) . array([ 4.4 , 5.125, 5.75 , 6.175, 7.3 ]) >>> np.percentile(X_test_trans[:, 0], [0, 25, 50, 75, 100]) . array([ 0.01. 0.25. 0.46. 0.60. , 0.94. ])
6.3.2.2. Отображение в гауссово распределение
Во многих сценариях моделирования желательна нормальность функций в наборе данных. Преобразования мощности — это семейство параметрических монотонных преобразований, которые нацелены на отображение данных из любого распределения как можно ближе к гауссовскому распределению, чтобы стабилизировать дисперсию и минимизировать асимметрию.
PowerTransformer в настоящее время предоставляет два таких преобразования мощности, преобразование Йео-Джонсона и преобразование Бокса-Кокса.
Преобразование Йео-Джонсона определяется следующим образом:

в то время как преобразование Бокса-Кокса задается следующим образом:

Бокс-Кокса можно применять только к строго положительным данным. В обоих методах преобразование параметризуется $\lampda$, который определяется путем оценки максимального правдоподобия. Вот пример использования Box-Cox для сопоставления выборок, взятых из логнормального распределения, в нормальное распределение:
>>> pt = preprocessing.PowerTransformer(method='box-cox', standardize=False) >>> X_lognormal = np.random.RandomState(616).lognormal(size=(3, 3)) >>> X_lognormal array([[1.28. 1.18. 0.84. ], [0.94. 1.60. 0.38. ], [1.35. 0.21. 1.09. ]]) >>> pt.fit_transform(X_lognormal) array([[ 0.49. 0.17. -0.15. ], [-0.05. 0.58. -0.57. ], [ 0.69. -0.84. 0.10. ]])
Хотя в приведенном выше примере standardize параметр установлен на False , PowerTransformer по умолчанию будет применяться нормализация с нулевым средним и единичной дисперсией к преобразованному результату.
Ниже приведены примеры Бокса-Кокса и Йео-Джонсона, примененные к различным распределениям вероятностей. Обратите внимание, что при применении к определенным распределениям степенные преобразования достигают результатов, очень похожих на гауссову, но с другими они неэффективны. Это подчеркивает важность визуализации данных до и после преобразования.

Также можно сопоставить данные с нормальным распределением, используя QuantileTransformer настройку output_distribution=’normal’ . Используя предыдущий пример с набором данных радужной оболочки:
>>> quantile_transformer = preprocessing.QuantileTransformer( . output_distribution='normal', random_state=0) >>> X_trans = quantile_transformer.fit_transform(X) >>> quantile_transformer.quantiles_ array([[4.3, 2. , 1. , 0.1], [4.4, 2.2, 1.1, 0.1], [4.4, 2.2, 1.2, 0.1], . [7.7, 4.1, 6.7, 2.5], [7.7, 4.2, 6.7, 2.5], [7.9, 4.4, 6.9, 2.5]])
Таким образом, медиана входа становится средним значением выхода с центром в 0. Нормальный выход обрезается так, чтобы минимум и максимум входа — соответствующие квантилям 1e-7 и 1 — 1e-7 соответственно — не становились бесконечными при преобразование.
6.3.3. Нормализация
Нормализация — это процесс масштабирования отдельных образцов до единичной нормы . Этот процесс может быть полезен, если вы планируете использовать квадратичную форму, такую как скалярное произведение или любое другое ядро, для количественной оценки подобия любой пары образцов.
Это предположение является основой модели векторного пространства, часто используемой в контекстах классификации и кластеризации текста.
Функция normalize обеспечивает быстрый и простой способ для выполнения этой операции на одном массиве, как набор данных, либо с помощью l1 , l2 или max нормы:
>>> X = [[ 1., -1., 2.], . [ 2., 0., 0.], . [ 0., 1., -1.]] >>> X_normalized = preprocessing.normalize(X, norm='l2') >>> X_normalized array([[ 0.40. -0.40. 0.81. ], [ 1. . 0. . 0. . ], [ 0. . 0.70. -0.70. ]])
preprocessing Модуль дополнительно содержит вспомогательный класс , Normalizer который реализует ту же самую операцию с использованием Transformer API (даже если fit метод бесполезен в этом случае: класс является лицом без этой операции , как трактует образцов независимо друг от друга).
Таким образом, этот класс подходит для использования на ранних этапах Pipeline :
>>> normalizer = preprocessing.Normalizer().fit(X) # fit does nothing >>> normalizer Normalizer()
Экземпляр нормализатора затем можно использовать в векторах выборки как любой преобразователь:
>>> normalizer.transform(X) array([[ 0.40. -0.40. 0.81. ], [ 1. . 0. . 0. . ], [ 0. . 0.70. -0.70. ]]) >>> normalizer.transform([[-1., 1., 0.]]) array([[-0.70. 0.70. 0. . ]])
Примечание. Нормализация L2 также известна как предварительная обработка пространственных знаков.
normalize и Normalizer принимать как плотные, похожие на массивы, так и разреженные матрицы из scipy.sparse в качестве входных данных .
Для разреженного ввода данные преобразуются в представление сжатых разреженных строк (см. Раздел «Ресурсы» scipy.sparse.csr_matrix ) перед подачей в эффективные подпрограммы Cython. Чтобы избежать ненужных копий памяти, рекомендуется выбирать представление CSR в восходящем направлении.
6.3.4. Кодирование категориальных признаков
Часто характеристики задаются не как непрерывные значения, а как категориальные. Например, человек может иметь функции [«male», «female»][«from Europe», «from US», «from Asia»], [«uses Firefox», «uses Chrome», «uses Safari», «uses Internet Explorer»]. Такие функции могут быть эффективно закодированы как целые числа, например [«male», «from US», «uses Internet Explorer»], может быть выражена как [0, 1, 3] в то время как [«female», «from Asia», «uses Chrome»] было бы [1, 2, 1] .
Чтобы преобразовать категориальные признаки в такие целочисленные коды, мы можем использовать расширение OrdinalEncoder . Этот оценщик преобразует каждую категориальную характеристику в одну новую характеристику целых чисел (от 0 до n_categories — 1):
>>> enc = preprocessing.OrdinalEncoder() >>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']] >>> enc.fit(X) OrdinalEncoder() >>> enc.transform([['female', 'from US', 'uses Safari']]) array([[0., 1., 1.]])
Такое целочисленное представление, однако, не может использоваться напрямую со всеми оценщиками scikit-learn, поскольку они ожидают непрерывного ввода и интерпретируют категории как упорядоченные, что часто нежелательно (т. Е. Набор браузеров был упорядочен произвольно).
Еще одна возможность преобразовать категориальные функции в функции, которые можно использовать с оценками scikit-learn, — это использовать кодировку «один из K», также известную как одноразовое или фиктивное кодирование. Этот тип кодирования может быть получен с помощью OneHotEncoder , который преобразует каждый категориальный признак с n_categories возможными значениями в n_categories двоичные признаки, один из которых равен 1, а все остальные 0.
Продолжая пример выше:
>>> enc = preprocessing.OneHotEncoder() >>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']] >>> enc.fit(X) OneHotEncoder() >>> enc.transform([['female', 'from US', 'uses Safari'], . ['male', 'from Europe', 'uses Safari']]).toarray() array([[1., 0., 0., 1., 0., 1.], [0., 1., 1., 0., 0., 1.]])
По умолчанию значения, которые может принимать каждый объект, автоматически выводятся из набора данных и могут быть найдены в categories_ атрибуте:
>>> enc.categories_ [array(['female', 'male'], dtype=object), array(['from Europe', 'from US'], dtype=object), array(['uses Firefox', 'uses Safari'], dtype=object)]
Это можно указать явно с помощью параметра categories . В нашем наборе данных есть два пола, четыре возможных континента и четыре веб-браузера:
>>> genders = ['female', 'male'] >>> locations = ['from Africa', 'from Asia', 'from Europe', 'from US'] >>> browsers = ['uses Chrome', 'uses Firefox', 'uses IE', 'uses Safari'] >>> enc = preprocessing.OneHotEncoder(categories=[genders, locations, browsers]) >>> # Note that for there are missing categorical values for the 2nd and 3rd >>> # feature >>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']] >>> enc.fit(X) OneHotEncoder(categories=[['female', 'male'], ['from Africa', 'from Asia', 'from Europe', 'from US'], ['uses Chrome', 'uses Firefox', 'uses IE', 'uses Safari']]) >>> enc.transform([['female', 'from Asia', 'uses Chrome']]).toarray() array([[1., 0., 0., 1., 0., 0., 1., 0., 0., 0.]])
Если есть вероятность, что в обучающих данных могут отсутствовать категориальные особенности, часто бывает лучше указать, handle_unknown=’ignore’ а не устанавливать categories вручную, как указано выше. Если handle_unknown=’ignore’ задано значение и во время преобразования встречаются неизвестные категории, ошибка не возникает, но в столбцах с горячим кодированием для этой функции будут все нули ( handle_unknown=’ignore’ поддерживается только для горячего кодирования):
>>> enc = preprocessing.OneHotEncoder(handle_unknown='ignore') >>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']] >>> enc.fit(X) OneHotEncoder(handle_unknown='ignore') >>> enc.transform([['female', 'from Asia', 'uses Chrome']]).toarray() array([[1., 0., 0., 0., 0., 0.]])
Также можно кодировать каждый столбец в столбцы n_categories — 1 вместо столбцов n_categories с помощью параметра drop. Этот параметр позволяет пользователю указать категорию для каждой удаляемой функции. Это полезно, чтобы избежать коллинеарности входной матрицы в некоторых классификаторах. Такая функциональность полезна, например, при использовании нерегуляризованной регрессии ( LinearRegression ), поскольку коллинеарность приведет к тому, что ковариационная матрица будет необратимой. Если этот параметр не равен None, handle_unknown необходимо установить значение error :
>>> X = [['male', 'from US', 'uses Safari'], . ['female', 'from Europe', 'uses Firefox']] >>> drop_enc = preprocessing.OneHotEncoder(drop='first').fit(X) >>> drop_enc.categories_ [array(['female', 'male'], dtype=object), array(['from Europe', 'from US'], dtype=object), array(['uses Firefox', 'uses Safari'], dtype=object)] >>> drop_enc.transform(X).toarray() array([[1., 1., 1.], [0., 0., 0.]])
Можно удалить один из двух столбцов только для функций с двумя категориями. В этом случае вы можете установить параметр drop=’if_binary’ .
>>> X = [['male', 'US', 'Safari'], . ['female', 'Europe', 'Firefox'], . ['female', 'Asia', 'Chrome']] >>> drop_enc = preprocessing.OneHotEncoder(drop='if_binary').fit(X) >>> drop_enc.categories_ [array(['female', 'male'], dtype=object), array(['Asia', 'Europe', 'US'], dtype=object), array(['Chrome', 'Firefox', 'Safari'], dtype=object)] >>> drop_enc.transform(X).toarray() array([[1., 0., 0., 1., 0., 0., 1.], [0., 0., 1., 0., 0., 1., 0.], [0., 1., 0., 0., 1., 0., 0.]])
В преобразованном виде $X$ первый столбец представляет собой кодирование признака с категориями «мужской» / «женский», а остальные 6 столбцов — это кодирование 2 признаков с соответственно 3 категориями в каждом.
OneHotEncoder поддерживает категориальные функции с пропущенными значениями, рассматривая отсутствующие значения как дополнительную категорию:
>>> X = [['male', 'Safari'], . ['female', None], . [np.nan, 'Firefox']] >>> enc = preprocessing.OneHotEncoder(handle_unknown='error').fit(X) >>> enc.categories_ [array(['female', 'male', nan], dtype=object), array(['Firefox', 'Safari', None], dtype=object)] >>> enc.transform(X).toarray() array([[0., 1., 0., 0., 1., 0.], [1., 0., 0., 0., 0., 1.], [0., 0., 1., 1., 0., 0.]])
Если функция содержит оба np.nan и None , они будут считаться отдельными категориями:
>>> X = [['Safari'], [None], [np.nan], ['Firefox']] >>> enc = preprocessing.OneHotEncoder(handle_unknown='error').fit(X) >>> enc.categories_ [array(['Firefox', 'Safari', None, nan], dtype=object)] >>> enc.transform(X).toarray() array([[0., 1., 0., 0.], [0., 0., 1., 0.], [0., 0., 0., 1.], [1., 0., 0., 0.]])
См. Раздел Загрузка функций из dicts, чтобы узнать о категориальных функциях, которые представлены как dict, а не как скаляры.
6.3.5. Дискретность
Дискретизация (также известная как квантование или биннинг) обеспечивает способ разделения непрерывных функций на дискретные значения. Определенные наборы данных с непрерывными объектами могут выиграть от дискретизации, потому что дискретизация может преобразовать набор данных с непрерывными атрибутами в набор только с номинальными атрибутами.
Дискретизированные признаки, закодированные одним горячим способом (One-hot encoded), могут сделать модель более выразительной, сохраняя при этом интерпретируемость. Например, предварительная обработка с помощью дискретизатора может внести нелинейность в линейные модели.
6.3.5.1. Дискретизация K-бинов
KBinsDiscretizer дискретизирует функции в k бункеры:
>>> X = np.array([[ -3., 5., 15 ], . [ 0., 6., 14 ], . [ 6., 3., 11 ]]) >>> est = preprocessing.KBinsDiscretizer(n_bins=[3, 2, 2], encode='ordinal').fit(X)
По умолчанию выходные данные быстро кодируются в разреженную матрицу (см. Категориальные функции кодирования ), и это можно настроить с помощью encode параметра. Для каждого объекта границы fit интервалов вычисляются во время и вместе с количеством интервалов они определяют интервалы. Следовательно, для текущего примера эти интервалы определены как:
На основе этих интервалов бинов X преобразуется следующим образом:
>>> est.transform(X) array([[ 0., 1., 1.], [ 1., 1., 1.], [ 2., 0., 0.]])
Результирующий набор данных содержит порядковые атрибуты, которые в дальнейшем можно использовать в файле Pipeline .
Дискретизация аналогична построению гистограмм для непрерывных данных. Однако гистограммы фокусируются на подсчете объектов, которые попадают в определенные интервалы, тогда как дискретизация фокусируется на присвоении значений признаков этим интервалам.
KBinsDiscretizer реализует различные стратегии биннинга, которые можно выбрать с помощью strategy параметра. «Равномерная» стратегия использует ячейки постоянной ширины. Стратегия «квантилей» использует значения квантилей, чтобы иметь одинаково заполненные ячейки в каждой функции. Стратегия «k-средних» определяет интервалы на основе процедуры кластеризации k-средних, выполняемой для каждой функции независимо.
Имейте в виду, что можно указать настраиваемые интервалы, передав вызываемый объект, определяющий стратегию дискретизации FunctionTransformer . Например, мы можем использовать функцию Pandas pandas.cut :
>>> import pandas as pd >>> import numpy as np >>> bins = [0, 1, 13, 20, 60, np.inf] >>> labels = ['infant', 'kid', 'teen', 'adult', 'senior citizen'] >>> transformer = preprocessing.FunctionTransformer( . pd.cut, kw_args= . ) >>> X = np.array([0.2, 2, 15, 25, 97]) >>> transformer.fit_transform(X) ['infant', 'kid', 'teen', 'adult', 'senior citizen'] Categories (5, object): ['infant' < 'kid' < 'teen' < 'adult' < 'senior citizen']
- Использование KBinsDiscretizer для дискретизации непрерывных объектов
- Дискретизация функций
- Демонстрация различных стратегий KBinsDiscretizer
6.3.5.2. Бинаризация функций
Бинаризация функций — это процесс определения пороговых значений числовых функций для получения логических значений . Это может быть полезно для последующих вероятностных оценок, которые предполагают, что входные данные распределены согласно многомерному распределению Бернулли . Например, это касается BernoulliRBM .
В сообществе обработки текста также распространено использование двоичных значений признаков (вероятно, для упрощения вероятностных рассуждений), даже если нормализованные подсчеты (также известные как частоты терминов) или функции, оцениваемые по TF-IDF, часто работают немного лучше на практике.
Что касается Normalizer класса утилиты, Binarizer он предназначен для использования на ранних этапах Pipeline . Метод fit не делает ничего , поскольку каждый образец обрабатывают независимо от других:
>>> X = [[ 1., -1., 2.], . [ 2., 0., 0.], . [ 0., 1., -1.]] >>> binarizer = preprocessing.Binarizer().fit(X) # fit does nothing >>> binarizer Binarizer() >>> binarizer.transform(X) array([[1., 0., 1.], [1., 0., 0.], [0., 1., 0.]])
Есть возможность настроить порог бинаризатора:
>>> binarizer = preprocessing.Binarizer(threshold=1.1) >>> binarizer.transform(X) array([[0., 0., 1.], [1., 0., 0.], [0., 0., 0.]])
Что касается Normalizer класса, модуль предварительной обработки предоставляет вспомогательную функцию, binarize которая будет использоваться, когда API-интерфейс преобразователя не нужен.
Обратите внимание, что Binarizer это похоже на то, KBinsDiscretizer когда k = 2 и когда край ячейки находится на значении threshold .
binarize и Binarizer принимать как плотные, похожие на массивы, так и разреженные матрицы из scipy.sparse в качестве входных данных .
Для разреженного ввода данные преобразуются в представление сжатых разреженных строк (см scipy.sparse.csr_matrix . Раздел «Ресурсы» ). Чтобы избежать ненужных копий памяти, рекомендуется выбирать представление CSR в восходящем направлении.
6.3.6. Вменение пропущенных значений
Инструменты для вменения пропущенных значений обсуждаются в разделе «Вменение пропущенных значений» .
6.3.7. Создание полиномиальных признаков
Часто бывает полезно усложнить модель, учитывая нелинейные особенности входных данных. Простой и распространенный метод использования — это полиномиальные функции, которые могут получить термины высокого порядка и взаимодействия функций. Реализован в PolynomialFeatures :
>>> import numpy as np >>> from sklearn.preprocessing import PolynomialFeatures >>> X = np.arange(6).reshape(3, 2) >>> X array([[0, 1], [2, 3], [4, 5]]) >>> poly = PolynomialFeatures(2) >>> poly.fit_transform(X) array([[ 1., 0., 1., 0., 0., 1.], [ 1., 2., 3., 4., 6., 9.], [ 1., 4., 5., 16., 20., 25.]])
Особенности X были преобразованы из $(X_1, X_2)$ к $(1, X_1, X_2, X_1^2, X_1X_2, X_2^2)$.
В некоторых случаях требуются только условия взаимодействия между функциями, и это можно получить с помощью настройки interaction_only=True :
>>> X = np.arange(9).reshape(3, 3) >>> X array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) >>> poly = PolynomialFeatures(degree=3, interaction_only=True) >>> poly.fit_transform(X) array([[ 1., 0., 1., 2., 0., 0., 2., 0.], [ 1., 3., 4., 5., 12., 15., 20., 60.], [ 1., 6., 7., 8., 42., 48., 56., 336.]])
Особенности $X$ были преобразованы из $(X_1, X_2, X_3)$ к $(1, X_1, X_2, X_3, X_1X_2, X_1X_3, X_2X_3, X_1X_2X_3)$.
Обратите внимание , что полиномиальные функции используются неявно в методах ядра (например, SVC , KernelPCA ) при использовании полиномиальных функций ядра .
См. Раздел Полиномиальная интерполяция для регрессии Риджа с использованием созданных полиномиальных функций.
6.3.8. Трансформаторы на заказ
Часто вам может потребоваться преобразовать существующую функцию Python в преобразователь для помощи в очистке или обработке данных. Вы можете реализовать преобразователь из произвольной функции с помощью FunctionTransformer . Например, чтобы создать преобразователь, который применяет преобразование журнала в конвейере, выполните:
>>> import numpy as np >>> from sklearn.preprocessing import FunctionTransformer >>> transformer = FunctionTransformer(np.log1p, validate=True) >>> X = np.array([[0, 1], [2, 3]]) >>> transformer.transform(X) array([[0. , 0.69314718], [1.09861229, 1.38629436]])
Вы можете убедиться, что func и inverse_func являются противоположностью друг другу, установив check_inverse=True и вызвав fit раньше transform . Обратите внимание, что появляется предупреждение, которое может быть преобразовано в ошибку с помощью filterwarnings :
>>> import warnings >>> warnings.filterwarnings("error", message=".*check_inverse*.", . category=UserWarning, append=False)
Полный пример кода, демонстрирующий использование a FunctionTransformer для извлечения функций из текстовых данных, см. В разделе Преобразователь столбцов с гетерогенными источниками данных.
Если вы хотите помочь проекту с переводом, то можно обращаться по следующему адресу support@scikit-learn.ru
© 2007 - 2020, scikit-learn developers (BSD License).
Как писать преобразователи данных в Sklearn

Сегодня разбираемся, как создавать собственные преобразователи Sklearn, позволяющие интегрировать практически любую функцию или преобразование данных в классы конвейера Sklearn. Подробности под катом к старту флагманского курса по Data Science.
Зачем?
Только один вызов fit , и один — predict — насколько это было бы здорово? Вы получаете данные, обучаете конвейер единожды, и он заботится о предварительной обработке, инжиниринге признаков, моделировании. Всё, что нужно сделать вам, — это вызвать fit .
Какой же конвейер для этого достаточно мощный? В Sklearn много преобразователей, но не для всех ситуаций предварительной обработки. Итак, наш конвейер — несбыточная мечта, или нет? Точно нет.
Что такое конвейеры Sklearn?
Вот простой конвейер, который заполняет пропущенные значения числами, масштабирует их и обучает XGBRegressor на X , y :
from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler from sklearn.impute import SimpleImputer import xgboost as xgb xgb_pipe = make_pipeline( SimpleImputer(strategy='mean'), StandardScaler(), xgb.XGBRegressor() ) _ = xgb_pipe.fit(X, y)
В этом посте я в мельчайших подробностях рассказал о конвейерах Sklearn и об их преимуществах.
Самое заметное преимущество конвейеров — способность объединять все этапы предварительной обработки и моделирования в единственный оценщик, предотвращать утечку данных и не вызывать fit на наборах данных для валидации. А ещё конвейер — это бонус в виде краткого, воспроизводимого, модульного кода.
Но вся эта идея атомарных, аккуратных конвейеров ломается, как только нужно выполнять операции, которые не встроены в Sklearn как функции оценки, например:
- Извлечь шаблоны регулярных выражений для очистки текстовых данных нужно.
- Объединить существующие функции в одну, исходя из знаний предметной области.
Чтобы сохранить все преимущества конвейеров, нужен способ интегрировать в Sklearn пользовательскую предварительную обработку и логику инжиниринга признаков. Здесь и вступают в игру пользовательские преобразователи.
Интеграция простых функций через FunctionTransformer
В сентябрьском конкурсе TPS 2021 на Kaggle одна из идей — добавить количества пропущенных [в сроке данных] значений как новый признак — значительно повысила производительность модели. Эта операция не реализована в Sklearn, поэтому напишем функцию, которая отработает после импорта данных:
tps_df = pd.read_csv("data/train.csv") tps_df.head()

>>> tps_df.shape (957919, 120) >>> # Find the number of missing values across rows >>> tps_df.isnull().sum(axis=1) 0 1 1 0 2 5 3 2 4 8 .. 957914 0 957915 4 957916 0 957917 1 957918 4 Length: 957919, dtype: int64
Эта функция принимает DataFrame и реализует операцию:
def num_missing_row(X: pd.DataFrame, y=None): # Calculate some metrics across rows num_missing = X.isnull().sum(axis=1) num_missing_std = X.isnull().std(axis=1) # Add the above series as a new feature to the df X["#missing"] = num_missing X["num_missing_std"] = num_missing_std return X
Добавим в функцию в конвейер — передадим её в FunctionTransformer :
from sklearn.preprocessing import FunctionTransformer num_missing_estimator = FunctionTransformer(num_missing_row)
При передаче пользовательской функции в FunctionTransformer создаётся оценщик с методами fit , transform и fit_transform :
# Check number of columns before print(f"Number of features before preprocessing: ") # Apply the custom estimator tps_df = num_missing_estimator.transform(tps_df) print(f"Number of features after preprocessing: ") ------------------------------------------------------ Number of features before preprocessing: 120 Number of features after preprocessing: 122
Итак, у нас есть простая функция, поэтому нет необходимости вызывать fit : она просто возвращает нетронутую оценку. Единственное требование FunctionTransformer состоит в том, что передаваемая функция должна принимать данные в своём первом аргументе. При желании, если в функции нужен целевой массив, можно передать и его:
# FunctionTransformer signature def custom_function(X, y=None): . estimator = FunctionTransformer(custom_function) # no errors custom_pipeline = make_pipeline(StandardScaler(), estimator, xgb.XGBRegressor()) custom_pipeline.fit(X, y)
FunctionTransformer также принимает инверсию переданной функции на случай, если понадобится отменить изменения:
def custom_function(X, y=None): . def inverse_of_custom(X, y=None): . estimator = FunctionTransformer(func=custom_function, inverse_func=inverse_of_custom)
Подробности о других аргументах смотрите в документации.
Интеграция сложных шагов предварительной обработки
Один из самых распространённых вариантов масштабирования искажённых данных — это логарифмическое преобразование. Но если функция содержит хотя бы один 0, преобразование с помощью np.log или PowerTransformer вернёт ошибку.
Для обхода особенности особенности участники соревнований Kaggle ко всем образцам данных добавляют 1, и лишь затем применяют преобразование. Если преобразование выполняется в целевом массиве, то потребуется обратное преобразование, для которого после прогнозирования нужно использовать экспоненциальную функцию и вычесть 1:
y_transformed = np.log(y + 1) _ = model.fit(X, y_transformed) preds = np.exp(model.predict(X, y_transformed) - 1)
Работает, но осталась та же проблема — мы не можем включить код в конвейер из коробки. Конечно, можно обратиться к новому другу — FunctionTransformer , но он не подходит для сложных этапов предварительной обработки, таких как этот.
Вместо этого напишем собственный класс преобразователя и создадим функции fit , transform вручную. В конце концов у нас снова будет Sklearn-совместимый оценщик. Начнём:
from sklearn.base import BaseEstimator, TransformerMixin class CustomLogTransformer(BaseEstimator, TransformerMixin): pass
Сначала мы создаём класс, который наследуется от BaseEstimator и TransformerMixin из sklearn.base . Наследование этих классов позволяет конвейерам Sklearn распознавать классы как пользовательские оценщики.
Напишем метод __init__ , где инициализируем экземпляр PowerTransformer :
from sklearn.preprocessing import PowerTransformer class CustomLogTransformer(BaseEstimator, TransformerMixin): def __init__(self): self._estimator = PowerTransformer()
Напишем fit , где добавляем 1 ко всем признакам в данных и обучаем PowerTransformer :
class CustomLogTransformer(BaseEstimator, TransformerMixin): def __init__(self): self._estimator = PowerTransformer() def fit(self, X, y=None): X_copy = np.copy(X) + 1 self._estimator.fit(X_copy) return self
Метод fit должен возвращать сам преобразователь, это делается возвратом self . И проверим то, что мы написали:
custom_log = CustomLogTransformer() >>> custom_log.fit(tps_df) CustomLogTransformer()
Пока работает как положено.
У нас есть transform , где после добавления 1 к переданным данным вызывается transform из класса PowerTransformer :
class CustomLogTransformer(BaseEstimator, TransformerMixin): def __init__(self): self._estimator = PowerTransformer() def fit(self, X, y=None): X_copy = np.copy(X) + 1 self._estimator.fit(X_copy) return self def transform(self, X): X_copy = np.copy(X) + 1 return self._estimator.transform(X_copy)
Проверим его по-другому:
custom_log = CustomLogTransformer() custom_log.fit(tps_df) transformed_tps = custom_log.transform(tps_df) >>> transformed_tps[:5, :5] array([[ 0.48908946, -2.17126787, -1.79124946, -0.52828469, nan], [ 0.38660665, -0.29384644, 1.31313666, 0.1901713 , -0.34236997], [-0.04286469, -0.05047097, -1.16463754, 0.95459266, 1.71830766], [-0.584329 , -1.5743182 , -1.02444525, -0.15117546, 0.46952437], [-0.87027925, -0.13045462, -0.10489176, -0.36806683, 1.21317668]])
Работает как надо. Как я уже говорил, нам нужен метод отмены преобразования:
class CustomLogTransformer(BaseEstimator, TransformerMixin): def __init__(self): self._estimator = PowerTransformer() def fit(self, X, y=None): X_copy = np.copy(X) + 1 self._estimator.fit(X_copy) return self def transform(self, X): X_copy = np.copy(X) + 1 return self._estimator.transform(X_copy) def inverse_transform(self, X): X_reversed = self._estimator.inverse_transform(np.copy(X)) return X_reversed - 1
Вместо inverse_transform можно было воспользоваться np.exp . Теперь проведём окончательную проверку:
custom_log = CustomLogTransformer() tps_transformed = custom_log.fit_transform(tps_df) tps_inversed = custom_log.inverse_transform(tps_transformed)
Но подождите! Мы не писали _fit_transform_ — откуда она взялась?
Это просто — когда вы наследуетесь от _BaseEstimator_ и _TransformerMixin_ , то метод _fit_transform_ получаете просто так.
После обратного преобразования можно сравнить его с исходными данными:
>>> tps_df.values[:5, 5] array([0.35275, 0.17725, 0.25997, 0.4293 , 0.34079]) >>> tps_inversed[:5, 5] array([0.35275, 0.17725, 0.25997, 0.4293 , 0.34079])
Теперь у нас есть собственный преобразователь. Давайте соберём весь код воедино:
from sklearn.metrics import roc_auc_score from sklearn.model_selection import train_test_split from sklearn.pipeline import make_pipeline xgb_pipe = make_pipeline( FunctionTransformer(num_missing_row), SimpleImputer(strategy="constant", fill_value=-99999), CustomLogTransformer(), xgb.XGBClassifier( n_estimators=1000, tree_method="gpu_hist", objective="binary:logistic" ), ) X, y = tps_df.drop("claim", axis=1), tps_df[["claim"]].values.flatten() split = train_test_split(X, y, test_size=0.33, random_state=1121218) X_train, X_test, y_train, y_test = split xgb_pipe.fit(X_train, y_train) preds = xgb_pipe.predict_proba(X_test) >>> roc_auc_score(y_test, preds[:, 1]) 0.7986831816726399
Несмотря на то что преобразование нанесло вред модели, мы заставили наш конвейер работать!
Говоря коротко, сигнатура пользовательского класса преобразователя должна быть такой:
class CustomTransformer(BaseEstimator, TransformerMixin): def __init__(self): pass def fit(self): pass def transform(self): pass def inverse_transform(self): pass
Так вы получаете fit_transform без всяких усилий. Если не нужны методы __init__ , fit , transform или inverse_transform , не используйте их, родительские классы Sklearn позаботятся обо всём. Логика этих методов полностью зависит от ваших нужд.
А пока вы осваиваете преобразования в Sklearn, мы поможем вам прокачать навыки или с самого начала освоить профессию, востребованную в любое время:
- Профессия Data Scientist
- Профессия Fullstack-разработчик на Python
Difference Between fit(), transform(), and fit_transform() Methods in Scikit-Learn
Scikit-Learn is a powerful machine learning library that provides various methods for data preprocessing and model training. In this article, we will explore the distinctions between three commonly used methods: fit(), transform(), and fit_transform() sklearn. Understanding these methods is crucial for effectively using Scikit-Learn in machine learning projects. We will delve into the purpose and functionality of each method, as well as when and how to use them. By the end of this article, you will clearly understand how to apply these methods in Scikit-Learn to enhance your data analysis and model building.
Table of contents
- Data Science Project Life Cycle
- Transformer In Sklearn
- Difference Between fit and fit_transform Sklearn
- fit()
- transform()
- fit_transform() Sklearn
- Conclusion
- Frequently Asked Questions
Test your knowledge of Scikit Learn methods used in ML pipelines, their distinct functionalities, and when to apply each for optimal data preprocessing and model training.
Start Quiz
You got <> out of >
Data Science Project Life Cycle
Before we start exploring the fit, transform, and fit_transform functions in Python, let’s consider the life cycle of any data science project. This will give us a better idea of the steps involved in developing any data science project and the importance and usage of these functions. Let’s discuss these steps in points:
- Exploratory Data Analysis (EDA) is used to analyze the datasets using pandas, numpy, matplotlib, etc., and dealing with missing values. By doing EDA, we summarize their main importance.
- Feature Engineering is the process of extracting features from raw data with some domain knowledge.
- Feature Selection is where we select those features from the dataframe that will give a high impact on the estimator.
- Model creation in this, we create a machine learning model using suitable algorithms, e.g., regressor or classifier.
- Deployment where we deploy our ML model on the web.
If we consider the first 3 steps, then it will probably be more towards Data Preprocessing, and Model Creation is more towards Model Training. So these are the two most important steps whenever we want to deploy any machine learning application.
Transformer In Sklearn
Scikit-learn has an object, usually, something called a Transformer. The use of a transformer is that it will be performing data preprocessing and feature transformation, but in the case of model training, we have learning algorithms like linear regression, logistic regression, knn, etc., if we talk about the examples of Transformer-like StandardScaler, which helps us to do feature transformation where it converts the feature with mean =0 and standard deviation =1, PCA, Imputer, MinMaxScaler, etc. then all these particular techniques have seen that we are doing some preprocessing on the input data will change the format of training dataset, and that data will be used for model training.
Suppose we take f1, f2, f3, and f4 features where f1, f2, and f3 are independent features, and f4 is our dependent feature. We apply a standardization process in which it takes a feature F and converts it into F’ by applying a formula of standardization. If you notice, at this stage, we take one input feature F and convert it into another input feature F’ itself So, in this condition, we do three different operations:
Now, we will discuss how the following operations are different from each other.
Difference Between fit and fit_transform Sklearn
| Method | Purpose | Syntax | Example |
|---|---|---|---|
| fit() | Learn and estimate the parameters of the transformation | estimator.fit(X) | estimator.fit(train_data) |
| transform() | Apply the learned transformation to new data | transformed_data = estimator.transform(X) | transformed_data = estimator.transform(test_data) |
| fit_transform() | Learn the parameters and apply the transformation to new data | transformed_data = estimator.fit_transform(X) | transformed_data = estimator.fit_transform(data) |
Note: In the syntax, estimator refers to the specific estimator or transformer object from Scikit-Learn that is being used. X represents the input data.
Example: Suppose we have a dataset train_data for training and test_data for testing. We can use fit() to learn the parameters from the training data ( estimator.fit(train_data) ) and then use transform() to apply the learned transformation to the test data ( transformed_data = estimator.transform(test_data) ). Alternatively, we can use fit_transform() to perform both steps in one ( transformed_data = estimator.fit_transform(data) ).
fit()
In the fit() method, where we use the required formula and perform the calculation on the feature values of input data and fit this calculation to the transformer. For applying the fit() method (fit transform in python), we have to use fit() in frontof the transformer object.
Suppose we initialize the StandardScaler object O and we do .fit(). It takes the feature F and computes the mean (μ) and standard deviation (σ) of feature F. That is what happens in the fit method.
from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # split training and testing data xtrain,xtest,ytrain,ytest= train_test_split( x,y, test_size=0.3, random_state=42 ) # creating object stand= StandardScaler() # fit data Fit= stand.fit(xtrain)
First, we have to split the dataset into training and testing subsets, and after that, we apply a transformer to that data.
In the next step, we basically perform a transform because it is the second operation on the transformer.
transform()
For changing the data, we probably do transform in the transform() method, where we apply the calculations that we have calculated in fit() to every data point in feature F. We have to use .transform() in front of a fit object because we transform the fit calculations.
The above example when we create an object of the fit method. We then put it in front of the .transform, and the transform method uses those calculations to transform the scale of the data points, and the output will we get is always in the form of a sparse matrix or array.
from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # split training and testing data xtrain,xtest,ytrain,ytest= train_test_split( x,y, test_size=0.3, random_state=42 ) # creating object stand= StandardScaler() # fit data Fit= stand.fit(xtrain) # transform data x_scaled = Fit.transform(xtrain)
As you can see that the output of the transform is in the form of an array in which data points vary from 0 to 1.
Note: It will only perform when we want to do some kind of transformation on the input data.
fit_transform() Sklearn
The fit_transform() Sklearn method is basically the combination of the fit method and the transform method. This method simultaneously performs fit and transform operations on the input data and converts the data points.Using fit and transform separately when we need them both decreases the efficiency of the model. Instead, fit_transform() is used to get both works done.
Suppose we create the StandarScaler object, and then we perform .fit_transform(). It will calculate the mean(μ)and standard deviation(σ) of the feature F at a time it will transform the data points of the feature F.
from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # split training and testing data xtrain,xtest,ytrain,ytest= train_test_split( x,y, test_size=0.3, random_state=42 ) stand= StandardScaler() Fit_Transform = stand.fit_transform(xtrain) Fit_Transform
This method output is the same as the output we obtain after applying the separate fit() and transform() methods.
Conclusion
In conclusion, the scikit-learn library provides us with three important methods, namely fit(), transform(), and fit_transform() Sklearn, that are used widely in machine learning. The fit() method helps in fitting the data into a model, transform() method helps in transforming the data into a form that is more suitable for the model. Fit_transform() method, on the other hand, combines the functionalities of both fit() and transform() methods in one step. Understanding the differences between these methods is very important to perform effective data preprocessing and feature engineering.
Key Takeaways
- The fit() method helps in fitting the training dataset into an estimator (ML algorithms).
- The transform() helps in transforming the data into a more suitable form for the model.
- The fit_transform() method combines the functionalities of both fit() and transform().
Frequently Asked Questions
Q1. Can we use transform() without using fit() in scikit-learn?
A. Yes, transform() method can be used without using fit() method in scikit-learn. This is useful when we want to transform new data using the same scaling or encoding applied to the training data.
Q2. What is the purpose of fit_transform() in scikit-learn?
A. The fit_transform() method is used to fit the data into a model and transform it into a form that is more suitable for the model in a single step. This saves us the time and effort of calling both fit() and transform() separately.
Q3. Are there any limitations to using fit(), transform(), and fit_transform() methods in scikit-learn?
A. The main limitation of these methods is that they may not work well with certain types of data, such as data with null values or outliers, and we might need to perform additional preprocessing steps.