Вопрос или проблема
У меня есть набор данных, в котором есть колонка цен, колонка дат и различные другие колонки с числовыми и категориальными значениями. Я хотел бы найти выбросы цен на основе всех колонок в наборе данных, и для этого я решил использовать метод изоляционного леса. Однако у меня вопрос: как найти выбросы цен с помощью метода изоляционного леса?
В качестве примера у меня есть 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
. Вы могли бы провести некоторый описательный анализ каждой категории, чтобы проверить, насколько схожей является распределение для каждой категории.
У вас могут быть некоторые альтернативы:
-
Рассмотреть проблему как обнаружение аномалий во временных рядах, где у вас будут исторические цены с течением времени, поэтому вы будете включать только
PRICE
в вашу модель. -
Если у вас достаточно данных для каждой категории, вы могли бы натренировать независимую модель обнаружения аномалий для каждой категории. Таким образом, на этапе интакции вы сначала проверите категорию нового пункта, а затем примените соответствующую модель.
Надеюсь, это поможет!
Ответ или решение
Для нахождения аномалий в ценах, основываясь на вашем датасете с различными числовыми и категориальными признаками, вы действительно можете использовать метод 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. Обучение модели на всех данных
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 может быть эффективным для обнаружения аномалий, но помните о важности предварительного анализа данных и их подготовки. Обучение разных моделей для каждой категории может повысить точность выявления аномалий. Если у вас есть достаточно данных, этот подход имеет смысл.
Если у вас есть дальнейшие вопросы по этой теме, не стесняйтесь спрашивать. Удачи в анализе вашего датасета!