Багатозначні класифікаційні показники на scikit


19

Я намагаюся створити класифікатор, що містить багато міток, щоб призначити теми існуючим документам за допомогою scikit

Я обробляю свої документи, передаючи їх по TfidfVectorizerмітках через MultiLabelBinarizerі OneVsRestClassifierстворюючи SGDClassifierа з оцінкою.

Однак під час тестування свого класифікатора я отримую лише бали до .29, що з того, що я прочитав, є досить низьким для подібних проблем. Я спробував декілька варіантів на TfidfVectorizer, такі як стоп-слова, уніграми, стримування і, здається, ніщо так не змінило результат.

Я також використовував, GridSearchCVщоб отримати найкращі параметри для мого оцінювача, і зараз я не маю ідеї, що спробувати далі.

У той же час, від того, що я розумію , що я не можу використовувати scikit.metricsз OneVsRestClassifierтаким , як я можу отримати деякі метрики (F1, Precision, Recall і т.д.), щоб з'ясувати , що не так?

Чи може бути проблема з моїм корпусом даних?

Оновлення: Я також спробував з допомогою CountVectorizerі HashingVectorizerі конвеєрними їх , TfidfTransformerале результати аналогічні. Тож я здогадуюсь, що підхід "сумних слів" робить найкраще в області токенізації, а решта - до класифікатора ...


1
Що таке вимірювання 0,29? Точність? Щось ще?
Sycorax повідомляє про відновлення Моніки

@GeneralAbrial Відповідно до документації scikit, що працює scoreна класифікаторі,Returns the mean accuracy on the given test data and labels. In multi-label classification, this is the subset accuracy which is a harsh metric since you require for each sample that each label set be correctly predicted.
mobius

Це те, що ти зробив? З вашого запитання зовсім не зрозуміло, що це так, тому це цілком розумне питання.
Sycorax повідомляє про відновлення Моніки

@GeneralAbrial Так, це я зробив. Вибачте за плутанину, я намагався утримати це питання в більш теоретичному, а не розвивальному.
mobius

Ви можете додати тут свій код? Зокрема, ви використовуєте sample_weight = "збалансований" для SGD? Але ми можемо зазначити інші речі, коли ми побачимо ваш код.
Дієго

Відповіді:


21

Точність підмножини дійсно є суворою метрикою. Щоб зрозуміти, наскільки хороший чи поганий 0,29, є якась ідея:

  • подивіться, скільки міток у вас в середньому для кожного зразка
  • подивіться угоду між анотаторами, якщо вона є (якщо ні, спробуйте самі побачити, яка точність підмножини отримана, коли ви класифікатор)
  • подумайте, чи чітко визначена тема
  • подивіться, скільки зразків у вас є для кожної етикетки

Ви також можете обчислити бал забивання, щоб побачити, чи ваш класифікатор не зрозумілий, чи замість цього пристойно хороший, але виправите прогнозування всіх міток правильно. Дивіться нижче, щоб обчислити бальну оцінку.

У той же час, з того, що я розумію, я не можу використовувати scikit.metrics з OneVsRestClassifier, тож як я можу отримати деякі показники (F1, Precision, Recall тощо), щоб зрозуміти, що не так?

Див. Розділ Як обчислити точність / відкликання для класифікації багаторівневих класів? . Я забув, чи підтримує sklearn, я пам'ятаю, що він мав деякі обмеження, наприклад sklearn не підтримує мультимарк для матриці плутанини . Це було б гарною ідеєю побачити ці цифри справді.


Оцінка Хеммінга :

У MultiLabel класифікації настройки, sklearn.metrics.accuracy_scoreтільки обчислює точність підмножини (3): тобто безліч міток передбачених для зразка повинен точно відповідати відповідного набору міток в y_true.

Цей спосіб обчислення точності колись названий, можливо, менш неоднозначно, точним співвідношенням відповідності (1):

введіть тут опис зображення

