Зациклился на 0.85 AUC

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

Я новичок в этой области и учусь, решая небольшие задачи. Я работаю с нейронной сетью на несбалансированном наборе данных, но застрял на AUC 0.85, и, похоже, это не улучшается. На аналогичном наборе данных с lgbm я получаю 0.97. Также за 100 испытаний optuna AUC составляет около 0.84-0.85. Не знаю… это кажется странным. Является ли хорошим вариантом использовать “сбалансированный” как вес класса для несбалансированного набора данных?

def objective_nn(trial, X_train_tuning, y_train_tuning, class_weight_dict):
    num_layers = trial.suggest_int('num_layers', 2, 5)
    units = trial.suggest_int('units', 128, 512)
    dropout_rate_input = trial.suggest_float('dropout_rate_input', 0.1, 0.3)
    dropout_rate_hidden = trial.suggest_float('dropout_rate_hidden', 0.1, 0.3)
    learning_rate = trial.suggest_float('learning_rate', 1e-4, 1e-3, log=True)
    activation = trial.suggest_categorical('activation', ['relu', 'swish'])
    optimizer_name = trial.suggest_categorical('optimizer', ['adam', 'adamw'])
    l2_reg = trial.suggest_float('l2_reg', 1e-4, 1e-2, log=True)
    batch_size = trial.suggest_categorical('batch_size', [16, 32])

    skf = StratifiedKFold(n_splits=3, shuffle=True, random_state=RANDOM_STATE)
    validation_aucs = []

    for fold_index, (train_index, valid_index) in enumerate(skf.split(X_train_tuning, y_train_tuning)):
        X_train_fold, X_valid_fold = X_train_tuning.iloc[train_index].reset_index(drop=True), X_train_tuning.iloc[valid_index].reset_index(drop=True)
        y_train_fold, y_valid_fold = y_train_tuning.iloc[train_index].reset_index(drop=True), y_train_tuning.iloc[valid_index].reset_index(drop=True)

        model = models.Sequential()
        model.add(layers.Input(shape=(X_train_fold.shape[1],)))
        model.add(layers.Dense(units, activation=activation, kernel_regularizer=regularizers.l2(l2_reg)))
        model.add(layers.BatchNormalization())
        model.add(layers.Dropout(dropout_rate_input))

        for _ in range(num_layers - 1):
            model.add(layers.Dense(units, activation=activation, kernel_regularizer=regularizers.l2(l2_reg)))
            model.add(layers.BatchNormalization())
            model.add(layers.Dropout(dropout_rate_hidden))

        model.add(layers.Dense(1, activation='sigmoid'))

        if optimizer_name == 'adam':
            optimizer = optimizers.Adam(learning_rate=learning_rate)
        elif optimizer_name == 'adamw':
            optimizer = optimizers.AdamW(learning_rate=learning_rate)


        model.compile(optimizer=optimizer, loss="binary_crossentropy", metrics=[tf.keras.metrics.AUC(name="auc")])

        # Коллбеки
        early_stopping = callbacks.EarlyStopping(monitor="val_auc", mode="max", patience=5, restore_best_weights=True)
        reduce_lr = callbacks.ReduceLROnPlateau(monitor="val_loss", mode="min", factor=0.5, patience=3, verbose=0)


        history = model.fit(
            X_train_fold, y_train_fold,
            validation_data=(X_valid_fold, y_valid_fold),
            epochs=50,
            batch_size=batch_size,
            class_weight=class_weight_dict,
            callbacks=[early_stopping, reduce_lr],
            verbose=0
        )

        val_auc = max(history.history['val_auc'])
        validation_aucs.append(val_auc)

    return np.mean(validation_aucs)

train_df = pd.read_csv(DATA_PATH, encoding='utf-8')
train_df.columns = train_df.columns.str.lower()

X = train_df.drop(columns=['isfraud'])
y = train_df['isfraud']

plot_dir="/content/plots"  
os.makedirs(plot_dir, exist_ok=True)

