Нормализация данных перед удалением низкой дисперсии, делает ошибки

Я тестирую набор данных iris (можно загрузить с помощью функции load_iris() из sklearn.datasets) с функциями scikit-learn normalize и VarianceThreshold.

Кажется, что если я использую MinMaxScaler, а затем запускаю VarianceThreshold - фич не остается.

Перед масштабированием:

Column:  sepal length (cm)  Mean:  5.843333333333334  var =  0.6811222222222223  var/mean:  0.11656398554858338
Column:  sepal width (cm)  Mean:  3.0573333333333337  var =  0.1887128888888889  var/mean:  0.06172466928332606
Column:  petal length (cm)  Mean:  3.7580000000000005  var =  3.0955026666666665  var/mean:  0.8237101295015078
Column:  petal width (cm)  Mean:  1.1993333333333336  var =  0.5771328888888888  var/mean:  0.48121141374837856

После масштабирования (MinMaxScaler)

Column:  sepal length (cm)  Mean:  0.42870370370370364  var =  0.052555727023319614  var/mean:  0.12259219262459005
Column:  sepal width (cm)  Mean:  0.44055555555555553  var =  0.03276265432098764  var/mean:  0.07436668067815606
Column:  petal length (cm)  Mean:  0.46745762711864397  var =  0.08892567269941587  var/mean:  0.19023258481745967
Column:  petal width (cm)  Mean:  0.4580555555555556  var =  0.10019668209876545  var/mean:  0.2187435145879658

Я использую VarianceThreshold как:

    from sklearn.feature_selection import VarianceThreshold
    sel = VarianceThreshold(threshold=(.8 * (1 - .8)))

Должны ли мы масштабировать данные (например, до MinMaxScaler), если мы хотим удалить объекты с низкой дисперсией?


person Boom    schedule 11.04.2020    source источник


Ответы (3)


Масштабирование данных в целом не поможет найти лишние функции.

Обычно VarianceThreshold используется для удаления признаков с нулевой дисперсией, то есть констант, не дающих никакой информации. Строка в вашем коде VarianceThreshold(threshold=(.8 * (1 - .8))) отбрасывает все функции с дисперсией ниже 0,16. И в вашем случае все функции имеют дисперсию ниже этой (после MinMaxScaler самая высокая дисперсия - ширина лепестка 0.1), поэтому вы все отбрасываете. Я считаю, что вы хотели оставить функции, которые вносят более 80% дисперсии, но это не то, что делает ваш код. И если бы вы применили эту строку до MinMaxScaler, то все ваши функции прошли бы.

Чтобы удалить функции с низкой дисперсией, вам нужно сначала определить разумный порог для этой конкретной функции. Но в общем случае вы не можете установить жестко закодированный произвольный порог дисперсии, потому что для одних признаков значение будет слишком высоким, а для других слишком низким. Например, PCA часто используется в качестве процедуры выбора признаков. Выполняют PCA и берут только K первых собственных векторов, где K выбирают таким образом, чтобы энергия соответствующих собственных значений составляла (скажем) 95% (или даже 80%) от общей. Таким образом, в случаях, когда у вас есть набор данных с 50-100 функциями, вы можете уменьшить количество функций в десять раз, не теряя при этом много информации.

Когда вы примените StandardScaler, все ваши функции будут центрированы и нормированы, поэтому их среднее значение будет равно нулю, а дисперсия равна 1 (конечно, за исключением констант). MinMaxScaler по умолчанию перенесет ваши функции в диапазон [0..1]. Вопрос не в том, какой масштабатор использовать, а в том, почему вы хотите использовать масштабатор. В общем случае вы не хотите выбрасывать функции, если вам это не нужно.

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

person igrinis    schedule 02.08.2020

По сути, функция с низкой дисперсией означает функция, по которой не хватает информации. То есть, если функция имеет дисперсию, близкую к нулю, она близка к тому, чтобы принимать постоянное значение. Однако каждая функция может представлять разную величину, поэтому ее дисперсия различна.

Например, рассмотрим в качестве ковариатов age, которые могут варьироваться от 0 до 100, и number_of_childs, которые могут варьироваться от 0 до 5 в качестве примера. Поскольку эти две переменные принимают разные значения, они будут иметь разные дисперсии. Теперь, масштабируя объекты, можно установить для них одни и те же единицы. Таким образом, мы могли бы сравнить их информацию в одном масштабе.

Обратите внимание, что для набора данных по радужной оболочке все функции установлены в одном масштабе (в сантиметрах), т. е.

from sklearn.datasets import load_iris

data = load_iris()
print(data.features_names) 
>>> ['sepal length (cm)',
     'sepal width (cm)',
     'petal length (cm)',
     'petal width (cm)']

В этом случае хорошим первым шагом будет центрирование данных. Делая это, можно удалить из него шум.

import pandas as pd 

X = pd.DataFrame(data['data'], columns=data.feature_names)
X = X - X.mean()
person Miguel Trejo    schedule 31.07.2020
comment
Центрируя данные, вы удаляете смещение (также известное как средний или постоянный компонент), а не шум. Обычно выполняется нормализация данных, потому что многие алгоритмы (например, SVM) работают намного лучше, когда данные находятся в диапазоне около [-1..1]. Для некоторых, например дерева решений, нормализация вообще не нужна. - person igrinis; 02.08.2020

MinMaxScaler использует следующую формулу:

X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min

Если вы проверите документы порога дисперсии и увидите формулу для дисперсии дисперсия набора из n равновероятных значений может быть эквивалентно выражена без прямой ссылки на среднее значение в терминах квадратов отклонений всех точек друг от друга:

введите здесь описание изображения

Итак, давайте сравним небольшой пример с двумя столбцами и тремя переменными:

a  b
1  0
0  1
0  2

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

a: (0.5(1-0)^2+0.5(1-0)^2+ 0.5(0-1)^2 +0.5(0-0)^2 + 0.5(0-1)^2 + 0.5(0-1)^2 )/3 = (0.5+0.5+0.5+0.5)/3= 2/3 = 0.75
b: 6/3 = 2

После MinMaxScaler у нас будет:

a  b
1  0
0  0.5
0  1

и так дисперсия:

a: 2/3
b: 2/3 

Таким образом, с порогом 0,8 оба будут исключены после нормализации.

Так что да, когда вы нормализуете свои данные до порога дисперсии, вы всегда будете выбрасывать больше столбцов, потому что основная идея minmaxscaler состоит в том, чтобы нормализовать ваши данные, что означает, что в них будет меньше дисперсии.

person PV8    schedule 31.07.2020
comment
Это кажется очень нелогичным. Чтобы даже использовать VarianceThreshold, мы должны сначала нормализовать данные. Будет ли StandardScaler() лучшим вариантом? - person MrSoLoDoLo; 31.07.2020