Керас: что на самом деле пытается сбалансировать class_weight?

Мои данные имеют экстремальный дисбаланс классов. Около 99,99% образцов являются отрицательными; позитивы (примерно) поровну поделены между тремя другими классами. Я думаю, что модели, которые я тренирую, просто предсказывают класс большинства в основном все время. По этой причине я пытаюсь взвесить классы.

модель

model = Sequential()

#Layer 1
model.add(Conv1D( {{choice([32, 64, 90, 128])}}, {{choice([3, 4, 5, 6, 8])}}, activation='relu', kernel_initializer=kernel_initializer, input_shape=X_train.shape[1:]))
model.add(BatchNormalization())

#Layer 2
model.add(Conv1D({{choice([32, 64, 90, 128])}}, {{choice([3, 4, 5, 6])}}, activation='relu',kernel_initializer=kernel_initializer))
model.add(Dropout({{uniform(0, 0.9)}}))

#Flatten
model.add(Flatten())

#Output
model.add(Dense(4, activation='softmax'))

(The {{...}} для использования с Hyperas.)

Как я пытался взвесить это

\1. С помощью class_weight в model.fit()

model.fit(X_train, Y_train, batch_size=64, epochs=10, verbose=2, validation_data=(X_test, Y_test), class_weight={0: 9999, 1:9999, 2: 9999, 3:1})

\2. С помощью class_weight в model.fit() с sklearncompute_class_weight()

model.fit(..., class_weight=class_weight.compute_class_weight("balanced", np.unique(Y_train), Y_train)

\3. С пользовательской функцией потери

from keras import backend as K
def custom_loss(weights):
    #gist.github.com/wassname/ce364fddfc8a025bfab4348cf5de852d

    def loss(Y_true, Y_pred):
        Y_pred /= K.sum(Y_pred, axis=-1, keepdims=True)
        Y_pred = K.clip(Y_pred, K.epsilon(), 1 - K.epsilon())

        loss = Y_true * K.log(Y_pred) * weights
        loss = -K.sum(loss, -1)
        return loss

    return loss

extreme_weights = np.array([9999, 9999, 9999, 1])
model.compile(loss=custom_loss(extreme_weights),
            metrics=['accuracy'],
            optimizer={{choice(['rmsprop', 'adam', 'sgd','Adagrad','Adadelta'])}}
            )

#(then fit *without* class_weight)

Результаты

Бедные. Точность для всех классов ~.99и несбалансированная точность для всех классов ~.5, Но более значимые метрики, такие как auPRC, рассказывают другую историю. AuPRC почти 1 для большинства класса, и почти 0 что касается прочего.

Это как Keras уравновешивает классы? Это просто гарантирует, что точность одинакова для всех - или метрики должны быть одинаковыми или сопоставимыми? Или я неправильно указываю вес?

1 ответ

Керас использует весовые коэффициенты во время тренировок, но точность не отражает этого. Точность рассчитывается для всех образцов независимо от веса между классами. Это потому, что вы используете метрику "точность" в compile(). Вы можете определить пользовательскую и более точную взвешенную точность и использовать ее или использовать метрики sklearn (например, f1_score(), которая может быть "двоичной", "взвешенной" и т. Д.).

Пример:

def macro_f1(y_true, y_pred):
     return f1_score(y_true, y_pred, average='macro')


model.compile(loss=custom_loss(extreme_weights),
        metrics=['accuracy', macro_f1],
        optimizer={{choice(['rmsprop', 'adam', 'sgd','Adagrad','Adadelta'])}}
        )
Другие вопросы по тегам