Функция потерь и индекс оценки в многоуровневой классификации

NLP
Функция потерь и индекс оценки в многоуровневой классификации

1. Введение

Привет друзья, добро пожаловать вМун Инн. В предыдущей статье [1] автор представил метод измерения модельных потерь в задаче классификации с одной меткой, то есть кросс-энтропийную функцию потерь. При этом также вводятся общие показатели оценки в мультиклассификационных задачах и методы их реализации [2]. В следующей статье автор подробно представит два распространенных метода оценки потерь в задачах классификации с несколькими метками, а также метрики оценки модели в сценариях классификации с несколькими метками.

2 Способ первый

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

loss(y,y^)=1Ci=1m[y(i)log(11+exp(y^(i)))+(1y(i))log(exp(y^(i))1+exp(y^(i)))]          (1)loss(y,\hat{y})=-\frac{1}{C} \sum_{i=1}^m\left[y^{(i)}\cdot\log\left(\frac{1}{1+\exp(-\hat{y}^{(i)})}\right)+\left(1-y^{(i)}\right)\cdot\log\left(\frac{\exp(-\hat{y}^{(i)})}{1+\exp(-\hat{y}^{(i)})}\right)\right]\;\;\;\;\;(1)

вCCпредставляет количество категорий,y(i)y^{(i)}иy^(i)\hat{y}^{(i)}Оба являются вектором, используемым для представления реальной метки и выходного значения сети без какой-либо обработки функции активации.

подчиненный(1)(1)Можно обнаружить, что этот метод измерения потерь на ошибки на самом деле является методом, используемым для измерения ошибки между прогнозируемой вероятностью и истинной меткой в ​​логистической регрессии.

2.1 numpyвыполнить:

По формуле(1)(1)Формула расчета величины убытка может быть дополнена следующим кодом Python:

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

def compute_loss_v1(y_true, y_pred):
    t_loss = y_true * np.log(sigmoid(y_pred)) + \
             (1 - y_true) * np.log(1 - sigmoid(y_pred))  # [batch_size,num_class]
    loss = t_loss.mean(axis=-1)  # 得到每个样本的损失值, 这里可以是
    return -loss.mean()  # 返回整体样本的损失均值(或其他)

if __name__ == '__main__':
    y_true = np.array([[1, 1, 0, 0], [0, 1, 0, 1]])
    y_pred = np.array([[0.2, 0.5, 0, 0], [0.1, 0.5, 0, 0.8]])
    print(compute_loss_v1(y_true, y_pred)) # 0.5926

Конечно, вTensorFlow 1.xиPytorchЭти два метода также реализуются отдельно.

2.2 TensorFlowвыполнить

существуетTensorflow 1.x, пройти можноtf.nnпод модульsigmoid_cross_entropy_with_logitsспособ вызова:

def sigmoid_cross_entropy_with_logits(labels, logits):
    loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=logits)
    loss = tf.reduce_mean(loss, axis=-1)
    return tf.reduce_mean(loss)

if __name__ == '__main__':
    y_true = tf.constant([[1, 1, 0, 0], [0, 1, 0, 1]],dtype=tf.float16)
    y_pred = tf.constant([[0.2, 0.5, 0, 0], [0.1, 0.5, 0, 0.8]],dtype=tf.float16)
    with tf.Session() as sess:
        loss = sess.run(sigmoid_cross_entropy_with_logits(y_true,y_pred))
        print(loss) # 0.5926

Конечно, после завершения обучения модели прогнозируемые результаты метки и соответствующие значения вероятности могут быть получены с помощью следующего кода:

def prediction(logits, K):
      y_pred = np.argsort(-logits, axis=-1)[:,:K]
    print("预测标签:",y_pred)
    p = np.vstack([logits[r,c] for r,c in enumerate(y_pred)])
    print("预测概率:",p)

prediction(y_pred,2)
#####
预测标签:
[[1 0]
 [3 1]]
预测概率: 
[[0.5 0.2]
 [0.8 0.5]]

2.3 Pytorchвыполнить

существуетPytorch, пройти можноtorch.nnв модулеMultiLabelSoftMarginLossкласс для завершения расчета потерь:

if __name__ == '__main__':
    y_true = torch.tensor([[1, 1, 0, 0], [0, 1, 0, 1]],dtype=torch.int16)
    y_pred = torch.tensor([[0.2, 0.5, 0, 0], [0.1, 0.5, 0, 0.8]],dtype=torch.float32)
    loss = nn.MultiLabelSoftMarginLoss(reduction='mean')
    print(loss(y_pred, y_true)) #0.5926

