#python #tensorflow #keras #imbalanced-data
Вопрос:
Я даже изо всех сил пытаюсь кратко, но ясно объяснить свой вопрос, поэтому я приложу все усилия, чтобы предоставить некоторую справочную информацию, прежде чем перейти непосредственно к вопросу.
Бракграунд
У меня очень несбалансированный набор данных, состоящий из 3 классов, 2 из которых являются классами меньшинств, и мне интересно их классифицировать.
Набор данных состоит из разреженных объектов и выглядит следующим образом:
RA0 RA1 RA2 RA3 RA4 RA5 RA6 RA7 RA8 RA9 ... RB1 RB2 RB3 RB4 RB5 RB6 RB7 RB8 RB9 label
-------------------------------------------------------------------------------------
0.0 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 2
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1
0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 1
Этот набор данных очень несбалансирован, так как значения для меток следующие:
df.label.value_counts()/len(df)
>0 0.944352
>1 0.028622
>2 0.027025
RAX
Объекты соответствуют метке 1, а RBX
объекты соответствуют метке 2. Почему эти две метки «смешаны» с этими двумя различными типами функций? Исходные данные представляют собой временные ряды, а метки представляют «состояние» временных рядов.
Итак, я снова и снова пробовал методы выборки, чтобы попытаться «сбалансировать» набор данных, но в данном случае, похоже, лучше работало то, что я пытался найти class_weights
метки с помощью поиска по сетке.
Я попытался выполнить поиск по сетке, используя roc_auc
оценку, а затем обучение нейронной сети для классификации, но я борюсь с частью показателей. Модель выглядит следующим образом:
import tensorflow as tf
def seq_model(n_features=20,init_neurons=170,decay=0.25,layers=3,lr=0.0001,activation1 = 'relu',activation2='relu'):
model = Sequential()
model.add(Dense(n_features, input_dim=n_features, activation=activation1))
actual_neurons = init_neurons
for i in range(layers):
actual_neurons = int(actual_neurons*(1-decay*i))
if actual_neurons <=0:
break
model.add(Dense(actual_neurons,activation = activation2))
model.add(Dense(3,activation = 'softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=[tf.keras.metrics.AUC()])
return model
И после запуска a GridSearch
я понял , что лучший вес класса для этого набора данных был {0: 1, 1: 95, 2: 95}
. Затем, после выполнения GridSearch
я обучил модель, но я заметил, что Keras
она больше не поддерживает roc_auc
кривую для показателей (например accuracy
), поэтому, прочитав другие вопросы и ответы в SO, я пришел к следующему:
class RocCallBack(Callback):
def __init__(self,training_data,validation_data):
self.x = training_data[0]
self.y = training_data[1]
self.x_val = validation_data[0]
self.y_val = validation_data[1]
def on_train_begin(self,logs={}):
return
def on_train_end(self, logs={}):
return
def on_epoch_begin(self,epoch,logs={}):
return
def on_epoch_end(self,epoch,logs={}):
y_pred_train = self.model.predict_proba(self.x)
roc_train = roc_auc_score(self.y,y_pred_train)
y_pred_val = self.model.predict_proba(self.x_val)
roc_val = roc_auc_score(self.y_val,y_pred_val)
print('rroc-auc_train: %s - roc-auc_val: %s' % (str(round(roc_train,4)),str(round(roc_val,4))),end=100*' ' 'n')
return
def on_batch_begin(self, batch, logs={}):
return
def on_batch_end(self, batch, logs={}):
return
roc = RocCallBack(training_data=(x_train.values,y_train2),
validation_data = (x_test.values,y_test2))
early_stopping = EarlyStopping(patience = 100,verbose = True,monitor='val_auc',restore_best_weights=True)
check_point = ModelCheckpoint('classifier.hdf5',verbose=1,save_best_only=True,monitor = 'val_auc')
y_train2 = to_categorical(y_train)
y_test2 = to_categorical(y_test)
history = model.fit(x_train.values,y_train2,
epochs = 50000,
batch_size = 24,
validation_data=(x_test.values,y_test2),
shuffle = False,
class_weight={0: 1, 1: 95, 2: 95},
callbacks=[roc,early_stopping,check_point])
Вопросы:
а) Во время обучения я заметил, что модель пытается минимизировать val_auc
значение, чего я не ожидал, потому что думал, что идея заключалась в том, чтобы максимизировать его. Это нормально или я допустил какую-то ошибку в процессе?
б) Для оптимизации roc_auc
(и, следовательно, повышения точности, верно?) правильно ли вводить tf.keras.metrics.AUC()
модель в качестве метрики? Если нет, то как это следует сделать, чтобы добиться хорошей производительности?
в) При нахождении оптимальных весов для классов я не должен использовать accuracy
их в качестве метрики, верно? Является roc_auc
ли лучшая метрика, которую я мог бы использовать для этих случаев?
Мне действительно жаль, если это был длинный пост, но я все еще учусь работать с наборами данных такого типа, и любая помощь будет признательна. Я также могу предоставить любую другую информацию, если это необходимо.
Комментарии:
1. Стандартные способы работы с несбалансированными наборами данных-это подвыборка, передискретизация или синтетические выборки. Для несбалансированных вы правы, точность-это плохо. Используйте другую метрику, учитывающую стоимость
2. @IanQuah Спасибо за ваш ответ. Я пробовал под и над выборкой, но не получил очень хороших результатов. Я действительно попробовал их с точностью в качестве метрики. Или я должен использовать, например, над выборкой вес класса roc auc? Какой еще показатель вы бы мне порекомендовали?
3. Точность — плохой показатель. Если у вас 99% класса А, и вы всегда угадываете «А», ваша точность составляет 99%, но это не очень хороший результат. Я бы просто погуглил несбалансированные потери в классе