Ще один типовий спосіб обчислення точності визначений у (1) та (2), і менш неоднозначно його називають шкалою Хеммінга (4) (оскільки він тісно пов'язаний із втратою Хеммінга) або точністю на основі етикетки ). Він обчислюється так:

введіть тут опис зображення

Ось метод пітона для обчислення оцінки Хеммінга:

# Code by /programming//users/1953100/william
# Source: /programming//a/32239764/395857
# License: cc by-sa 3.0 with attribution required

import numpy as np

y_true = np.array([[0,1,0],
                   [0,1,1],
                   [1,0,1],
                   [0,0,1]])

y_pred = np.array([[0,1,1],
                   [0,1,1],
                   [0,1,0],
                   [0,0,0]])

def hamming_score(y_true, y_pred, normalize=True, sample_weight=None):
    '''
    Compute the Hamming score (a.k.a. label-based accuracy) for the multi-label case
    /programming//q/32239577/395857
    '''
    acc_list = []
    for i in range(y_true.shape[0]):
        set_true = set( np.where(y_true[i])[0] )
        set_pred = set( np.where(y_pred[i])[0] )
        #print('\nset_true: {0}'.format(set_true))
        #print('set_pred: {0}'.format(set_pred))
        tmp_a = None
        if len(set_true) == 0 and len(set_pred) == 0:
            tmp_a = 1
        else:
            tmp_a = len(set_true.intersection(set_pred))/\
                    float( len(set_true.union(set_pred)) )
        #print('tmp_a: {0}'.format(tmp_a))
        acc_list.append(tmp_a)
    return np.mean(acc_list)

if __name__ == "__main__":
    print('Hamming score: {0}'.format(hamming_score(y_true, y_pred))) # 0.375 (= (0.5+1+0+0)/4)

    # For comparison sake:
    import sklearn.metrics

    # Subset accuracy
    # 0.25 (= 0+1+0+0 / 4) --> 1 if the prediction for one sample fully matches the gold. 0 otherwise.
    print('Subset accuracy: {0}'.format(sklearn.metrics.accuracy_score(y_true, y_pred, normalize=True, sample_weight=None)))

    # Hamming loss (smaller is better)
    # $$ \text{HammingLoss}(x_i, y_i) = \frac{1}{|D|} \sum_{i=1}^{|D|} \frac{xor(x_i, y_i)}{|L|}, $$
    # where
    #  - \\(|D|\\) is the number of samples  
    #  - \\(|L|\\) is the number of labels  
    #  - \\(y_i\\) is the ground truth  
    #  - \\(x_i\\)  is the prediction.  
    # 0.416666666667 (= (1+0+3+1) / (3*4) )
    print('Hamming loss: {0}'.format(sklearn.metrics.hamming_loss(y_true, y_pred))) 

Виходи:

Hamming score: 0.375
Subset accuracy: 0.25
Hamming loss: 0.416666666667

(1) Сороуер, Мохаммед С. " Літературне опитування щодо алгоритмів навчання на багато міток ". Орегонський державний університет, Корваліс (2010).

(2) Цумака, Григоріос та Іоанніс Катакіс. " Класифікація мульти-етикетки: огляд ". Кафедра інформатики, Університет Арістотеля в Салоніках, Греція (2006).

(3) Гамраві, Надія та Ендрю Маккаллум. " Колективна багатозначна класифікація ". Матеріали 14-ї міжнародної конференції АСМ з питань управління інформацією та знаннями. ОСБ, 2005.

(4) Годбол, Шантану та Суніта Саравагі. " Дискримінаційні методи для багатозначної класифікації. " Успіхи у відкритті знань та обміні даними. Спрингер Берлін Гейдельберг, 2004. 22-30.


чудова відповідь, це просто зробило мене кращим :) Я збираюся прочитати це більш ретельно, спробуйте бал Хеммінга і повернусь до вас!
mobius

Якщо чесно, мені не зовсім зрозуміло, що саме є точністю підмножини (Точне співвідношення відповідності). Не могли б ви пояснити трохи більше? Здається, що у випадку багатокласовості це ідентичне нагадування.
Poete Maudit

Ці hamming_scoreфункціональні помилки поза на Keras: <IPython-вхід-34-16066d66dfdd> в hamming_score (y_true, y_pred, нормалізують, sample_weight) 60 '' »61 acc_list = [] ---> 62 для г в діапазоні (y_true.shape [ 0]): 63 set_true = set (np.where (y_true [i]) [0]) 64 set_pred = set (np.where (y_pred [i]) [0]) TypeError: індекс повертається non-int (тип NoneType )
rjurney

0

Чи недостатньо балів 0,29? Як виглядає ваша матриця плутанини? Чи є якісь теми, які неможливо відокремити, лише переглянувши вміст слова?

В іншому випадку спробуйте вирішити свою проблему: Гіпотеза про те, що низькі бали насправді є найкращим, який може зробити ваш класифікатор у ваших даних. Це означає, що ваші документи не підлягають класифікації за допомогою цього підходу.

Щоб перевірити цю гіпотезу, вам потрібен набір тестових документів із відомими характеристиками «сумного слова» (який ви створюєте самі). Ви повинні отримати 100% балів.

Якщо ви цього не зробите, то у вас є помилка. В іншому випадку вам потрібен інший підхід до класифікації документів. Запитайте себе: чим документи різних класів відрізняються один від одного? Чи потрібно переглянути інші особливості моїх документів тощо.


Крім цифр, я відчуваю, що 0,29 є низьким. Я використовую підготовлену модель для прогнозування тем на документах, які я вже використовував у навчанні для ручного тестування класифікатора. Мені не вдалося отримати хоча б стільки ж тем, які користувач вручну ввів у документ. Зазвичай я просто отримую їх підмножину. Що стосується питання матриці плутанини, я не думаю, що я можу отримати матрицю плутанини на OneVsRestClassifier за допомогою scikit.metrics ... Я перевірю це, хоча
mobius
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.