Как применить модель на основе дерева с числовыми и категориальными значениями для выявления выбросов

Вопрос или проблема

У меня есть набор данных, в котором есть колонка цен, колонка дат и различные другие колонки с числовыми и категориальными значениями. Я хотел бы найти выбросы цен на основе всех колонок в наборе данных, и для этого я решил использовать метод изоляционного леса. Однако у меня вопрос: как найти выбросы цен с помощью метода изоляционного леса?

В качестве примера у меня есть dataframe iso_df с 5 колонками: PRICE – это колонка цен, для которой я хочу найти выбросы, RIV_VALUES – вторая колонка цен (но я не хочу находить выбросы для нее), ITEM_GROUP – это категориальная колонка со значениями, такими как A, B, C и т.д., а YEAR_MONTH – это колонка, содержащая комбинации года и месяца (например, 2020-01, 2020-02 и т.д.), так что примерный dataframe выглядит следующим образом:

  PRICE    |   RIV_VALUES   |  ITEM_GROUP  |    YEAR_MONTH
---------------------------------------------------------------
    2.2    |      4.7       |       A      |     2020-01
    7.9    |      3.9       |       A      |     2020-02  
     2     |      1.2       |       B      |     2020-01
    10.2   |      8.9       |       A      |     2020-03
    25.2   |      2.4       |       D      |     2020-02

то есть

iso_df = iso_df[['PRICE', "RIV_VALUES", "ITEM_GROUP", 'YEAR_MONTH']]

После этого я использую label_encoder из пакета scikit-learn, чтобы преобразовать колонки ITEM_GROUP и YEAR_MONTH в порядковые числовые значения.

Когда это будет готово, моя идея заключалась в том, чтобы сделать что-то вроде этого:

from sklearn.ensemble import IsolationForest

clf = IsolationForest(n_estimators = 10, max_samples="auto", contamination=float(.05), max_features=1.0, bootstrap=False, n_jobs=-1, verbose=0)
clf_prediction = clf.fit_predict(iso_df)

Однако мне это кажется неправильным – так как я пытаюсь найти PRICES, которые являются выбросами, следует ли мне все это отобразить в модели так? Или стоит найти способ более четко разделить их? Или, может быть, есть лучшая модель для этого (помимо обычных подходов с доверительными интервалами или ящиками)? Любая помощь будет оценена, заранее спасибо!

Имейте в виду, что у вас есть уровневая характеристика, ITEM_GROUP. Это подразумевает, что то, что может считаться выбросом в категории A, может не быть таковым в категории B или C. Вы могли бы провести некоторый описательный анализ каждой категории, чтобы проверить, насколько схожей является распределение для каждой категории.

У вас могут быть некоторые альтернативы:

  1. Рассмотреть проблему как обнаружение аномалий во временных рядах, где у вас будут исторические цены с течением времени, поэтому вы будете включать только PRICE в вашу модель.

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

Надеюсь, это поможет!

Ответ или решение

Для нахождения аномалий в ценах, основываясь на вашем датасете с различными числовыми и категориальными признаками, вы действительно можете использовать метод Isolation Forest. Однако важно корректно учитывать категориальные признаки и их влияние на определение аномалий. Ниже приведены шаги, которые помогут вам в этой задаче.

Шаг 1: Подготовка данных

Начнем с того, что вам нужно будет подготовить данные. Вы упомянули, что хотите использовать только три столбца: PRICE, ITEM_GROUP и YEAR_MONTH, исключив RIV_VALUES. Убедитесь, что вы применяете кодирование для категориальных значений.

import pandas as pd
from sklearn.preprocessing import LabelEncoder

# Ваш сохранённый dataframe
iso_df = iso_df[['PRICE', "ITEM_GROUP", 'YEAR_MONTH']]

# Кодирование категориальных переменных
label_encoder = LabelEncoder()
iso_df['ITEM_GROUP'] = label_encoder.fit_transform(iso_df['ITEM_GROUP'])
iso_df['YEAR_MONTH'] = pd.to_datetime(iso_df['YEAR_MONTH']).dt.to_period('M').astype('int')  # Преобразуем в числики

# Теперь iso_df готов к использованию

Шаг 2: Обучение модели Isolation Forest

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

  1. Обучение модели на всех данных сразу: Этот метод подразумевает, что аномалии могут быть глобальными.
  2. Обучение отдельных моделей для каждой группы: Это более продвинутый подход, который позволяет учитывать различия в распределении цен между группами.

Вот пример кода для обоих подходов:

1. Обучение модели на всех данных

from sklearn.ensemble import IsolationForest

# Создаем модель
clf = IsolationForest(n_estimators=100, contamination=0.05, random_state=42)

# Обучение модели
clf.fit(iso_df)

# Предсказания
iso_df['OUTLIER'] = clf.predict(iso_df)
# Замена меток -1 (аномалия) и 1 (нормальный)
iso_df['OUTLIER'] = iso_df['OUTLIER'].map({-1: 1, 1: 0})

# Посмотрим, сколько аномалий мы нашли
outliers = iso_df[iso_df['OUTLIER'] == 1]
print(outliers)

2. Обучение модели для каждой группы

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

outliers = []

for item_group in iso_df['ITEM_GROUP'].unique():
    group_data = iso_df[iso_df['ITEM_GROUP'] == item_group]
    clf = IsolationForest(n_estimators=100, contamination=0.05, random_state=42)
    clf.fit(group_data)

    # Предсказания
    group_data['OUTLIER'] = clf.predict(group_data)
    group_data['OUTLIER'] = group_data['OUTLIER'].map({-1: 1, 1: 0})

    outliers.append(group_data[group_data['OUTLIER'] == 1])

# Объединение результатов
outliers_df = pd.concat(outliers)
print(outliers_df)

Шаг 3: Визуализация и анализ

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

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 6))
plt.scatter(iso_df['YEAR_MONTH'], iso_df['PRICE'], c=iso_df['OUTLIER'], cmap='coolwarm')
plt.title('Цены и аномалии')
plt.xlabel('Год и месяц')
plt.ylabel('Цена')
plt.show()

Выводы

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

Если у вас есть дальнейшие вопросы по этой теме, не стесняйтесь спрашивать. Удачи в анализе вашего датасета!

Оцените материал
Добавить комментарий

Капча загружается...