Когда мне нечего делать, я разбираюсь в кривой PR и кривой ROC и пишу код для расчета двух показателей. В среде python в sklearn есть готовые функции для расчета точек координат ROC-кривой.Чтобы разобраться в этих двух показателях глубже, при написании кода используется только пакет numpy. Факты доказали, что практика является единственным критерием проверки истинности.Только в процессе написания кода от руки можно по-настоящему оценить некоторые мелкие детали этих двух критериев оценки.Код записывается следующим образом.
1. Смоделируйте результат предсказания
Поскольку обе кривые используются для оценки эффективности классификации классификатора, здесь мы напрямую используем случайные числа для создания набора категорий и соответствующих достоверностей. Есть две категории: 0 и 1. Уверенность генерируется случайным образом от 0 до 1.
data_len = 50
label = np.random.randint(0, 2, size=data_len)
score = np.random.choice(np.arange(0.1, 1, 0.01), data_len)
Сгенерированные результаты следующие: первая строка представляет реальную категорию, а вторая строка представляет уверенность в том, что классификатор считает, что цель относится к категории 1.
label | 1 | 0 | 1 | 0 | 0 | 1 | 1 | ... |
---|---|---|---|---|---|---|---|---|
score | 0.22 | 0.31 | 0.92 | 0.34 | 0.37 | 0.18 | 0.51 | ... |
Поскольку наши уровни достоверности генерируются случайным образом, результат эквивалентен «угадыванию» бинарного классификатора.
2. Кривая PR
Будь то кривая PR или кривая ROC, сначала выберите категорию, а затем рассчитайте конкретно для этой категории.
Абсцисса кривой — это скорость отзыва (R), а ордината — точность (P), поэтому она называется кривой PR. Возьмем простой пример, чтобы проиллюстрировать определение P и R: предположим, что двоичному классификатору необходимо предсказать 100 выборок, и в этих выборках есть 80 классов 1 и 20 классов 0. Когда в качестве достоверности принимается некоторое значение S, предполагается, что классификатор считает, что в этот момент существует 60 выборок категории 1. Среди 60 предсказанных выборок 50 выборок предсказаны верно, а остальные 10 выборок предсказаны неправильно . Затем значения P и R для категории 1 рассчитываются следующим образом:
То есть есть вероятность 0,667 что предсказание верное.Для 80 образцов категории 1 классификатор подобен магу который может вызывать божественных зверей.После поднятия 80 божественных зверей было призвано только 50. Так что показатель отзыва составляет 62,5%, а остальные безжалостно отбрасываются.
Для категории 0, поскольку второй классификатор считает, что существует 60 категорий категории 1, в свою очередь, остальные 40 считаются категорией 0. Из вышеизложенного можно сделать вывод, что только 10 из 40 относятся к категории 0, а остальные относятся к категории 1. Таким образом, значения P и R для категории 0 рассчитываются следующим образом:
Согласно приведенному выше описанию код реализован следующим образом:
def PR_curve(y,pred):
pos = np.sum(y == 1)
neg = np.sum(y == 0)
pred_sort = np.sort(pred)[::-1] # 从大到小排序
index = np.argsort(pred)[::-1] # 从大到小排序
y_sort = y[index]
print(y_sort)
Pre = []
Rec = []
for i, item in enumerate(pred_sort):
if i == 0:#因为计算precision的时候分母要用到i,当i为0时会出错,所以单独列出
Pre.append(1)
Rec.append(0)
else:
Pre.append(np.sum((y_sort[:i] == 1)) /i)
Rec.append(np.sum((y_sort[:i] == 1)) / pos)
print(Pre)
print(Rec)
## 画图
plt.plot(Rec, Pre, 'k')
# plt.legend(loc='lower right')
plt.title('Receiver Operating Characteristic')
plt.plot([(0, 0), (1, 1)], 'r--')
plt.xlim([-0.01, 1.01])
plt.ylim([-0.01, 01.01])
plt.ylabel('Precision')
plt.xlabel('Recall')
plt.show()
Нарисованная кривая PR:
Здесь есть сомнение: в арбузной книге кривая PR — это кривая, проходящая через две точки (1, 0) и (0, 1), но точка (1, 0) всегда кажется маловероятной. кривой PR Есть ли проблема с вашим пониманием?3. ROC-кривая
Ордината ROC-кривой — TPR, а абсцисса — FPR (перевод на китайский язык слишком сумбурный, я до сих пор привык выражаться по-английски). TPR эквивалентен скорости отзыва кривой PR, а FPR представляет собой отношение всех предсказанных положительных отрицательных примеров к количеству истинно отрицательных примеров.
В приведенном выше примере для категории 1 эти два показателя рассчитываются следующим образом:
def ROC_curve(y,pred):
pos = np.sum(y == 1)
neg = np.sum(y == 0)
pred_sort = np.sort(pred)[::-1] #从大到小排序
index = np.argsort(pred)[::-1]#从大到小排序
y_sort = y[index]
print(y_sort)
tpr = []
fpr = []
thr = []
for i,item in enumerate(pred_sort):
tpr.append(np.sum((y_sort[:i] == 1)) / pos)
fpr.append(np.sum((y_sort[:i] == 0)) / neg)
thr.append(item)
print(fpr)
print(tpr)
print(thr)
#画图
plt.plot(fpr, tpr, 'k')
plt.title('Receiver Operating Characteristic')
plt.plot([(0,0),(1,1)],'r--')
plt.xlim([-0.01,1.01])
plt.ylim([-0.01,01.01])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
Результат выглядит следующим образом:
Можно видеть, что кривая ROC, полученная классификатором случайного угадывания, колеблется вокруг линии y=x.Если мы сохраним случайно сгенерированную достоверность только до одного десятичного знака, то в данных будет много значений одинаковой достоверности. Рассчитываемая таким образом ROC-кривая каждый раз будет немного отличаться в зависимости от результата сортировки.
Прикрепил:
Эти значения действительно довольно запутанные, и прилагается таблица формул, которую легко запросить, когда запутаешься: