Вопрос или проблема
Я начинающий в scikit-learn, и у меня небольшая проблема при использовании модуля отбора признаков VarianceThreshold. Проблема в том, что когда я устанавливаю дисперсию Var[X]=.8*(1-.8)
предполагается, что будут удалены все признаки (которые имеют одинаковое значение во всех образцах), у которых вероятность $p>0.8$. В моем случае пятая колонка должна быть удалена, p=8/10>(threshold=0,7)
.
#####################################
from sklearn.feature_selection import VarianceThreshold
X=[[0,1,1,1,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,254,1.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00],
[0,1,1,1,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,254,1.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00],
[0,1,1,1,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,254,1.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00],
[0,1,1,1,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,254,1.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00],
[0,1,1,1,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,254,1.00,0.01,0.01,0.00,0.00,0.00,0.00,0.00],
[0,1,1,1,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,255,1.00,0.00,0.01,0.00,0.00,0.00,0.00,0.00],
[0,1,2,1,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,0.00,0.00,0.00,0.00,0.50,1.00,0.00,10,3,0.30,0.30,0.30,0.00,0.00,0.00,0.00,0.00],
[0,1,1,1,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,253,0.99,0.01,0.00,0.00,0.00,0.00,0.00,0.00],
[0,1,1,1,105,146,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0.00,0.00,0.00,0.00,1.00,0.00,0.00,255,254,1.00,0.01,0.00,0.00,0.00,0.00,0.00,0.00],
[0,2,3,1,223,185,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,4,4,0.00,0.00,0.00,0.00,1.00,0.00,0.00,71,255,1.00,0.00,0.01,0.01,0.00,0.00,0.00,0.00]]
sel=VarianceThreshold(threshold=(.7*(1-.7)))
А вот что я получаю при запуске скрипта
>>> sel.fit_transform(X)
array([[ 1., 105., 146., 1., 1., 255., 254.],
[ 1., 105., 146., 1., 1., 255., 254.],
[ 1., 105., 146., 1., 1., 255., 254.],
[ 1., 105., 146., 2., 2., 255., 254.],
[ 1., 105., 146., 2., 2., 255., 254.],
[ 1., 105., 146., 2., 2., 255., 255.],
[ 2., 29., 0., 2., 1., 10., 3.],
[ 1., 105., 146., 1., 1., 255., 253.],
[ 1., 105., 146., 2., 2., 255., 254.],
[ 3., 223., 185., 4., 4., 71., 255.]])
Вторая колонка здесь не должна появляться. Спасибо;)
0.8 – это пороговое значение, означающее, что вы хотите исключить колонки (признаки) с как минимум 80% значений равных 0 или 1: своего рода несбалансированные фиктивные переменные. Это хорошо применяется только к фиктивным переменным, но не обязательно к общим числовым значениям. Для числовых вы можете протестировать функцию RFECV из пакета feature_selection в scikit-learn, синтаксис следующий:
feature_folds = ms.KFold(n_splits=10, shuffle = True) # фолды кросс-валидации
selector = fs.RFECV(estimator = your_model, cv = feature_folds,
scoring = 'roc_auc')
selector = selector.fit(your_features, your_labels)
selector.support_
Ответ или решение
Вопрос о использовании метода выбора признаков VarianceThreshold из библиотеки scikit-learn представляет собой интересную задачу, особенно для начинающих специалистов в области анализа данных. Рассмотрим, как правильно настроить этот метод, чтобы он соответствовал вашим ожиданиям.
Понимание VarianceThreshold
VarianceThreshold
— это метод, используемый для удаления признаков из набора данных, если их дисперсия ниже заданного порога. Это означает, что данный метод может быть полезен для исключения признаков, которые не предоставляют значимой информации для модели, прежде чем вы начнете ее обучение.
Проблема с вашим кодом
В вашем коде задан порог:
threshold=(.7*(1-.7))
Рассмотрим, что это означает. В вашем случае вы хотите удалить признаки, у которых вероятность (p) значений больше 0.8. Тем не менее, для метода VarianceThreshold
, порог задается по формуле, которая действительно определяет, какие признаки оставлять.
Объяснение дисперсии
Дисперсия признака рассчитывается как:
[ Var[X] = p \cdot (1 – p) ]
Где ( p ) — это вероятность (в данном случае, относительная частота, с которой значение признака равно 1, например). Если Var[X]
меньше вашего порога, значит, этот признак можно удалить.
Чтобы достичь вашей цели, вы должны убедиться, что значение threshold
вы можете задать в соответствии с вашим пониманием вероятностей. Например, если вы хотите удалить признаки, у которых ( p > 0.8 ), вам нужно рассчитать, какую дисперсию это будет означать:
- Для ( p = 0.8 ):
[
Var[X] = 0.8 \cdot (1 – 0.8) = 0.8 \cdot 0.2 = 0.16
]
Таким образом, если вы хотите удалить признаки с ( p > 0.8 ), вам следует установить порог на уровне 0.16.
Исправленный код
Давайте обновим ваш код исходя из этих знаний:
from sklearn.feature_selection import VarianceThreshold
# Пример данных
X = [
[0, 1, 1, 1, 105, 146, 0, 0, 0, 0],
[0, 1, 1, 1, 105, 146, 0, 0, 0, 0],
[0, 1, 1, 1, 105, 146, 0, 0, 0, 0],
[0, 1, 1, 1, 105, 146, 0, 0, 0, 0],
# Добавьте остальные данные...
]
# Установка порога
threshold = 0.8 * (1 - 0.8) # Это не будет работать: нужно установить минимум 0.16
sel = VarianceThreshold(threshold=0.16)
X_reduced = sel.fit_transform(X)
print(X_reduced)
Заключение
Теперь, корректируя порог, вы сможете точно настроить VarianceThreshold
для исключения признаков с высокой дисперсией и, следовательно, выбрать те, которые действительно информативны. Не забывайте, что можно использовать другие методы выбора признаков, такие как RFECV
, как вы уже упоминали, для более сложной выборки. Таким образом, ваше понимание работы с данными в Python будет расти, что приведет к созданию более точных и эффективных моделей машинного обучения.