Тип точности

#python #tensorflow #scikit-learn #precision

#python #тензорный поток #scikit-учиться #точность

Вопрос:

Точность достигается ниже с помощью библиотеки keras:

 model.compile(optimizer='sgd',
          loss='mse',
          metrics=[tf.keras.metrics.Precision()])
 

Какой тип точности, вычисляемый sklearn, равен точности, вычисляемой keras?

 precision_score(y_true, y_pred, average=???)
 
  1. макрос
  2. микро
  3. взвешенный
  4. Нет

Что происходит, когда вы устанавливаете значение zero_division равным 1, как показано ниже?:

 precision_score(y_true, y_pred, average=None, zero_division=1)
 

Ответ №1:

TLDR; По умолчанию используется binary для двоичной классификации и micro для многоклассовой классификации. Другие средние типы, такие как None и macro , также могут быть достигнуты с небольшими изменениями, как описано ниже.


Это должно дать вам некоторую ясность в отношении различий между tf.keras.Precision() и sklearn.metrics.precision_score() . Давайте сравним разные сценарии.

Сценарий 1: двоичная классификация

Для двоичной классификации ваши y_true и y_pred равны 0,1 и 0-1 соответственно. Реализация для обоих довольно проста.

Документация Sklearn: результаты отчета только для класса, указанного pos_label . Это применимо только в том случае, если целевые объекты (y_{true,pred}) являются двоичными.

 #Binary classification

from sklearn.metrics import precision_score
import tensorflow as tf

y_true = [0,1,1,1]
y_pred = [1,0,1,1]

print('sklearn precision: ',precision_score(y_true, y_pred, average='binary'))
#Only report results for the class specified by pos_label. 
#This is applicable only if targets (y_{true,pred}) are binary.

m = tf.keras.metrics.Precision()
m.update_state(y_true, y_pred)
print('tf.keras precision:',m.result().numpy())
 
 sklearn precision:  0.6666666666666666
tf.keras precision: 0.6666667
 

Сценарий 2: Многоклассовая классификация (глобальная точность)

Здесь вы работаете с метками нескольких классов, но вас не беспокоит, какова точность для каждого отдельного класса. Вам просто нужен глобальный набор TP и FP для вычисления общего показателя точности. В sklearn this задается параметром micro , в то время как в tf.keras this является настройкой по умолчанию для Precision()

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

 #Multi-class classification (global precision)

#3 classes, 6 samples
y_true = [[1,0,0],[0,1,0],[0,0,1],[1,0,0],[0,1,0],[0,0,1]]
y_pred = [[1,0,0],[0,0,1],[0,1,0],[1,0,0],[1,0,0],[0,1,0]]

print('sklearn precision: ',precision_score(y_true, y_pred, average='micro'))
#Calculate metrics globally by counting the total true positives, false negatives and false positives.

m.reset_states()
m = tf.keras.metrics.Precision()
m.update_state(y_true, y_pred)
print('tf.keras precision:',m.result().numpy())
 
 sklearn precision:  0.3333333333333333
tf.keras precision: 0.33333334
 

Сценарий 3: Многоклассовая классификация (двоичная точность для каждой метки)

Вас интересует этот сценарий, если вы хотите узнать точность для каждого отдельного класса. В sklearn это делается путем установки average параметра на None , в то время как в tf.keras вам придется создавать экземпляр объекта для каждого отдельного класса отдельно, используя class_id .

Документация Sklearn: если нет, возвращаются оценки для каждого класса.

 #Multi-class classification (binary precision for each label)

#3 classes, 6 samples
y_true = [[1,0,0],[0,1,0],[0,0,1],[1,0,0],[0,1,0],[0,0,1]]
y_pred = [[1,0,0],[0,0,1],[0,1,0],[1,0,0],[1,0,0],[0,1,0]]

print('sklearn precision: ',precision_score(y_true, y_pred, average=None))
#If None, the scores for each class are returned.

#For class 0
m0 = tf.keras.metrics.Precision(class_id=0)
m0.update_state(y_true, y_pred)

#For class 1
m1 = tf.keras.metrics.Precision(class_id=1)
m1.update_state(y_true, y_pred)

#For class 2
m2 = tf.keras.metrics.Precision(class_id=2)
m2.update_state(y_true, y_pred)

mm = [m0.result().numpy(), m1.result().numpy(), m2.result().numpy()]

print('tf.keras precision:',mm)
 
 sklearn precision:  [0.66666667 0.         0.        ]
tf.keras precision: [0.6666667, 0.0, 0.0]
 

Сценарий 4: Классификация по нескольким классам (среднее значение отдельных двоичных оценок)

После того, как вы рассчитали индивидуальную точность для каждого класса, вы можете захотеть получить средний балл (или средневзвешенное значение). В sklearn , простое среднее значение отдельных баллов берется путем установки параметра average macro равным . В tf.keras вы можете получить тот же результат, взяв среднее значение отдельных прецизий, как рассчитано в приведенном выше сценарии.

Документация Sklearn: вычислите показатели для каждой метки и найдите их невзвешенное среднее значение.

 #Multi-class classification (Average of individual binary scores)

#3 classes, 6 samples
y_true = [[1,0,0],[0,1,0],[0,0,1],[1,0,0],[0,1,0],[0,0,1]]
y_pred = [[1,0,0],[0,0,1],[0,1,0],[1,0,0],[1,0,0],[0,1,0]]

print('sklearn precision (Macro): ',precision_score(y_true, y_pred, average='macro'))
print('sklearn precision (Avg of None):' ,np.average(precision_score(y_true, y_pred, average=None)))

print(' ')

print('tf.keras precision:',np.average(mm)) #mm is list of individual precision scores
 
 sklearn precision (Macro):  0.2222222222222222
sklearn precision (Avg of None):  0.2222222222222222
 
tf.keras precision: 0.22222222
 

ПРИМЕЧАНИЕ: помните, что у sklearn вас есть модели, которые напрямую предсказывают метки, а precision_score это автономный метод. Поэтому он может работать непосредственно со списком меток для прогнозируемых и фактических значений. Однако tf.keras.Precision() это метрика, которая должна применяться к двоичному или многоклассовому плотному выводу. Он НЕ сможет работать с метками напрямую. Вам нужно будет предоставить ему массив длиной n для каждого образца, где n — количество классов / выходных плотных узлов.

Надеюсь, это прояснит, как 2 отличаются в разных сценариях. Пожалуйста, найдите более подробную информацию в документации sklearn и документации tf.keras.


Ваш второй вопрос —

Согласно документации sklearn,

 zero_division - “warn”, 0 or 1, default=”warn”
#Sets the value to return when there is a zero division. If set to “warn”, #this acts as 0, but warnings are also raised.
 

Это флаг обработки исключений. Во время вычисления оценки, если наступает время, когда он встречает a divide by zero , он будет считать его равным нулю и предупреждать. В противном случае установите его равным 1, если явно задано как 1.