Это сообщение продолжает начатую ранее тему подготовки данных для создания предсказательных моделей и посвящено трансформации предикторов. Необходимость преобразование исходных значений предикторов может быть вызвана разными причинами. Например, некоторые статистические методы требуют, чтобы все предикторы измерялись в одинаковых единицах. В других случаях качество модели может в значительной мере зависеть от наличия выбросов. Ниже будут описаны некоторые наиболее распространенные способы трансформации количественных предикторов, с примерами их реализации средствами пакета caret.
Трансформация отдельных предикторов
Начнем с преобразования значений отдельных предикторов. В качестве примера используем рассмотренные ранее данные GermanCredit по кредитоспособности клиентов одного из немецких банков:
library(caret) data(GermanCredit) summary(GermanCredit) # для экономии места вывод результа предыдущей команды сокращен Duration Amount InstallmentRatePercentage ResidenceDuration Min. : 4.0 Min. : 250 Min. :1.000 Min. :1.000 1st Qu.:12.0 1st Qu.: 1366 1st Qu.:2.000 1st Qu.:2.000 Median :18.0 Median : 2320 Median :3.000 Median :3.000 Mean :20.9 Mean : 3271 Mean :2.973 Mean :2.845 3rd Qu.:24.0 3rd Qu.: 3972 3rd Qu.:4.000 3rd Qu.:4.000 Max. :72.0 Max. :18424 Max. :4.000 Max. :4.000 Age NumberExistingCredits NumberPeopleMaintenance Telephone Min. :19.00 Min. :1.000 Min. :1.000 Min. :0.000 1st Qu.:27.00 1st Qu.:1.000 1st Qu.:1.000 1st Qu.:0.000 Median :33.00 Median :1.000 Median :1.000 Median :1.000 Mean :35.55 Mean :1.407 Mean :1.155 Mean :0.596 3rd Qu.:42.00 3rd Qu.:2.000 3rd Qu.:1.000 3rd Qu.:1.000 Max. :75.00 Max. :4.000 Max. :2.000 Max. :1.000 ...
Стандартизация
В таблицу GermanCredit входят переменные, измеренные на разных шкалах. Так, многие из них являются индикаторными переменными (т.е. отражают наличие или отсутствие того или иного признака у клиента в виде значений 1 и 0). Размер кредита Amount измеряется в немецких марках, возраст клиента Age - в годах, и т.д. Как следствие, размах значений некоторых переменных также существенно разнится. Например, индикаторные переменные по определению варьируют от 0 до 1, тогда как размер кредита изменяется от 250 до 18424 марок. Для приведения всех переменных к одинаковым единицам измерения служит стандартизация. Данная операция заключается в вычитании из исходного значения \(x_i\) некоторой переменной \(X\) соответствующего среднего значения \(\bar{x}\) ("центрирование", или "centering") и последующем делении полученной разницы на стандартное отклонение этой переменной \(\sigma_{x}\) ("нормализация", или "scaling"):
\[ {x}'_{i} = \frac{x_i - \bar{x}}{\sigma_{x}} \]
В результате стандартизации все количественные переменные будут иметь среднее значение, равное 0, и стандартное отклонение, равное 1. Единственным недостатком этой операции является потеря возможности интерпретировать значения отдельных предикторов, поскольку они больше не будут выражаться в исходных единицах измерения. Это, однако, не является большой проблемой, если модель разрабатывается исключительно для прогнозирования и не предназначена для объяснения влияния тех или иных переменных на прогнозируемый отклик.
Преобразование Бокса-Кокса
Помимо того, что многие переменные в таблице GermanCredit выражаются в разных единицах, некоторые из них имеют также явно выраженные асимметричные распределения (например, Amount и Age), что может представлять проблему для некоторых статистических методов. Часто решить эту проблему позволяют такие простые преобразования исходных значений, как извлечение квадратного корня, логарифмирование или расчет обратных значений. В качестве популярной альтернативы можно также использовать т.н. степенное преобразование Бокса-Кокса ("Box-Cox transformation"), которое в общем виде выражается следующим образом:
\( {x}'_{i} = \frac{x_{i}^{\lambda} - 1}{\lambda} \) для \( \lambda \neq 0\) и
\( {x}'_{i} = \log(x) \) для \( \lambda = 0\).
Можно заметить, что преобразование Бокса-Кокса в действительности представляет собой целое семейство преобразований. Так, при \(\lambda = 2\) исходные значения трансформируемой переменной будут возведены в квадрат, при \(\lambda = 0.5\) будет извлечен квадратный корень, а при \(\lambda = -1\) будут рассчитаны обратные значения. Параметр \(\lambda\) может принимать произвольные положительные или отрицательные значения. Оптимальное значение этого параметра для конкретной переменной обычно находят при помощи метода максимального правдоподобия (подробный пример того, как это сделать в R, можно найти в разд. 4.5 книги Мастицкий, Шитиков, 2015). Одной из функций, позволяющих оценить оптимальное значение \(\lambda\) по данным, является функция BoxCoxTrans() из пакета caret. Применим ее, например, к переменной Amount из таблицы GermanCredit:
( AmountTrans = BoxCoxTrans(GermanCredit$Amount) ) Box-Cox Transformation 1000 data points used to estimate Lambda Input data summary: Min. 1st Qu. Median Mean 3rd Qu. Max. 250 1366 2320 3271 3972 18420 Largest/Smallest: 73.7 Sample Skewness: 1.94 Estimated Lambda: -0.1 With fudge factor, Lambda = 0 will be used for transformations
Из приведенного результата видно, что найденное программой оптимальное значение \(\lambda\) составило -0.1 (Estimate Lambda: -0.1). Однако с учетом определенной поправочной константы ("fudge factor"), учитывающей случайный характер выборки, итоговое значение \(\lambda\) составило 0 (см. строку With fudge factor, Lambda = 0 will be used for transformations), что соответствует логарифмированию (см. выше). Для применения преобразования на основе \(\lambda = 0\) к значениям Amount необходимо воспользоваться функцией predict(), подав на нее объект AmountTrans и переменную с исходными значениями:
Результат этого преобразования представлен графически на рисунке ниже:
Одновременная трансформация нескольких предикторов
В ряде случаев возникает необходимость одновременного преобразования целой группы предикторов или сразу всех предикторов, входящих в тот или иной набор данных. Как правило, такая необходимость возникает при наличии многомерных выбросов (подробно понятие выбросов в контексте регрессионного анализа обсуждалось ранее здесь и здесь), а также когда исследователь желает снизить размерность исходной задачи (например, из-за наличия большого количества высоко коррелирующих предикторов) при помощи методов, подобных анализу главных компонент.
Метод пространственных знаков
Если ожидается, что тот или иной метод построения предсказательной модели чувствителен к наличию многомерных выбросов, исходные данные можно преобразовать при помощи метода пространственных знаков ("spatial sign"; Serneels et al. 2006). С математической точки зрения, этот метод проецирует значения предикторов на поверхность многомерной сферы, в результате чего отдельные наблюдения становятся равноудаленными от центра этой сферы:
\[ {x}'_{ij} = \frac{x_{ij}}{\sum_{j=1}^{P} {x}^2_{ij} } \]
В приведенной формуле \(P\) - это число предикторов. Поскольку знаменатель выражает квадрат расстояния до центра распределения предикторов, перед применением этой формулы важно выполнить стандартизацию всех предикторов (этим будет достигнут примерно одинаковый их вклад в величину квадрата расстояния). Кроме того, важно понимать, что это преобразование по методу пространственных знаков применяется одновременно к группе предикторов. Поэтому удаление каких-либо предикторов из анализа после такого преобразования приведет к утрате его смысла.
Метод главных компонент
Метод главных компонент ("principle components analysis", PCA) является одним из наиболее популярных методов снижения размерности исходного набора данных. Необходимость снижения размерности задачи может быть обусловлена, например, чрезмерно большим количеством предикторов по сравнению с количеством наблюдений или большим количеством высоко коррелирующих предикторов, несущих сходную информацию. PCA сводится к нахождению ограниченного числа ортогональных (=некоррелирующих) линейных комбинаций предикторов, которые "объясняют" достаточно высокую долю дисперсии в исходных данных (например, 80% или 95%). Такие линейные комбинации называются главными компонентами и могут быть использованы вместо исходных предикторов. Например, j-тую главную компоненту можно записать следующим образом:
\[ PC_{j} = (a_{j1}X_1) + (a_{j2}X_2) + \dots + (a_{jP}X_P),\]
где P - число предикторов в исходном наборе данных.
Реализация разных методов трансформации при помощи функции preProcess()
В состав пакета caret входит функция preProcess(), которая позволяет одновременно применить к данным любые комбинации рассмотренных выше, а также некоторых других методов трансформации. Ее основными аргументами являются следующие:
- x - таблица или матрица с данными (все переменные должны быть количественными);
- method - метод трансформации; возможные значения: "BoxCox", "YeoJohnson", "expoTrans", "center", "scale", "range", "knnImpute", "bagImpute", "medianImpute", "pca", "ica" и "spatialSign";
- thresh - кумулятивная доля дисперсии исходных, которая должна содержаться в главных компонентах (по умолчанию 0.95, т.е. 95%);
- pcaComp - максимальное число главных компонент (целое число), которое следует оставить после трансформации данных для дальнейшей работы (по умолчанию этот параметр имеет значение NULL, т.е. он выключен, и оптимальное число главных компонент выбирается на основе thresh).
С дополнительными аргументами можно ознакомиться в справочном файле функции, доступном по команде ?preProcess.
Применим функцию preProcess() к таблице GermanCredit, предварительно удалив предикторы с околонулевой дисперсией и разбив данные на обучающую (80%) и контрольную (=проверочную, 20%) выборки.
# Сохраним переменную-отклик в виде отдельного объекта # и удалим ее из таблицы с предикторами: Class = GermanCredit$Class GermanCredit$Class = NULL # Удалим предикторы с околонулевой дисперсией: nz = nearZeroVar(GermanCredit) GermanCredit = GermanCredit[, -nz] # Разобъем исходные данные случайным образом на # обучающую и контрольную выборки: set.seed(202) index = sample(1:nrow(GermanCredit), nrow(GermanCredit)*0.8, replace = F) trSet = GermanCredit[index, ] # обучающая выборка testSet = GermanCredit[-index, ] # проверочная выборка # Применим preProcess() к обучающей выборке и выполним
# преобразование Бокса-Кокса и
# стандартизацию исходных переменных ("center" и "scale"): ( trans = preProcess(trSet, method = c("BoxCox", "center", "scale")) ) Call: preProcess.default(x = trSet, method = c("BoxCox", "center", "scale")) Created from 800 samples and 48 variables Pre-processing: Box-Cox transformation, centered, scaled Lambda estimates for Box-Cox transformation: Min. 1st Qu. Median Mean 3rd Qu. Max. NA's -2.00000 -0.55000 0.00000 -0.01667 0.85000 1.50000 42
Функция preProcess() приводит к созданию объекта одноименного класса. При выводе содержимого этого объекта на экран, мы узнаем, что он был создан на основе 800 наблюдений и 48 переменных (Created from 800 samples and 48 variables), к которым были применены преобразование Бокса-Кокса и стандартизация (Pre-processing: Box-Cox transformation, centered, scaled). Далее мы увидим описательные статистики для параметра \(\lambda\) и узнаем, что преобразование Бокса-Кокса не удалось применить к 42 предикторам (см. Lambda estimates for Box-Cox transformation). Последнее обстоятельство обусловлено тем, что эти 42 переменные являются индикаторными, в связи с чем применение к ним преобразования Бокса-Кокса попросту не имеет смысла.
Важно понимать, что применив функцию preProcess() к обучающим данным, мы просто оценили параметры, необходимые для выполнения соответствующих преобразований (в частности, значения \(\lambda\), средние значения и стандартные отклонения каждой переменной), но данные пока еще остались неизменными. Для применения преобразований с учетом этих оцененных параметров необходимо воспользоваться функцией predict():
Такой подход очень удобен, поскольку однажды создав объект preProcess, мы можем применить его к любым данным, содержащим те же предикторы, что и обучающая выборка, включая данные из контрольной выборки и новые данные, к которым в последующем будет применяться предсказательная модель. Применим, например, преобразования, хранящиеся в объекте trans к нашей контрольной выборке:
Интересует вопрос.C R я на "Вы",к сожалению.
Хотел бы спросить, может есть задачник какой нибудь по R? Потому что обычно, все книги по R могут служить скорее справочниками, нежели учебниками.
Кроме того, обычно логика книг по R такова, что они строятся на конкретных примерах, которые читатель может легко модифицировать для собственных нужд. Соответственно, Вам нужно найти хорошую книгую по интересующей Вас теме и пробовать, пробовать, пробовать...
а так полезно и хорошо!!
Ну понятно, что если у нас логарифмирование было переменной, то мы просто экспонируем, но если у нас было несколько разных итераций?
Отправить комментарий