scikit-learn: параметры произвольного леса class_weight и sample_weight
У меня есть проблема с дисбалансом классов, и я экспериментировал со взвешенным Случайным Лесом, используя реализацию в scikit-learn (>= 0.16).
Я заметил, что реализация принимает параметр class_weight в конструкторе дерева и параметр sample_weight в методе fit, чтобы помочь устранить дисбаланс классов. Эти два, кажется, умножены, чтобы решить окончательный вес.
У меня проблемы с пониманием следующего:
- На каких этапах построения / обучения / прогнозирования дерева используются эти веса? Я видел некоторые документы для взвешенных деревьев, но я не уверен, что реализует Scikit.
- В чем конкретно разница между class_weight и sample_weight?
2 ответа
RandomForests построены на деревьях, которые очень хорошо задокументированы. Проверьте, как деревья используют взвешивание выборки:
- Руководство пользователя по деревьям решений - рассказывает, какой именно алгоритм используется
- API дерева решений - объясняет, как sample_weight используется деревьями (который, как вы определили, для случайных лесов является продуктом class_weight и sample_weight).
Что касается разницы между class_weight
а также sample_weight
: многое можно определить просто по характеру их типов данных. sample_weight
1D массив длины n_samples
, присваивая явный вес каждому примеру, используемому для обучения. class_weight
является ли словарь каждого класса одинаковым весом для этого класса (например, {1:.9, 2:.5, 3:.01}
), или строка, сообщающая sklearn, как автоматически определять этот словарь.
Таким образом, тренировочный вес для данного примера является продуктом его явно названного sample_weight
(или же 1
если sample_weight
не предусмотрено), и это class_weight
(или же 1
если class_weight
не предусмотрено).
Если мы посмотрим исходный код ,RandomForestClassifier
является подклассом отForestClassifier
класс, который, в свою очередь, является подклассом класса, а метод фактически определенBaseForest
сорт. Как отметил ОП, взаимодействие между и определение весов выборки используется для подбора каждого дерева решений случайного леса.
Если мы проверим_validate_y_class_weight()
,иметоды, мы можем понять взаимодействие между иbootstrap
параметры лучше. В частности,
- если передается в
RandomForestClassifier()
конструктор, но не передается, используется в качестве образца веса - если и то, и другое
class_weight
передаются, затем они умножаются вместе, чтобы определить окончательные веса выборки, используемые для обучения каждого отдельного дерева решений. - если
class_weight=None
, затем определяет окончательные веса выборки (по умолчанию, если None, выборки имеют одинаковый вес).
Соответствующую часть исходного кода можно резюмировать следующим образом.
from sklearn.utils import compute_sample_weight
if class_weight == "balanced_subsample" and not bootstrap:
expanded_class_weight = compute_sample_weight("balanced", y)
elif class_weight is not None and class_weight != "balanced_subsample" and bootstrap:
expanded_class_weight = compute_sample_weight(class_weight, y)
else:
expanded_class_weight = None
if expanded_class_weight is not None:
if sample_weight is not None:
sample_weight = sample_weight * expanded_class_weight
else:
sample_weight = expanded_class_weight
Сbootstrap=True
, наблюдения выбираются случайным образом для отдельных обученных деревьев, что осуществляется с помощьюsample_weight
аргумент_parallel_build_trees()
fit()
соответствующий (сокращенный) код которого выглядит следующим образом.
if bootstrap:
if sample_weight is None:
sample_weight = np.ones((X.shape[0],), dtype=np.float64)
indices = check_random_state(tree.random_state).randint(X.shape[0], n_samples_bootstrap)
sample_counts = np.bincount(indices, minlength=X.shape[0])
sample_weight *= sample_counts
if class_weight == "balanced_subsample":
sample_weight *= compute_sample_weight("balanced", y, indices=indices)