Точно так же после завершения обучения модели вы также можете пройти вышеуказанноеpredictionфункция для завершения предсказания вывода. Следует отметить, что вTensorFlow 1.xсерединаsigmoid_cross_entropy_with_logitsМетод возвращает среднее значение всех потерь выборки; в то время как вPytorchсередина,MultiLabelSoftMarginLossВозврат по умолчанию - это среднее значение всех потерь выборки, но его можно указать, указав параметры.reductionзаmeanилиsumуказать тип возвращаемого значения.

3 Способ 2

Среди методов измерения потерь результатов многометочной классификации, помимо метода 1, представленного выше, широко используется функция потерь. Эта функция потерь на самом деле является расширенной версией кросс-энтропийной функции потерь, которую мы используем в классификации с одной меткой, а одну метку можно рассматривать как частный случай. Его конкретная формула расчета выглядит следующим образом:

loss(y,y^)=1mi=1mj=1qyj(i)logy^j(i)                    (2)loss(y,\hat{y})=-\frac{1}{m}\sum_{i=1}^m\sum_{j=1}^qy^{(i)}_j\log{\hat{y}^{(i)}_j}\;\;\;\;\;\;\;\;\;\;(2)

вyj(i)y^{(i)}_jозначает первыйiiобразец №jjистинное значение каждой категории,y^j(i)\hat{y}^{(i)}_jозначает первыйiiобразец №jjВывод каждой категории обрабатывается softmax.

Например, для следующего образца:

y_true = np.array([[1, 1, 0, 0], [0, 1, 0, 1.]])
y_pred = np.array([[0.2, 0.5, 0.1, 0], [0.1, 0.5, 0, 0.8]])

Результат выходного значения после обработки softmax:

[[0.24549354 0.33138161 0.22213174 0.20099311]
 [0.18482871 0.27573204 0.16723993 0.37219932]]

Тогда по формуле(2)(2)Видно, что для двух приведенных выше образцов значение потерь равно:

\begin{aligned} loss &= -\frac{1}{2}\left(1\cdot \log(0.245)+1\cdot \log(0.331)\\+1\cdot \log(0.275) +1\cdot \log(0.372)\right)\approx2.395 \end{aligned}\;\;\;\;\;\;\;\;\;\;(3)

3.1 numpyвыполнить:

По формуле(3)(3)Формула расчета величины убытка может быть дополнена следующим кодом Python:

def softmax(x):
    s = np.exp(x)
    return s / np.sum(s, axis=-1, keepdims=True)

def compute_loss_v2(logits, y):
    logits = softmax(logits)
    print(logits)
    c = -(y * np.log(logits)).sum(axis=-1)  # 计算每一个样本的在各个标签上的损失和
    return np.mean(c)  # 计算所有样本损失的平均值
y_true = np.array([[1, 1, 0, 0], [0, 1, 0, 1.]])
y_pred = np.array([[0.2, 0.5, 0.1, 0], [0.1, 0.5, 0, 0.8]])
print(compute_loss_v2(y_pred, y_true))# 2.392

3.2TensorFlowвыполнить

существуетTensorflow 1.x, пройти можноtf.nnпод модульsoftmax_cross_entropy_with_logits_v2способ вызова:

def softmax_cross_entropy_with_logits(labels, logits):
    loss = tf.nn.softmax_cross_entropy_with_logits_v2(labels=labels, logits=logits)
    return tf.reduce_mean(loss)
y_true = tf.constant([[1, 1, 0, 0], [0, 1, 0, 1.]], dtype=tf.float16)
y_pred = tf.constant([[0.2, 0.5, 0.1, 0], [0.1, 0.5, 0, 0.8]], dtype=tf.float16)
with tf.Session() as sess:
    loss = sess.run(softmax_cross_entropy_with_logits(y_true, y_pred))
    print(loss)# 2.395 

3.3 Pytorchвыполнить

существуетPytorch, автор еще не нашел соответствующую модель, которую можно назвать, но ее можно реализовать кодированием самому:

def cross_entropy(logits, y):
    s = torch.exp(logits)
    logits = s / torch.sum(s, dim=1, keepdim=True)
    c = -(y * torch.log(logits)).sum(dim=-1)
    return torch.mean(c)

