Вопрос или проблема
Ниже приведен мой код, который берет диапазон чисел и создает новый столбец label, содержащий либо -1
, либо 1
.
Если число больше 14000
, мы маркируем его как -1 (выброс). Если число меньше 14000
, мы маркируем его как 1 (нормальное значение).
## Здесь я просто импортирую все библиотеки и импортирую столбец с моим набором данных
## Да, я пытаюсь найти аномалии, используя только данные из одного столбца
df['label'] = [-1 if x >= 14000 else 1 for x in df['data_numbers']] # То, что я объяснил выше
data = df.drop('label', axis=1)
target = df['label']
outliers = df[df['label'] == -1]
outliers = outliers.drop('label', axis=1)
from sklearn.model_selection import train_test_split
train_data, test_data, train_target, test_target = train_test_split(data, target, train_size=0.8)
train_data.shape
nu = outliers.shape[0] / target.shape[0]
print("nu", nu)
model = svm.OneClassSVM(nu=nu, kernel="rbf", gamma=0.00005)
model.fit(train_data)
from sklearn import metrics
preds = model.predict(train_data)
targs = train_target
print("accuracy: ", metrics.accuracy_score(targs, preds))
print("precision: ", metrics.precision_score(targs, preds))
print("recall: ", metrics.recall_score(targs, preds))
print("f1: ", metrics.f1_score(targs, preds))
print("area under curve (auc): ", metrics.roc_auc_score(targs, preds))
train_preds = preds
preds = model.predict(test_data)
targs = test_target
print("accuracy: ", metrics.accuracy_score(targs, preds))
print("precision: ", metrics.precision_score(targs, preds))
print("recall: ", metrics.recall_score(targs, preds))
print("f1: ", metrics.f1_score(targs, preds))
print("area under curve (auc): ", metrics.roc_auc_score(targs, preds))
test_preds = preds
from mlxtend.plotting import plot_decision_regions
# так как используется rbf svm, рисуется много границ решений, в отличие от одного в линейной SVM
# верхние центральные точки синими квадратами являются выбросами, в то время как внизу они оранжевые треугольники (нормальные значения)
plot_decision_regions(np.array(train_data), np.array(train_target), model)
plt.show()
Вывод из тренировочных данных
accuracy: 0.9050484526414505
precision: 0.9974137931034482
recall: 0.907095256762054
f1: 0.9501129131595154
area under curve (auc): 0.5876939698444417
Вывод из тестовых данных
accuracy: 0.9043451078462019
precision: 1.0
recall: 0.9040752351097179
f1: 0.9496213368455713
area under curve (auc): 0.9520376175548589
Мой график, кажется, имеет так много линий разделения, я думал, что будет только одна, которая отличает выбросы от нормальных данных.
OneClassSVM — это несупервизируемый алгоритм, который должен обучаться распределению нормальных данных. Это означает, что алгоритм будет моделировать границы областей высокой вероятности для ваших точек данных.
Даже если вы знаете, какие точки являются выбросами, SVM будет знать только то, что доля выбросов примерно равна nu, поэтому предел 14000 вовсе не является интуитивно понятным с точки зрения распределения.
Что делает SVM, объясняя ваши множественные линии:
-
Если у вас есть дыра в том, что вы считаете “зоной нормы” — например, у вас нет точек данных между 2560 и 2985 — SVM может решить, что это область низкой вероятности для вашего распределения, и, следовательно, построить два вектора, чтобы исключить ее из изученного нормального распределения.
-
Наоборот, если у вас есть несколько точек, сосредоточенных вместе выше 14000, поскольку SVM не имеет представления о том, что это зона аномалии, он может обнаружить зону высокой вероятности для выбора из данных и построить два вектора, чтобы включить ее в изученное нормальное распределение.
Теперь, относительно ваших метрик:
-
Вероятно, у вас есть несбалансированный набор данных, так как мы говорим об обнаружении аномалий (иначе это не имеет смысла!), поэтому вы не должны использовать глобальную точность здесь, потому что это вводит в заблуждение.
-
Есть одна вещь, которая должна вас насторожить: тренировочная AUC очень низкая, в то время как тестовая AUC очень высокая, и это ненормально. Таким образом ваше алгоритм плохо обучается целевому нормальному распределению.
Высокая тестовая AUC может быть объяснена, но сначала давайте используем некоторые обозначения:
- Реальное нормальное распределение данных будет называться “целевое нормальное распределение”, в том смысле, что вы хотите его изучить. Это интервал [0;14000[
- Реальная аномальная зона (невозможно говорить о распределении в этом контексте) будет называться “целевой аномальной зоной”. Это интервал [14000;+бесконечность[
- Изученное нормальное распределение будет называться “изученное нормальное распределение”, очевидно.
- Изученная аномальная зона будет называться “изученная аномальная зона”
Таким образом, изученное распределение состоит из небольших кластеров вокруг областей более высокой плотности тренировочных данных. Поскольку у вас (предположительно) мало выбросов и много нормальных точек, изученное распределение все еще хорошо пересекается с целевым нормальным распределением, но не с целевой аномальной зоной, где только несколько областей будут принадлежать изученному нормальному распределению. Вы можете проверить это на своем графике: в целевой аномальной зоне есть только несколько векторов.
Теперь, применяя алгоритм к тестовому набору, маловероятно, что точка из тестового набора в целевой аномальной зоне попадет в пересечение изученного нормального распределения и целевой аномальной зоны, потому что это пересечение очень мало. Но это связано только с малым числом точек данных в этой аномальной зоне, а не с успешным процессом обучения. Поэтому эти точки по-прежнему будут помечены как аномалии, и вы получите вводящий в заблуждение высокий показатель AUC.
Наоборот, целевое нормальное распределение и изученное нормальное распределение правильно пересекаются, потому что было больше точек данных для обучения. Поэтому большинство нормальных точек в тестовом наборе классифицируется правильно.
В общем, ваш алгоритм изучает совершенно другое распределение, чем то, что вы ожидали. Вы можете попробовать использовать более высокое значение gamma для сглаживания ядра. но, вероятно, не удастся избежать классификации областей большей плотности выше 14000 как нормальных точек данных. Поэтому следите за тренированной AUC!
Было бы очень интересно исследовать эти утверждения с графиками, вы могли бы, например, изобразить зону [14000; +бесконечность[, выделить границы функции решения и изобразить данные наборов тренировочных и тестовых точек. Вы должны получить подтверждение того, что я сказал выше (я сделаю это позже и добавлю графики, если найду время!)
Если вы знаете границу решения (14000), зачем вам нужен алгоритм машинного обучения? Вы можете применить условие if на это. Алгоритмы машинного обучения разработаны для нахождения границы решения? Если вы действительно хотите экспериментировать с этим набором данных, то вам следует знать, какой тип классификации вы выполняете? Из искусственно размеченного набора данных я вижу, что у вас две кластеры (1, -1). Но вы используете OneClassSVM. Это ошибка! Просто удалите OneClassSVM и используйте обычную линейную svm. И нет необходимости использовать ‘rbf’. ‘rbf’ предназначен для нелинейного разделения. Ваша граница классификации является линейной. Это просто линия, идущая через 14000.
from sklearn import svm
clf = svm.SVC()
clf.fit(train_data, train_target)
Примечание: Если вы хотите обнаружить выбросы, то не нужно маркировать данные по условию (< 14000). Позвольте OneClassSVM находить выбросы, анализируя только тренировочные признаки.
.
Ответ или решение
Для IT-эксперта, разбирающегося в методах машинного обучения, особенно в алгоритмах Векторной машины опорных векторов (SVM), важно понимать, почему модель с RBF (гауссовым ядром) может генерировать множество разделяющих линий. Это важный аспект, который можно объяснить через особенности работы SVM и принципы классификации аномалий.
Обзор проблемы
Предположим, что ваш датасет состоит из чисел, которые вы делите на две категории: "нормальные" (метка 1) и "аномальные" (метка -1), в зависимости от числа 14000. Однако, используя алгоритм OneClassSVM с гауссовым ядром, вы наблюдаете множество разделяющих линий, что может вызвать недоумение.
Понимание алгоритма OneClassSVM
OneClassSVM — это метод независимого обучения, который учится определять нормальное распределение данных. Он не принимает во внимание ярлыки аномалий, которые мы задаем, потому что изначально предназначен для выявления аномалий на основе изучения характеристик нормальных данных. Эта особенность может создавать множество "разделяющих линий" из-за следующих факторов:
-
Неравномерность распределения данных: Если в данных есть пробелы, например, от 2560 до 2985, SVM может интерпретировать это как области низкой вероятности и создавать дополнительные векторы для их исключения из нормального распределения.
-
Высокая плотность кластеров: Если выше 14000 есть области с высокой плотностью точек, SVM может ошибочно включить их в "нормальное" распределение.
Анализ метрик и их объяснение
Ваши метрики, такие как точность, прецизия и AUC, показывают аномалии в процессе обучения. Низкий AUC для обучающей выборки и высокий для тестовой могут обозначать переобучение. Это показывает, что ваша модель плохо изучает целевое нормальное распределение. Высокий показатель AUC на тестовой выборке может быть ложным, из-за чего тестовые аномальные точки не попадают в малое множество обученных нормальных распределений.
Рекомендации
-
Уточните подход к проблеме: Если ваше намерение состоит в чётком разделении двух классов, которые вы уже знаете, используйте обычный метод классификации SVM. У вас линейная граница, поэтому использование ядра RBF может быть излишним.
-
Используйте линейный SVM для бинарной классификации:
from sklearn import svm clf = svm.SVC(kernel='linear') clf.fit(train_data, train_target)
-
Аномалия без предварительной метки: Если цель — выявить аномалии, не задавайте метку (меньше 14000) условно, а дайте OneClassSVM возможность самостоятельно определять аномалии на основе особенностей тренировочных данных.
Эти рекомендации помогут сделать вашу модель более точной и соответствующей реальным условиям задачи. Успехов в внедрении и оптимизации ваших решений для анализа данных и классификации!