#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=???)
- макрос
- микро
- взвешенный
- Нет
Что происходит, когда вы устанавливаете значение 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.