y_true = torch.tensor([[1, 1, 0, 0], [0, 1, 0, 1.]])
y_pred = torch.tensor([[0.2, 0.5, 0.1, 0], [0.1, 0.5, 0, 0.8]])
loss = cross_entropy(y_pred,y_true)
print(loss)# 2.392

Следует отметить, что из-за различных стратегий сохранения знаков после запятой при расчете каждого фреймворка конечный результат будет немного отличаться после запятой.

4 Метрики оценки

4.1 Игнорирование частично правильных методов оценки

(1) Коэффициент абсолютного совпадения (Exact Match Ratio)

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

MR=1mi=1mI(y(i)==y^(i))                    (4)MR=\frac{1}{m}\sum_{i=1}^mI(y^{(i)}==\hat{y}^{(i)})\;\;\;\;\;\;\;\;\;\;(4)

вnnпредставляет общее количество образцов;I()I(\cdot)является индикаторной функцией, когдаyiy_iточно эквивалентноy^i\hat{y}_iвремя взять11, в противном случае00. Видно, что чем больше значение MR, тем выше точность классификации.

Например, доступны следующие фактические и прогнозные значения:

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

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

Тогда его соответствующий MR должен быть0.3330.333, потому что только вторая выборка предсказана как правильная. существуетsklearn, вы можете напрямую пройтиsklearn.metricsв модулеaccuracy_scoreметод для завершения расчета [3], следующим образом:

from sklearn.metrics import accuracy_score
print(accuracy_score(y_true,y_pred)) # 0.33333333

(2) поражение 0–1

В дополнение к абсолютной частоте совпадений есть еще один критерий оценки, прямо противоположный процессу расчета, а именно проигрыш 0-1 (Zero-One Loss). Абсолютная точность вычисляет долю выборок, которые полностью предсказаны правильно, к общему количеству выборок, в то время как потеря 0-1 вычисляет долю выборок, которые предсказывают полностью неправильно, к общему количеству выборок. Таким образом, для приведенного выше прогноза и истинного результата его потеря 0-1 должна быть 0,667. Рассчитывается следующим образом:

L01=1mi=1mI(y(i)y^(i))                    (5)L_{0-1}=\frac{1}{m}\sum_{i=1}^mI(y^{(i)}\neq\hat{y}^{(i)})\;\;\;\;\;\;\;\;\;\;(5)

существуетsklearn, пройти можноsklearn.metricsв модулеzero_one_lossметод для завершения расчета [3], следующим образом:

from sklearn.metrics import zero_one_loss
print(zero_one_loss(y_true,y_pred))# 0.66666

4.2 Рассмотрим частично правильный метод оценки

Из приведенных выше двух показателей оценки видно, что будь то абсолютная скорость совпадения или потеря 0-1, оба они не учитывают частично правильную ситуацию при расчете результата, который явно неточен для оценки модели. .из. Например, предположим, что правильная метка[1,0,0,1], метка, предсказанная моделью,[1,0,1,0]. Можно видеть, что, хотя модель не предсказала все метки, она все же предсказала некоторые. Поэтому целесообразно учитывать результаты, которые частично предсказаны правильно [4]. Для реализации этой идеи в литературе [5] предложены коэффициент точности (Accuracy), коэффициент точности (Precision), коэффициент полноты (Recall) иF1F_1ценность(F1F_1-мера) метод расчета.

(1) Точность

Формула расчета показателя точности:

Accuracy=1mi=1my(i)y^(i)y(i)y^(i)                    (6)\text{Accuracy} = \frac{1}{m} \sum_{i=1}^{m} \frac{\lvert y^{(i)} \cap \hat{y}^{(i)}\rvert}{\lvert y^{(i)} \cup \hat{y}^{(i)}\rvert}\;\;\;\;\;\;\;\;\;\;(6)

из формулы(6)(6)Можно видеть, что показатель точности на самом деле представляет собой средний показатель точности всех выборок. Для каждой выборки уровень точности представляет собой долю предсказанных правильных меток в общем числе предсказанных правильных или истинно правильных меток. Например, для образца его истинная метка[0, 1, 0, 1], предсказанная метка[0, 1, 1, 0]. Тогда соответствующая точность этой выборки должна быть:

acc=11+1+1=13                    (7)acc = \frac{1}{1+1+1}=\frac{1}{3}\;\;\;\;\;\;\;\;\;\;(7)

Поэтому для следующих фактических и прогнозируемых результатов:

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

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

Его точность составляет:

Accuracy=13×(13+22+14)0.5278                    (8)\text{Accuracy}=\frac{1}{3}\times(\frac{1}{3}+\frac{2}{2}+\frac{1}{4})\approx0.5278\;\;\;\;\;\;\;\;\;\;(8)

