Я использую случайный лес в качестве двоичного классификатора для набора данных, и результаты просто не кажутся правдоподобными, но я не могу найти, в чем проблема.
Проблема заключается в том, что примеры явно нельзя разделить путем установки порога, поскольку значения интересующей характеристики для положительных / отрицательных примеров очень однородны. Когда для двоичной классификации используется только один признак, RF должен иметь возможность различать примеры только путем установки абсолютного порога для положительной / отрицательной идентификации, верно? Если это так, то как приведенный ниже код может обеспечить идеальную производительность на тестовом наборе?
P.S. На практике у меня гораздо больше, чем ~ 30 примеров, показанных ниже, но я включил их только в качестве примера. Такая же производительность при оценке> 100.
import numpy as np
from sklearn.ensemble import RandomForestClassifier
X_train = np.array([0.427948, 0.165065, 0.31179, 0.645415, 0.125764,
0.448908, 0.417467, 0.524891, 0.038428, 0.441921,
0.927511, 0.556332, 0.243668, 0.565939, 0.265502,
0.122271, 0.275983, 0.60786, 0.670742, 0.565939,
0.117031, 0.117031, 0.001747, 0.148472, 0.038428,
0.50393, 0.49607, 0.148472, 0.275983, 0.191266,
0.254148, 0.430568, 0.198253, 0.323144, 0.29869,
0.344978, 0.524891, 0.323144, 0.344978, 0.28821,
0.441921, 0.127511, 0.31179, 0.254148, 0, 0.001747,
0.243668, 0.281223, 0.281223, 0.427948, 0.548472,
0.927511, 0.417467, 0.282969, 0.367686, 0.198253,
0.572926, 0.29869, 0.570306, 0.183406, 0.310044,
1, 1, 0.60786, 0, 0.282969, 0.349345, 0.521106,
0.430568, 0.127511, 0.50393, 0.367686, 0.310044,
0.556332, 0.670742, 0.30393, 0.548472, 0.193886,
0.349345, 0.122271, 0.193886, 0.265502, 0.537991,
0.165065, 0.191266])
y_train = np.array([0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0,
1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0,
1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1,
0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1,
0, 0, 1, 0, 0, 0, 0])
X_test = np.array((0.572926, 0.521106, 0.49607, 0.570306, 0.645415,
0.125764, 0.448908, 0.30393, 0.183406, 0.537991))
y_test = np.array((1, 1, 1, 0, 0, 0, 1, 1, 0, 0))
# Instantiate model and set parameters
clf = RandomForestClassifier()
clf.set_params(n_estimators=500, criterion='gini', max_features='sqrt')
# Note: reshape is because RF requires column vector format, # but
default NumPy is row
clf.fit(X_train.reshape(-1, 1), y_train)
pred = clf.predict(X_test.reshape(-1, 1))
# sort by feature value for comparison
o = np.argsort(X_test)
print('Example#\tX\t\t\tY_test\tY_true')
for i in o:
print('%d\t\t\t%f\t%d\t%d' % (i, X_test[i], y_test[i], pred[i]))
Что затем возвращается:
Example# X Y_test Y_true
5 0.125764 0 0
8 0.183406 0 0
7 0.303930 1 1
6 0.448908 1 1
2 0.496070 1 1
1 0.521106 1 1
9 0.537991 0 0
3 0.570306 0 0
0 0.572926 1 1
4 0.645415 0 0
Как модель RF с одной функцией может различать эти примеры? Что-то не так? Я просмотрел конфигурацию классификатора и еще много чего и не нашел никаких проблем. Я подумал, что, возможно, это проблема переоснащения (однако я делаю 10-кратную перекрестную проверку, так что это кажется менее вероятным), но затем я наткнулся на эту цитату на официальной веб-странице классификации случайных лесов: «Случайные леса действительно не переобучать. Вы можете запустить столько деревьев, сколько захотите ». (https://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm#remarks)
When only a single feature is used for binary classification, RF should only be able to discriminate between examples by setting an absolute threshold for positive/negative identification, right?
Каждый ветвь может различать только один порог, но каждое дерево построено из нескольких ветвей. Если X-пространство может быть разделено на несколько интервалов, так что каждый интервал имеет одно и то же значение y, тогда, пока классификатор имеет достаточно данных для получения границ этих интервалов, он сможет предсказать набор тестов. Однако я заметил, что ваш «тестовый» набор, кажется, является подмножеством вашего набора поездов, что противоречит цели наличия тестового набора. Конечно, если вы протестируете его на данных, на которых тренировались, точность будет высокой. Попробуйте отсортировать данные по значению X, а затем взять значения X, которых нет в вашем обучающем наборе, но которые находятся между двумя соседними значениями X_train, которые имеют разные значения y. Например, x = 0,001. Вы должны увидеть падение точности.
@CuChemist SVM предназначен для случаев, когда существует один порог является. Они плохо работают, когда граница сложная, особенно без каких-либо модификаций на основе данных.
Спасибо за разъяснения! На самом деле поезд и набор тестов не являются подмножествами друг друга, однако есть примеры, которые имеют одинаковую ценность функции. Пример, который я привел, взят из первого разделения поездов / тестов для 10-кратной перекрестной проверки (каждая новая модель создавала экземпляры). Одна вещь, которую я должен был добавить, - это то, что когда я выполняю ту же задачу с помощью SVM, производительность немного хуже, чем случайно. Так что я не могу понять, почему производительность между RF и SVM будет такой разной? Очевидно, это неправильно, но я не могу найти проблему.