Класовият дисбаланс е често срещан проблем при машинното обучение, особено при проблеми с класификацията. Данните за дисбаланс могат да попречат на точността на нашия модел. Появява се в много области, включително откриване на измами, филтриране на нежелана поща, скрининг на заболявания, класификация на пневмония. Дисбалансът на класовете е нормален и се очаква в типичните приложения за машинно обучение.

Визуализирайте с набор от данни за пневмония:

Вижте набора от данни тук

Както можем да видим тук набор от данни за пневмония, има класов дисбаланс със съотношение 1:3. Проблемът с обучението на модела с небалансиран набор от данни е, че моделът ще бъде предубеден само към класа на мнозинството. Това създава проблем, когато се интересуваме от прогнозата за класа на малцинството.

В тази статия научихме за различните техники, които можем да използваме, за да се справим с дисбаланса на класа. Няма „най-добър“ метод за справяне с дисбаланса, това зависи от вашия случай на употреба.

Нека обсъдим два начина за справяне с класовия дисбаланс:

  • Инициализация на отклонение.
  • Генериране на класово тегло.

Инициализация на отклонение:

Ако инициализираме всички тегла с нула, вашата мрежа не е по-добра от линеен модел. Важно е да се отбележи, че задаването на отклонения на 0 няма да създаде никакви проблеми, тъй като ненулевите тегла се грижат за нарушаване на симетрията и дори ако отклонението е 0, стойностите във всеки неврон пак ще бъдат различни. Нека да видим с пример с 0 инициализация срещу внимателен избор на отклонение.

model.layers[-1].bias.assign([0.0])
zero_bias_history = model.fit(
    train_features,
    train_labels,
    batch_size=BATCH_SIZE,
    epochs=10,
    validation_data=(validation_features, validation_labels), 
    verbose=0)
results = model.evaluate(train_features, train_labels, batch_size=BATCH_SIZE, verbose=0)
print("Loss with 0 bias: {:0.4f}".format(results[0]))

Загуба с отклонение 0: .3851

initial_bias = np.log([COUNT_PNEUMONIA/COUNT_NORMAL])
#select bias in output dense layer
tf.keras.layers.Dense(1, activation='sigmoid',bias_initializer=initial_bias)

careful_bias_history = model.fit(
    train_features,
    train_labels,
    batch_size=BATCH_SIZE,
    epochs=20,
    validation_data=(val_features, val_labels), 
    verbose=0)
results = model.evaluate(train_features, train_labels, batch_size=BATCH_SIZE, verbose=0)
print("Loss with bias: {:0.4f}".format(results[0]))

Загуба с инициализация на отклонение: .0134

Както виждаме, загубата е намаляла значително. По този начин отклонението при инициализацията подобрява производителността на моделите и компенсира главоблъсканицата с небалансирания набор от данни.

Генериране на класово тегло:

Генерирането на тегло на клас е друг добре познат подход за справяне с дисбаланса на класа, той е приложим както за двоично, така и за категорично приложение на клас. Повечето алгоритми за машинно обучение не са много полезни с предубедени данни за клас. Но можем да променим текущия алгоритъм на обучение, за да вземем предвид изкривеното разпределение на класовете. Това може да се постигне чрез даване на различни тежести както на класовете на мнозинството, така и на малцинството. Целта е да се санкционира погрешната класификация, направена от класа на малцинството, като се зададе по-високо тегло на класа и в същото време се намали тежестта за класа на мнозинството. По време на обучението ние даваме по-голяма тежест на малцинствения клас във функцията на разходите на алгоритъма, така че да може да осигури по-високо наказание за малцинствения клас и алгоритъмът да може да се фокусира върху намаляване на грешките за малцинствения клас.

По подразбиране стойността на class_weight=None, т.е. и на двата класа са дадени равни тегла. Освен това, можем или да го дадем като „балансиран“, или можем да подадем речник, който съдържа ръчни тегла и за двата класа.

Когато class_weights = ‘balanced’, моделът автоматично присвоява теглата на класа обратно пропорционално на съответните им честоти.

Ето примера как да наложите класово тегло ръчно на модел.

weight_for_0 = (1 / COUNT_NORMAL)*(TRAIN_IMG_COUNT)/2.0 
weight_for_1 = (1 / COUNT_PNEUMONIA)*(TRAIN_IMG_COUNT)/2.0

class_weight = {0: weight_for_0, 1: weight_for_1}
history = model.fit(
    train_ds,
    steps_per_epoch=TRAIN_IMG_COUNT // BATCH_SIZE,
    epochs=EPOCHS,
    validation_data=validation_features,
    validation_steps=VAL_IMG_COUNT // BATCH_SIZE,
    class_weight=class_weight,
)

Функция на загуба за двоична класификация

Функция на загуба за многокласова класификация

Където „w“ са теглата на класа, изчислява сумирането, като всеки клас се умножава с действителната стойност (Y) и прогнозираната стойност (log p).

Как получаваме персонализирана функция за загуба:

class CustomClassImbalaceLoss(class_weight):
    
    def __init__(self , thresold):
        super().__init__()
        self.class_weight = class_weight
        
    def call(self , y_true , y_pred):
        L = np.sum(self.class_weight* y_true* np.log(y_pred)* (-1) )
        
        return L
 model.compile(
        optimizer='adam',
        loss=CustomClassImbalaceLoss(class_weight),
        metrics=METRICS
    )

Заключение

Това не е всеобхватен набор от подходи за справяне с небалансирани данни, а по-скоро отправна точка. Няма идеален подход или модел за всички ситуации и е силно препоръчително да експериментирате с различни стратегии и модели, за да видите кое работи най-добре. Опитайте с нов или друг набор от данни и не забравяйте да приложите с вашия собствен подход .

Благодаря ти

Препратки



X. Guo, Y. Yin, C. Dong, G. Yang и G. Zhou, „On the Class Imbalance Problem,“ 2008 Fourth International Conference on Natural Computation, Jinan, China, 2008, pp. 192–201, doi: 10.1109/ICNC.2008.871

Класификация на небалансирани данниTensorFlowhttps://www.tensorflow.org › уроци › структурирани_данни

Сегментация и класификация на ядра, базирана на дълбоко обучение в хистопатологични изображения с приложение към геномиката на изображенията https://doi.org/10.1016/B978-0-12-814972-0.00008-4A

цялостен анализ на нивото на данните за диагностика на рак върху небалансирани данни https://doi.org/10.1016/j.jbi.2018.12.003