Соответствующий код реализации [6]:

def Accuracy(y_true, y_pred):
    count = 0
    for i in range(y_true.shape[0]):
        p = sum(np.logical_and(y_true[i], y_pred[i]))
        q = sum(np.logical_or(y_true[i], y_pred[i]))
        count += p / q
    return count / y_true.shape[0]
print(Accuracy(y_true, y_pred)) # 0.52777

(2) Точность

Формула расчета показателя точности:

Precision=1mi=1my(i)y^(i)y^(i)                    (9)\text{Precision} = \frac{1}{m} \sum_{i=1}^{m} \frac{\lvert y^{(i)} \cap \hat{y}^{(i)}\rvert}{\lvert \hat{y}^{(i)}\rvert}\;\;\;\;\;\;\;\;\;\;(9)

из формулы(9)(9)Можно видеть, что показатель точности фактически вычисляет средний показатель точности всех выборок. Для каждого образца показатель точности представляет собой отношение количества правильно предсказанных меток к общему количеству правильно предсказанных меток. Например, для образца его истинная метка[0, 1, 0, 1], предсказанная метка[0, 1, 1, 0]. Тогда показатель точности, соответствующий этой выборке, должен быть:

pre=11+1=12                    (10)\text{pre} = \frac{1}{1+1}=\frac{1}{2}\;\;\;\;\;\;\;\;\;\;(10)

Таким образом, для истинных и предсказанных выше результатов точность составляет:

Precision=13×(12+22+12)0.6666                    (11)\text{Precision} = \frac{1}{3}\times(\frac{1}{2}+\frac{2}{2}+\frac{1}{2})\approx0.6666\;\;\;\;\;\;\;\;\;\;(11)

Соответствующий код реализации:

def Precision(y_true, y_pred):
    count = 0
    for i in range(y_true.shape[0]):
        if sum(y_pred[i]) == 0:
            continue
        count += sum(np.logical_and(y_true[i], y_pred[i])) / sum(y_pred[i])
    return count / y_true.shape[0]
print(Precision(y_true, y_pred))# 0.6666

(3) Скорость отзыва

Формула расчета коэффициента отзыва:

Recall=1mi=1my(i)y^(i)y(i)                    (12)\text{Recall} = \frac{1}{m} \sum_{i=1}^{m} \frac{\lvert y^{(i)} \cap \hat{y}^{(i)}\rvert}{\lvert y^{(i)}\rvert} \;\;\;\;\;\;\;\;\;\;(12)

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

Поэтому для следующих фактических и прогнозируемых результатов:

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

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

Его скорость отзыва:

Recall=13×(12+22+13)0.6111                    (13)\text{Recall}=\frac{1}{3}\times(\frac{1}{2}+\frac{2}{2}+\frac{1}{3})\approx0.6111\;\;\;\;\;\;\;\;\;\;(13)

Соответствующий код реализации:

def Recall(y_true, y_pred):
    count = 0
    for i in range(y_true.shape[0]):
        if sum(y_true[i]) == 0:
            continue
        count += sum(np.logical_and(y_true[i], y_pred[i])) / sum(y_true[i])
    return count / y_true.shape[0]
print(Recall(y_true, y_pred))# 0.6111

(4)F1F_1ценность

заF1F_1В стоимостном выражении его формула расчета такова:

F1=1mi=1m2y(i)y^(i)y(i)+y^(i)                    (14)F_{1} = \frac{1}{m} \sum_{i=1}^{m} \frac{2 \lvert y^{(i)} \cap \hat{y}^{(i)}\rvert}{\lvert y^{(i)}\rvert + \lvert \hat{y}^{(i)}\rvert} \;\;\;\;\;\;\;\;\;\;(14)

из формулы(14)(14)Как можно видеть,F1F_1Также рассчитывается средняя точность по всем образцам. Следовательно, для приведенных выше реальных и прогнозируемых результатов егоF1F_1Значение:

F1=23(14+24+15)0.6333                    (15)F_1=\frac{2}{3}(\frac{1}{4}+\frac{2}{4}+\frac{1}{5})\approx0.6333\;\;\;\;\;\;\;\;\;\;(15)

Соответствующий код реализации:

