Что такое метрика Information Value (IV)?

Ответ

Information Value (IV) — это метрика, используемая в основном в кредитном скоринге и задачах бинарной классификации для оценки прогнозной силы отдельного признака. Она количественно измеряет, насколько хорошо признак разделяет два класса (например, «дефолт» и «не дефолт»).

Расчет IV основан на Weight of Evidence (WOE):

  1. Признак разбивается на интервалы (бины).
  2. Для каждого бина вычисляется WOE: WOE_i = ln( (% Good_i) / (% Bad_i) ) = ln( (Good_i / Total_Good) / (Bad_i / Total_Bad) )
    • Good_i — количество «хороших» наблюдений в бине i.
    • Bad_i — количество «плохих» наблюдений в бине i.
  3. Затем вычисляется IV как сумма по всем бинам: IV = Σ ( (% Good_i - % Bad_i) * WOE_i )

Интерпретация IV:

  • < 0.02: Непредсказующая сила (признак бесполезен).
  • 0.02 – 0.1: Слабая предсказательная сила.
  • 0.1 – 0.3: Средняя предсказательная сила.
  • > 0.3: Сильная предсказательная сила.

Практический пример на Python:

import pandas as pd
import numpy as np

# Создадим синтетические данные
np.random.seed(42)
data = pd.DataFrame({
    'age_group': np.random.choice(['18-25', '26-35', '36-50', '50+'], size=500),
    'default': np.random.choice([0, 1], size=500, p=[0.85, 0.15]) # 15% дефолтов
})

def calculate_iv(df, feature, target):
    """Вычисляет IV для категориального признака."""
    # Группируем данные
    grouped = df.groupby(feature)[target].agg(['count', 'sum'])
    grouped.columns = ['total', 'bad']
    grouped['good'] = grouped['total'] - grouped['bad']

    # Вычисляем доли
    total_good = grouped['good'].sum()
    total_bad = grouped['bad'].sum()
    grouped['pct_good'] = grouped['good'] / total_good
    grouped['pct_bad'] = grouped['bad'] / total_bad

    # Вычисляем WOE и IV
    grouped['woe'] = np.log(grouped['pct_good'] / grouped['pct_bad'])
    grouped['iv_component'] = (grouped['pct_good'] - grouped['pct_bad']) * grouped['woe']
    iv = grouped['iv_component'].sum()

    return iv, grouped

iv_value, iv_table = calculate_iv(data, 'age_group', 'default')
print(f"Information Value для 'age_group': {iv_value:.4f}")
print("nДетальная таблица:")
print(iv_table[['total', 'bad', 'good', 'woe', 'iv_component']])

Важно: Высокий IV (>0.5) может указывать на «переобученный» признак, который слишком хорошо разделяет выборку и может не работать на новых данных.

Ответ 18+ 🔞

А, ну это про IV, да? Эту штуку в кредитках используют, чтобы понять, какой признак реально предсказывает, накроется ли клиент медным тазом или нет. По сути, это как измерить, насколько хитрая жопа у твоего признака — может ли он отличить хорошего заёмщика от распиздяя.

Считается через какую-то свою магию, Weight of Evidence, короче. Берёшь признак, делишь на группы — скажем, возраст: молокососы, взрослые, старики. Потом для каждой кучки смотришь, сколько там «хороших» (платят) и «плохих» (съебали в закат). Дальше начинается математика, ёпта. Считаешь логарифм отношения долей — это и есть WOE. А потом уже из этих WOE как из кирпичиков собираешь сам IV.

Как понять, что получилось?

  • Меньше 0.02: Признак — полный ноль, манда с ушами. От него толку, как от козла молока.
  • 0.02 – 0.1: Слабоват, но может в компании других признаков потянуть.
  • 0.1 – 0.3: Вот это уже дело! Признак с характером, средняя сила.
  • Больше 0.3: О, да тут монстр! Сила предсказания — просто овердохуища.

Но и тут есть подвох, чувак. Если IV зашкаливает, больше 0.5, то подозрение ебать чувствую. Скорее всего, признак переобучился на исторических данных и на новых клиентах сделает пиздопроебибну, наобещав с три короба.

Вот, смотри, как на питоне это выглядит, там всё по полочкам:

import pandas as pd
import numpy as np

# Накидаем данных от балды
np.random.seed(42)
data = pd.DataFrame({
    'age_group': np.random.choice(['18-25', '26-35', '36-50', '50+'], size=500),
    'default': np.random.choice([0, 1], size=500, p=[0.85, 0.15]) # 15% дефолтов
})

def calculate_iv(df, feature, target):
    """Вычисляет IV для категориального признака."""
    # Группируем данные
    grouped = df.groupby(feature)[target].agg(['count', 'sum'])
    grouped.columns = ['total', 'bad']
    grouped['good'] = grouped['total'] - grouped['bad']

    # Вычисляем доли
    total_good = grouped['good'].sum()
    total_bad = grouped['bad'].sum()
    grouped['pct_good'] = grouped['good'] / total_good
    grouped['pct_bad'] = grouped['bad'] / total_bad

    # Вычисляем WOE и IV
    grouped['woe'] = np.log(grouped['pct_good'] / grouped['pct_bad'])
    grouped['iv_component'] = (grouped['pct_good'] - grouped['pct_bad']) * grouped['woe']
    iv = grouped['iv_component'].sum()

    return iv, grouped

iv_value, iv_table = calculate_iv(data, 'age_group', 'default')
print(f"Information Value для 'age_group': {iv_value:.4f}")
print("nДетальная таблица:")
print(iv_table[['total', 'bad', 'good', 'woe', 'iv_component']])

Запустишь — и сразу видно, кто есть кто. Главное, не гонись за астрономическими значениями, а то модель потом, как та мартышлюшка, будет только на старых данных умной выглядеть.