Получение точности для многозвенного предсказания в scikit-learn

В настройке классификации с несколькими метками sklearn.metrics.accuracy_score вычисляет только точность подмножества (3): то есть набор меток, предсказанный для выборки, должен точно соответствовать соответствующему набору меток в y_true.

Этот способ вычисления точности иногда называют, возможно, менее двусмысленно, точным коэффициентом соответствия (1):

enter image description here

Есть ли способ получить другой типичный способ вычисления точности в scikit-learn, а именно

enter image description here

(как определено в (1) и (2), и менее двусмысленно упоминается как оценка Хэмминга (4) (так как это тесно связано с потерей Хэмминга), или на основе меток точность) ?


(1) Сороуер, Мохаммад С. "Литературное исследование по алгоритмам многоуровневого обучения." Университет штата Орегон, Корваллис (2010).

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

(3) Гамрави, Надя и Эндрю МакКаллум. "Коллективная классификация по нескольким меткам." Материалы 14-й международной конференции ACM по управлению информацией и знаниями. ACM, 2005.

(4) Годболе, Шантану и Сунита Сараваги. "Дискриминационные методы классификации с несколькими метками." Достижения в области обнаружения знаний и интеллектуального анализа данных. Springer Berlin Heidelberg, 2004. 22-30.

Ответ 1

Вы можете написать одну версию самостоятельно, вот пример без учета веса и нормализации.

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
    http://stackoverflow.com/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

Ответ 2

Для людей, читающих в 2019 году, теперь вы можете использовать sklearn.metrics.hamming_loss:

>>> import numpy as np
>>> hamming_loss(np.array([[0, 1], [1, 1]]), np.zeros((2, 2)))
0.75

Это также довольно легко вычислить в Numpy:

# Exact Match ratio:
np.all(y_pred == y_true, axis=1).mean()

# Hamming Score:
(y_pred == y_true).mean()