def F1Measure(y_true, y_pred):
    count = 0
    for i in range(y_true.shape[0]):
        if (sum(y_true[i]) == 0) and (sum(y_pred[i]) == 0):
            continue
        p = sum(np.logical_and(y_true[i], y_pred[i]))
        q = sum(y_true[i]) + sum(y_pred[i])
        count += (2 * p) / q
    return count / y_true.shape[0]
print(F1Measure(y_true, y_pred))# 0.6333

В приведенных выше четырех показателях чем больше значение, тем лучше классификационный эффект соответствующей модели. При этом из формулы(6)(9)(12)(14)(6)(9)(12)(14)Можно видеть, что, хотя этапы расчета показателей в сценарии с несколькими метками отличаются от шагов в сценарии с одной меткой, эти две концепции аналогичны при расчете показателей.

Конечно, для расчета последних трех показателей вы также можете напрямую передатьsklearnДля завершения код выглядит следующим образом:

from sklearn.metrics import precision_score, recall_score, f1_score
print(precision_score(y_true=y_true, y_pred=y_pred, average='samples'))# 0.6666
print(recall_score(y_true=y_true, y_pred=y_pred, average='samples'))# 0.6111
print(f1_score(y_true,y_pred,average='samples'))# 0.6333

(5) Потери Хэмминга

В дополнение к 6 методам оценки, описанным выше, ниже представлен еще один, более интуитивно понятный метод измерения потерь Хэмминга[3], формула его расчета:

Hamming Loss=1mqi=1mj=1qI(yj(i)y^j(i))                    (16)\text{Hamming Loss} = \frac{1}{m q} \sum_{i=1}^{m}\sum_{j=1}^{q} I\left( y^{(i)}_{j} \neq \hat{y}^{(i)}_{j} \right) \;\;\;\;\;\;\;\;\;\;(16)

вyj(i)y^{(i)}_jозначает первыйiiпервый из образцовjjтеги,qqУказывает, сколько существует категорий.

из формулы(16)(16)Можно видеть, что потеря Хэмминга измеряет долю неправильно предсказанных меток в общем количестве меток во всех выборках. Таким образом, для потерь по Хэммингу, чем меньше значение, тем лучше производительность модели. Поэтому для следующих фактических и прогнозируемых результатов:

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

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

Его потери по Хэммингу:

Hamming Loss=13×4(2+0+3)0.4166                    (17)\text{Hamming Loss}=\frac{1}{3\times4}(2+0+3)\approx0.4166\;\;\;\;\;\;\;\;\;\;(17)

Соответствующий код реализации:

def Hamming_Loss(y_true, y_pred):
    count = 0
    for i in range(y_true.shape[0]):
        p = np.size(y_true[i] == y_pred[i])
        q = np.count_nonzero(y_true[i] == y_pred[i])
        count += p - q
    return count / (y_true.shape[0] * y_true.shape[3])
print(Hamming_Loss(y_true, y_pred))# 0.4166

Также возможно пройтиsklearn.metricsсерединаhamming_lossметод достижения:

from sklearn.metrics import hamming_loss
print(hamming_loss(y_true, y_pred))# 0.4166

Конечно, хотя здесь представлены 7 различных показателей оценки, в многоуровневой классификации есть и другие различные методы оценки.Подробности см. в документе [4]. Например, также можноsklearn.metricв модулеmultilabel_confusion_matrixметод для отдельного расчета коэффициента точности, коэффициента отзыва и т. д. для каждой категории в мультиметке, наконец, рассчитывается среднее значение каждого индекса в каждой категории.

5 Резюме

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

Это конец этого материала, спасибо за чтение! Если вы найдете вышеизложенное полезным,Добро пожаловать, чтобы следить и распространять этот общедоступный аккаунт! Если у вас есть какие-либо вопросы или предложения, пожалуйста, добавьте автора в WeChat 'nulls8' или оставьте сообщение для связи. Зеленые холмы не меняются, а зеленые воды текут вечно Увидимся в Moon Inn!

Цитировать

[1] Чтобы понять мультиклассификацию, мы должны поговорить о логистической регрессии.

[2] Отзыв и F-значение в задачах мультиклассификации

[3] Scikit-learn: Machine Learning in Python, Pedregosa et al., JMLR 12, pp. 2825-2830, 2011.

[4] Сорауэр, Мохаммад С.. «Обзор литературы по алгоритмам для многоэтапного обучения» (2010).

[5] Годболе С. и Сараваги С. Дискриминативные методы для многоуровневой классификации, Конспект лекций по информатике, (2004), 22–30.

[6] ММУ РА Тара T.GitHub.IO/2020-01-25/…