Учебный мультибликовый классификатор с несбалансированными образцами в Керасе - PullRequest
0 голосов
/ 26 ноября 2018

Я пытаюсь обучить модель keras, которая берет выборки, скажем, x_i для выборки i и прогнозирует несколько независимых меток {y_hat}_ij, например, {y_hat}_ij = 1, если модель прогнозирует выборку x_i иметь метку j и 0 в противном случае.

Проблема, с которой я неоднократно сталкиваюсь, заключается в том, что количество образцов на этикетку не сбалансировано между метками.В частности, вот подсчет количества сэмплов на каждом ярлыке (разумеется, существует двойной подсчет, поскольку мы имеем дело с классификацией по нескольким меткам).У моей модели 23 этикетки.

total: 6790
Counter({22: 4702, 0: 1749, 12: 130, 8: 43, 16: 39,
         15: 30, 17: 24, 20: 17, 4: 13, 5: 13, 19: 9,
         6: 7, 7: 6, 2: 4, 10: 4})

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

То, что я до сих пор пробовал: я вычислял произвольные весовые коэффициенты каждой метки относительно ее вхождений в сравнении с общими выборками.class_weight = dict((c,round((1/v)*total,1)) for c,v in class_occ.items()), где class_occ - счетчик, показанный выше.Вот что я получаю:

class_weights: {0: 3.9, 2: 1697.5, 4: 522.3, 5: 522.3, 6: 970.0, 7: 1131.7, 8: 157.9, 10: 1697.5, 12: 52.2, 15: 226.3, 16: 174.1, 17: 282.9, 19: 754.4, 20: 399.4, 22: 1.4}

Затем, обучая модель, я поставляю ее в виде kwarg:

model.fit(x=...., class_weight=class_weight)

Однако модель недействительно учиться после этого, и точность остается на уровне 0,1 или около того.Чтобы дать некоторый контекст, вот как я скомпилировал модель:

out = Dense(numclasses+1, activation='sigmoid', name='out')(dense_top)

model = Model(inputs=[input], outputs=[out])
model.compile(optimizer="adam", loss="binary_crossentropy",
              metrics=["categorical_accuracy"])

А вот как идет обучение (синий - потеря; все слои поддаются обучению): model-fit-history

А из другого учебного экземпляра ( желтый - потеря; начальные слои заморожены): enter image description here

Я не уверен, что идет не такя даже правильно использую веса классов?Без весов классов модель просто все время предсказывала бы доминирующий класс (ы), а точность была бы базовой линией доли выборок, которые имели доминирующий класс (ы).Но похоже, что теперь он работает хуже, чем случайный.

На всякий случай, если это поможет, вот мой вывод model.summary():

Layer (type)                 Output Shape              Param #   
=================================================================
input_1 (InputLayer)         (None, None, 128)         0         
_________________________________________________________________
lstm_1 (LSTM)                (None, 192)               246528    
_________________________________________________________________
dense_1 (Dense)              (None, 160)               30880     
_________________________________________________________________
dense_2 (Dense)              (None, 128)               20608     
_________________________________________________________________
dense_3 (Dense)              (None, 128)               16512     
_________________________________________________________________
dense_4 (Dense)              (None, 64)                8256      
_________________________________________________________________
dense_top_1 (Dense)          (None, 64)                4160      
_________________________________________________________________
dropout_42 (Dropout)         (None, 64)                0         
_________________________________________________________________
dense_top_2 (Dense)          (None, 64)                4160      
_________________________________________________________________
dropout_43 (Dropout)         (None, 64)                0         
_________________________________________________________________
dense_top_3 (Dense)          (None, 64)                4160      
_________________________________________________________________
dropout_44 (Dropout)         (None, 64)                0         
_________________________________________________________________
dense_top_4 (Dense)          (None, 64)                4160      
_________________________________________________________________
dropout_45 (Dropout)         (None, 64)                0         
_________________________________________________________________
dense_top_5 (Dense)          (None, 32)                2080      
_________________________________________________________________
out (Dense)                  (None, 23)                759       
=================================================================
Total params: 342,263
Trainable params: 19,479
Non-trainable params: 322,784

Причина не обучаемых параметров заключается в том, что я 'm с использованием трансферного обучения: первый набор слоев взят из другой модели, которая выполнила бинарную классификацию для тех же данных, для наборов связанных меток («имеет ли образец x какие-либо метки из набора меток A по сравнению с набором меток B»? ').На всякий случай это проблема, я также установил trainable на True в отдельном случае, но это не помогло с обучением и получением модели для работы.

...