Как исправить дисбаланс классов в диалоговых (текстовых) данных временных рядов? - PullRequest
1 голос
/ 05 мая 2020

У меня есть набор данных, который выглядит так:

df.head(5)


 data                                                     labels
0  [0.0009808844009380855, 0.0008974465127279559]             1
1  [0.0007158940267629654, 0.0008202958833774329]             3
2  [0.00040971929722210984, 0.000393972522972382]             3
3  [7.916243163372941e-05, 7.401835468434177e243]             3
4  [8.447556379936086e-05, 8.600626393842705e-05]             3

Столбец «данные» - это мой X, а метки - это y. В df 34890 строк. В каждом ряду по 2 поплавка. Данные представляют собой связку последовательного текста, и каждое наблюдение является представлением предложения. Всего 5 классов.

Я тренирую его на этом LSTM-коде:

data = df.data.values
labels = pd.get_dummies(df['labels']).values

X_train, X_test, y_train, y_test = train_test_split(data,labels, test_size = 0.10, random_state = 42)

X_train = X_train.reshape((X_train.shape[0],1,X_train.shape[1])) # shape = (31401, 1, 5)
X_test = X_test.reshape((X_test.shape[0],1,X_test.shape[1])) # shape = (3489, 1, 5)
### y_train shape =  (31401, 5)
### y_test shape =  (3489, 5)

### Bi_LSTM
Bi_LSTM = Sequential()
Bi_LSTM.add(layers.Bidirectional(layers.LSTM(32)))
Bi_LSTM.add(layers.Dropout(.5))
# Bi_LSTM.add(layers.Flatten())
Bi_LSTM.add(Dense(11, activation='softmax'))

def compile_and_fit(history):

    history.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])

    history = history.fit(X_train,
              y_train,
              epochs=30,
              batch_size=32,
              validation_data=(X_test, y_test))

    return history

LSTM_history = compile_and_fit(Bi_LSTM)

Модель обучается, но точность val фиксирована на уровне 53% для каждой эпохи. Я предполагаю, что это из-за моей проблемы с дисбалансом классов (1 класс занимает ~ 53% данных, остальные 4 в некоторой степени равномерно распределены по оставшимся 47%).

Как мне сбалансировать мои данные? Мне известны типичные методы избыточной / недостаточной выборки для данных, не относящихся к временным рядам, но я не могу использовать избыточную / недостаточную выборку, потому что это нарушит характер данных с последовательными временными рядами. Любой совет?

EDIT

Я пытаюсь использовать аргумент class_weight в Keras для решения этой проблемы. Я передаю этот dict в аргумент class_weight:

class_weights = {
    0: 1/len(df[df.label == 1]),
    1: 1/len(df[df.label == 2]),
    2: 1/len(df[df.label == 3]),
    3: 1/len(df[df.label == 4]),
    4: 1/len(df[df.label == 5]),
}

На чем я основываюсь на этой рекомендации:

https://stats.stackexchange.com/questions/342170/how-to-train-an-lstm-when-the-sequence-has-imbalanced-classes

Однако , акк / проигрыш сейчас действительно ужасный. Я получаю ~ 30% точности с плотным net, поэтому я ожидал, что LSTM будет улучшением. См. Кривые увеличения / уменьшения ниже:

enter image description here

1 Ответ

1 голос
/ 05 мая 2020

Keras / Tensorflow позволяет использовать class_weight или sample_weights в model.fit методе

class_weight влияет на относительный вес каждого класса при вычислении целевой функции. sample_weights, как следует из названия, позволяет дополнительно контролировать относительный вес образцов, принадлежащих к одному классу.

class_weight принимает словарь, в котором вы вычисляете веса каждого класса, а sample_weights получает одномерный массив dim == len (y_train), в котором вы назначаете определенный c вес каждой выборке

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...