X = preprocess_data(X, MODE, DIR, SEED, plot_dir)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=TEST_SIZE, random_state=RANDOM_STATE, stratify=y)

tuning_subset_size = 0.2
X_train_tuning, _, y_train_tuning, _ = train_test_split(X_train, y_train, test_size=(1-tuning_subset_size), random_state=RANDOM_STATE, stratify=y_train)

class_weights = compute_class_weight(class_weight="balanced", classes=np.unique(y), y=y)
class_weight_dict = dict(enumerate(class_weights))

study = optuna.create_study(direction='maximize', study_name="maximize_auc")
study.optimize(lambda trial: objective_nn(trial, X_train_tuning, y_train_tuning, class_weight_dict), n_trials=N_TRIALS, n_jobs=40)

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

Выбор подхода для повышения AUC нейронной сети в условиях несбалансированных данных

В данной статье мы рассмотрим проблемы, связанные с застреванием на уровне AUC 0.85 при обучении нейронной сети на несбалансированном наборе данных, и предложим возможные пути их решения. Также мы проанализируем, почему результаты, полученные с помощью LightGBM, достигают AUC 0.97, и что можно сделать для улучшения модели нейронной сети.

1. Оценка текущего состояния модели

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

Ключевые моменты для анализа:

  • Гиперпараметры сети: Возможно, вам следует попробовать увеличивать или уменьшать количество единиц в слоях, а также количество слоев до тех пор, пока не появятся улучшения в AUC. Это также касается dropout rate и регуляризации L2. Некоторые комбинации могут быть слишком агрессивными или неэффективными.

  • Функции активации и оптимизаторы: Экспериментируйте с другими комбинациями активаций и оптимизаторов. Например, попробуйте использовать LeakyReLU или ELU в качестве альтернативы ReLU, поскольку они легче справляются с затухающим градиентом.

  • Классовые веса: Использование сбалансированных весов классов может оказаться полезным. Однако, стоит помнить, что проблема дисбаланса классов требует индивидуального подхода, и иногда применение сбалансированных весов может ухудшить общий результат.

2. Работа с несбалансированными данными

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

Рекомендации:

  • Переобучение или недообучение: Проверьте, не происходит ли переобучение модели. Так как AUC 0.85 дает представление о том, что модель, возможно, недостаточно сложна или переобучена. Следует проанализировать кривые обучения и в случае необходимости использовать более сложные архитектуры.

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

  • Смещение и подвыборка: Рассмотрите использование методов SMOTE или NearMiss для создания синтетических образцов меньшего класса или отбора образцов большего класса.

3. Перекрестная проверка и обучение

При настройке модели, вы используете StratifiedKFold для оценки AUC. Это хороший подход, однако важно убедиться, что каждая выборка на этапе кросс-валидации адекватно отражает распределение классов.

Рекомендации:

  • Увеличение количества фолдов: Попробуйте увеличить количество фолдов в кросс-валидации для более надежной оценки.

  • Ошибка обучения: Проверьте значения потери и AUC на этапе обучения и валидации. Если вы видите значительное расхождение, это может свидетельствовать о проблемах в обучении.

4. Применение альтернативных моделей

Использование LightGBM дает более высокие AUC-значения. Это не случайно. LightGBM широко используется для работы с несбалансированными данными благодаря встроенным методам. Возможно, стоит провести дополнительный анализ того, почему именно этот алгоритм обеспечивает лучшие результаты и взять это в расчет при доработке нейронной сети.

Заключение

Ваш процесс обучения нейронной сети на несбалансированных данных требует тщательного анализа и экспериментов. Улучшение AUC от 0.85 до более высоких значений возможно, но потребует времени и ресурсов. Рассматривайте различные варианты улучшения архитектуры, подходы к обработке данных и методы оценки, чтобы стремиться к более высокому уровню предсказуемости. Не стесняйтесь использовать и комбинировать различные инструменты и шаблоны, чтобы находить оптимальные решения.

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

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