Какой показатель точности c является наиболее подходящим для классификации по нескольким меткам, когда существует дисбаланс между отрицательными и положительными значениями - PullRequest
0 голосов
/ 10 июля 2020

Я кратко объясню свою проблему и подходы, которые я тестировал до сих пор.

У меня есть набор данных mov ie, и я пытаюсь предсказать 17 жанров на основе 4 столбцов (об актерах, сюжете, контент, обзоры).

Моя целевая переменная выглядит так:

y_train=array([[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, 1],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0],
       [0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

# Could be a problem that they are not float32 but int32?

y_test=array([[0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 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, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]])

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

Функция активации выходного слоя: сигмоид
Функция потерь: Binary_crossentropy
Metri c функция: точность (двоичная, поскольку функция потерь является двоичной кроэссентропией)

Результаты были очень многообещающими с уровнем точности 0,98 и потерей 0,003 по набору данных для обучения и проверки.

Кривые обучения Нет признаков переобучения или недостатка. enter image description here

However, I thought that such very well fitted accuracy is due to the fact of many negative values. And the algorithm can predict very well the 0s and thus it achieves such high accuracy.

So I tried the following trials

1st trial
Activation function of output layer: Sigmoid
Loss function: categorical_cross_entropy
Metric function: categorical_accuracy

The results are much worse. Very high accuracy and a totally unrepresentative validation dataset with many spikes. enter image description here

2nd trial
Activation function of output layer: Sigmoid
Loss function: sigmoid_focal_loss ( ссылка )
Метри c функция: category_accuracy

Лучшее улучшение потерь, с точностью, все еще находящейся в плохом диапазоне значений. Так что я пришел к выводу, что категорическая точность - не мой вариант. enter image description here

3rd trial ( I changed categorical accuracy to AUC)
Activation function of output layer: Sigmoid
Loss function: sigmoid_focal_loss ( ссылка )
Метри c функция: tf.keras.metrics.AU C (multi_label = True)

Результаты третьего испытания на тестовом наборе данных (фильмы никогда видел ранее классификатор нейронной сети)

"Test Score (evalution of the model's loss/error on the test sequences): 0.026287764310836792"
"Test Accuracy (evalution of the model's auc on the test sequences): 0.99942547082901"

enter image description here

Based on the results of each trial is still valid to assume that the model's metric is affected by the imbalance between 0, 1 target values? or the neural network with Adam optimizer is robust and generalized? I would like you to write your opinions on this matter.

[UPDATE]

Based on the comments, it was recommended to add class_weights produced the following error:

enter image description here

class_weights={0:1.0, 1:0.29}

Does Keras have any bug with the class weights argument?

Thanks a lot in advance.

[UPDATE] - 11.07.2020

I have decided to follow this plan:

Activation function of output layer: Sigmoid
Loss function: binary_crossentropy
Metric function: f1_score

I don't want to use the Accuracy metric since this is not an appropriate metric for classification with lots of negative classes compared to positive classes.

My model.compile() method looks like this

model_for_pruning.compile(optimizer='adam',
                          loss='binary_crossentropy',
                          metrics=[tfa.metrics.F1Score(y_train[0].shape[-1], average=None)])

Однако мне трудно выбрать между F1_score micro или простой счет F1, так как мои данные многоликие. Основываясь на моей интуиции, микро-среднее значение больше подходит для данных с несколькими метками, но, поскольку я использую sigmoid и binary_crossentropy, я считаю, что для оценки F1 не следует выполнять усреднение. Таким образом, я попытался поставить примерные веса на свои классы.

from sklearn.utils.class_weight import compute_sample_weight

class_weights_sample = compute_sample_weight('balanced',
                                             y_train)

fitted_model=model_for_pruning.fit([X_train_seq_actors, X_train_seq_plot, X_train_seq_features, X_train_seq_reviews],
                                           y_train,
                                           steps_per_epoch=int(np.ceil((X_train_seq_actors.shape[0]*optimizer_parameters['validation_split_ratio'])//hparams[HP_HIDDEN_UNITS])),
                                           epochs=fit_parameters["epoch"],
                                           batch_size=hparams[HP_HIDDEN_UNITS],
                                           validation_split=fit_parameters['validation_data_ratio'],
                                           callbacks=callbacks,
                                           use_multiprocessing=True,
                                           sample_weight=class_weights_sample
                                           )

Это типичный правильный подход или я что-то упускаю. Обратите внимание, я спрашиваю о правильности подхода, а не о том, запущен код или нет, потому что все работает успешно.

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