Постановка задачи
Многие слышали о ROC-кривой, которая часто используется в ML. Расшифровывая данную аббревиатуру мы получаем, что ROC (англ. receiver operating characteristic). При переводе с английского это означает РХП (рабочая характеристика приемника). Данное понятие позаимствовано из теории обнаружения сигналов. ROC-кривую можно связать с радиолокационной станцией (РЛС), рассматривая ее с точки зрения обнаружения объекта. Опишем это более формально.
РЛС посылает импульсы, которые отражаются от объектов. Отражённый сигналвоспринимается приёмной антенной радара (Рис. 1). Если есть какой-либо объект, находящийся в зоне обнаружения (ЗО), то отраженный сигнал будет выше порога детектированияи это будет означать наличие объекта. Если отражённый сигнал ниже порога детектирования, то это означает отсутствие объекта.
ЗО
Зоной обнаружения РЛС называется область пространства, в пределах которой РЛС обеспечивает обнаружение объектов с вероятностями правильного обнаружения не хуже требуемых.
Наличие объекта обозначим как гипотеза, а его отсутствие как гипотеза. Сигнал— это непрерывная случайная величина. Предположим, что мы имеем условные распределения, которые нам известны.
Очевидно, что мы можем говорить о том, чтоимеет одинаковое распределение для обоих гипотез, но математические ожидания условных распределенийбудут различными. Так же реалистично предположить, что
Учитывая отклонения , возникающие из-за шума, получаем:
На Рис. 2 — есть условные математические ожидания случайной величиныпри условии гипотезы исоответственно. При этом, согласно, получаем, что .
Как уже было сказано ранее, сигнал сравнивается с неким порогом, который мы обозначили как . Решение о том есть ли объект в ЗО РЛС или нет обозначим как и соответственно. Дополняя Рис. 2 и, получаем:
Получаем следующие условные вероятности:
Условные вероятностиможно интерпретировать так:
– есть вероятность обнаружения объекта при условии, что выполняется гипотеза , т.е. объект действительно находится в ЗО.
– есть вероятность ложной тревоги, т.е. мы утверждаем , которое означает принятие решения о наличии объекта в ЗО, когда в действительности выполняется, т.е. объекта в ЗО нет.
Визуализируя интегралы , получаем:
Очевидно, что с уменьшением порогаплощадь под кривыми будет больше, а значит, чтоибудут увеличиваться.
Кривая, показывающая зависимость как функцию от для различных , называется ROC-кривая (англ. Receiver Operating Characteristic, рабочая характеристика приёмника).
Дисперсия случайной величиныопределяется характеристикой Отношение сигнал-шум (ОТШ, англ. Signal-to-Noise Ratio, сокр. ), которая записывается как:
– мощность сигнала;
– мощность шума.
Принимая в , а – дисперсия, получаем:
Построение ROC-кривых и их анализ
Пусть заданы следующие начальные условия:
Извидно, что мы делаем предположение о том, что условные плотности имеют нормальное распределение, т.е. и , где – обозначение нормального распределения с математическим ожиданием и дисперсией . Ранее мы обозначали как условное математическое ожидание случайной величины . Исходя из , получаем, что , а .
Из диапазона мы можем понять, какой у нас диапазон дисперсии . Для этого выразим из :
Подставляя граничные точки отрезка из , получаем:
Зададим вектор значений для построения ROC-кривой для каждого из них:
Шаг изменения значений вектора возьмем равным , т.е. . Определим теперь ROC-кривую как параметрическую функцию от , где в качестве параметра выступает . Из и , получаем:
– задает конкретную ROC-кривую из семейства ROC-кривых.
Зададим теперь вектор значений :
Шаг изменения значений вектора возьмем равным , т.е. . Вектор содержит значение, т.е. имеем точку для каждого графика. Таким образом, графики будут визуально выглядеть гладкими.
Имеющихся данных достаточно для построения ROC-кривых.
Воспользуемся для этого языком Python.
Подключение библиотек
# подключение дополнительных библиотек
from scipy.stats import norm
from scipy.misc import derivative
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns; sns.set()
%matplotlib inline
Дополнительные функции и начальные условия
# зададим вектор SNR и lambda
SNR_values = np.arange(-1, 5.5, 1/2)
lambda_values = np.arange(0, 1.01, 1/100)
# функция, которая возвращает значение sigma по заданному значению SNR
def snr_to_sigma(SNR):
return np.power(10, -SNR/20)
# функция, которая возвращает значения Pfa и Pd по заданным sigma и lambda
def roc_curve(sigma, lambda_):
return 1 - norm.cdf(lambda_/sigma), 1 - norm.cdf((lambda_ - 1)/sigma)
# создание DataFrame в котором будут храниться значения Pfa, Pd, SNR
data = []
for SNR in SNR_values:
for lambda_ in lambda_values:
Pfa, Pd = roc_curve(snr_to_sigma(SNR), lambda_)
data.append([Pfa, Pd, str(SNR)])
data = pd.DataFrame(data, columns=['Pfa', 'Pd', 'SNR'])
Код для построения графика
fig, ax = plt.subplots(figsize=(18, 14))
sns.set_context('poster')
plt.title('$ROC$-кривые в зависимости от значения $SNR$', fontsize=40)
plt.xlabel('$P_{fa}$', fontsize=40)
plt.xticks(np.arange(0, 0.7, 0.05), fontsize=30)
plt.yticks(np.arange(0.5, 1, 0.05), fontsize=30)
plt.ylabel('$P_d$', fontsize=40, rotation=0, labelpad=40)
sns.lineplot(x='Pfa', y='Pd', hue='SNR',
data=data, palette='gist_ncar', ax=ax)
ax.annotate("Возрастание $\lambda$", xy=(0.15, 0.81), xycoords='data',
xytext=(90, 150), textcoords='offset points',
size=30, ha='left',
arrowprops=dict(arrowstyle="->", color='black',
connectionstyle="arc3,rad=0.1"))
plt.grid(color='black', linestyle='--', linewidth=1, alpha=0.3)
plt.legend(fontsize='small', shadow=True, title='$SNR(dB)$',
borderpad=0.9, fancybox=True);
Из графика видно следующее:
Все кривые начинают свое движение с линии и заканчивают на линии ;
Чем больше значение , тем ближе ROC-кривая к точке ;
Все кривые выпуклы вверх;
ROC - кривая монотонно не убывает. Чем выше лежит кривая, тем лучше качество РЛС.
Первое объясняется ограниченностью значения порога детектирования . Посмотрим, как будут выглядеть ROC-кривые, если увеличить диапазон , например, до .
Дополнительный код
# создание DataFrame в котором будут храниться значения Pfa, Pd, SNR
data2 = []
for SNR in SNR_values:
for lambda_ in np.arange(-10, 10.1, 1/10) :
Pfa, Pd = roc_curve(snr_to_sigma(SNR), lambda_)
data2.append([Pfa, Pd, str(SNR)])
data2 = pd.DataFrame(data2, columns=['Pfa', 'Pd', 'SNR'])
Код для построения графика
fig, ax = plt.subplots(figsize=(18, 14))
sns.set_context('poster')
plt.title('$ROC$-кривые в зависимости от значения $SNR$', fontsize=40)
plt.xlabel('$P_{fa}$', fontsize=40)
plt.xticks(np.arange(0, 1.05, 0.1), fontsize=20)
plt.yticks(np.arange(0, 1.05, 0.1), fontsize=20)
plt.ylabel('$P_d$', fontsize=40, rotation=0, labelpad=40)
sns.lineplot(x='Pfa', y='Pd', hue='SNR',
data=data2, palette='gist_ncar', ax=ax)
ax.annotate("Возрастание $\lambda$", xy=(0.15, 0.81), xycoords='data',
xytext=(90, 110), textcoords='offset points',
size=20, ha='left',
arrowprops=dict(arrowstyle="->", color='black',
connectionstyle="arc3,rad=0.1"))
plt.grid(color='black', linestyle='--', linewidth=1, alpha=0.3)
plt.legend(fontsize='small', shadow=True, title='$SNR(dB)$',
borderpad=0.9, fancybox=True);
Второе объясняется тем, что можно достичь большего значения при меньшем значении . Это происходит потому, что при увеличении значения , уменьшается значение , что видно из . Посмотрим, как визуально изменяются кривые условных плотностей при разных значениях .
Дополнительный код
# функция, которая возвращает значение условных плотностей в зависимости от sigma
def conditional_density(x, sigma):
return norm.pdf(x/sigma), norm.pdf((x - 1)/sigma)
# создание DataFrame в котором будут храниться значения условных плотностей и SNR
data3 = []
x_range = np.linspace(-5, 5, 100)
for SNR in SNR_values:
for x in x_range :
cond_dens1, cond_dens2 = conditional_density(x, snr_to_sigma(SNR))
data3.append([cond_dens1, cond_dens2, str(SNR), x])
data3 = pd.DataFrame(data3, columns=['cond_dens1', 'cond_dens2', 'SNR', 'x'])
Код для построения графика
fig, ax = plt.subplots(figsize=(20, 10))
sns.set_context('poster')
plt.title('Условные распределения в зависимости от значения $SNR$',
fontsize=30)
plt.xlabel('$x$', fontsize=40)
plt.xticks(np.arange(-5, 5.5, 0.5), fontsize=20)
plt.yticks(np.arange(0, 0.45, 0.05), fontsize=20)
plt.ylabel('Значение условной плотности', fontsize=20,
labelpad=30)
sns.lineplot(x='x', y='cond_dens2', hue='SNR',
data=data3, palette='gist_ncar', ax=ax)
sns.lineplot(x='x', y='cond_dens1', hue='SNR',
data=data3, palette='gist_ncar', ax=ax, legend=False)
ax.legend(fontsize='small', shadow=True, title='$SNR(dB)$',
borderpad=0.9, fancybox=True, loc='upper left')
ax.annotate("$f_{X|H_0}(x|H_0)$", xy=(-0.6, 0.35), xycoords='data',
xytext=(-90, 20), textcoords='offset points',
size=30, ha='right',
arrowprops=dict(arrowstyle="->", color='black',
connectionstyle="arc3,rad=0.1"))
ax.annotate("$f_{X|H_1}(x|H_1)$", xy=(1.6, 0.35), xycoords='data',
xytext=(100, 20), textcoords='offset points',
size=30, ha='left',
arrowprops=dict(arrowstyle="->", color='black',
connectionstyle="arc3,rad=0.1"))
plt.grid(color='black', linestyle='--', linewidth=1, alpha=0.3);
По Рис. 7 видно, что при увеличении , кривые становятся уже, а, значит, пересекаются в меньшей степени. Посмотрим теперь на зависимость вероятности обнаружения от :
Дополнительный код
data4 = []
for SNR in SNR_values:
for lambda_ in lambda_values:
Pfa, Pd = roc_curve(snr_to_sigma(SNR), lambda_)
data4.append([Pfa, Pd, str(SNR), lambda_])
data4 = pd.DataFrame(data4, columns=['Pfa', 'Pd', 'SNR', 'lambda'])
Код для построения графика
fig, ax = plt.subplots(figsize=(16, 12))
sns.set_context('poster')
plt.title('Кривые $P_d$ от $\lambda$ при разных $SNR$', fontsize=40)
plt.xlabel('$\lambda$', fontsize=40)
plt.xticks(np.arange(0, 1.05, 0.1), fontsize=20)
plt.yticks(np.arange(0.5, 1.05, 0.1), fontsize=20)
plt.ylabel('$P_d$', fontsize=40, rotation=0, labelpad=40)
sns.lineplot(x='lambda', y='Pd', hue='SNR',
data=data4, palette='gist_ncar', ax=ax)
ax.annotate("Возрастание $\lambda$", xy=(0.5, 0.85), xycoords='data',
xytext=(-10, 50), textcoords='offset points',
size=20, ha='right',
arrowprops=dict(arrowstyle="->", color='black',
connectionstyle="arc3,rad=-0.2"))
plt.grid(color='black', linestyle='--', linewidth=1, alpha=0.3)
plt.legend(fontsize='small', shadow=True, title='$SNR(dB)$',
borderpad=0.9, fancybox=True);
достигает максимального значения при и . Но при таком низком пороге детектирования мы получаем:
Код для построения графика
fig, ax = plt.subplots(figsize=(16, 12))
sns.set_context('poster')
plt.title('Кривые $P_{fa}$ от $\lambda$ при разных $SNR$', fontsize=40)
plt.xlabel('$\lambda$', fontsize=40)
plt.ylabel('$P_{fa}$', fontsize=40, rotation=0, labelpad=40)
sns.lineplot(x='lambda', y='Pfa', hue='SNR',
data=data4, palette='gist_ncar', ax=ax)
ax.annotate("Возрастание $\lambda$", xy=(0.5, 0.35), xycoords='data',
xytext=(-10, 90), textcoords='offset points',
size=30, ha='right',
arrowprops=dict(arrowstyle="->", color='black',
connectionstyle="arc3,rad=0.2"))
plt.grid(color='black', linestyle='--', linewidth=1, alpha=0.3)
plt.legend(fontsize='small', shadow=True, title='$SNR(dB)$',
borderpad=0.9, fancybox=True);
При получается, что вероятность ложной тревоги равна , так как определенный интеграл от условной плотности распределения
считается от значения математического ожидания до , что в точности равно , в силу симметричности плотности нормального распределения.
Третье объясняется тем, что тангенс угла наклона ROC-кривой в некоторой ее точке равен значению плотностей от порога детектирования , необходимому для достижения и в этой точке.
Пусть
тогда:
Исследуем функцию :
Из и следует, что тангенс угла наклона ROC-кривой монотонно изменяется от до при от до . Таким образом, начиная построение графика от и, следовательно, . Заканчивается все в точке , когда , т.е. (касательная в данной точке перпендикулярна оси абсцисс).
Дополнительный код
# функция, которая возвращает значения Pfa и Pd по заданным sigma и lambda
def dif_roc_curve(sigma, lambda_):
return (derivative(lambda x: 1 - norm.cdf(x/sigma), lambda_, dx=1e-10),
derivative(lambda x: 1 - norm.cdf((x - 1)/sigma), lambda_, dx=1e-10))
data5 = []
for SNR in SNR_values:
for lambda_ in [0, 0.5, 1]:
dPfa, dPd = dif_roc_curve(snr_to_sigma(SNR), lambda_)
Pfa, Pd = roc_curve(snr_to_sigma(SNR), lambda_)
tan = dPd/dPfa
for i in np.arange(0.01/tan, 0.2/tan, 0.01/tan):
data5.append([tan*(i - Pfa) + Pd, i, str(SNR), lambda_])
data5 = pd.DataFrame(data5, columns=['y', 'x', 'SNR', 'lambda'])
Код для построения графика
fig, ax = plt.subplots(figsize=(18, 14))
sns.set_context('poster')
plt.title('$ROC$-кривая с $3^{мя}$ касательными', fontsize=40)
plt.xlabel('$P_{fa}$', fontsize=40)
plt.xticks(np.arange(0, 1.05, 0.1), fontsize=20)
plt.yticks(np.arange(0, 1.05, 0.1), fontsize=20)
plt.ylabel('$P_d$', fontsize=40, rotation=0, labelpad=40)
sns.lineplot(x='Pfa', y='Pd', hue='SNR', legend=False,
data=data[data['SNR'] == '5.0'], palette='gist_ncar', ax=ax)
sns.lineplot(x='x', y='y', hue='lambda', linestyle='--',
data=data5[data5['SNR'] == '5.0'],
palette='dark:b', legend=True, ax=ax)
plt.grid(color='black', linestyle='--', linewidth=1, alpha=0.3)
plt.legend(fontsize='small', shadow=True, title='Касательная для $\lambda=$',
borderpad=0.9, fancybox=True, loc=4);
/
На рис. 10 рассматриваются точки .
Вывод
В ходе исследования были построены множество ROC-кривых на основе аналитического выражения . Были также получены свойства ROC-кривых на основе графиков и аналитических выражений. То, каким образом будет выглядеть характеристика рабочего приемника, зависит от значения , из которого однозначно определяется значение . Также область, в которой определена ROC-кривая, зависит от диапазона .
Использованная литература
Ван-Трис Гарри Л. Теория обнаружения, оценок и модуляции. Том 1. Теория обнаружения, оценок и линейной модуляции -Нью-Йорк, 1968, Пер, с англ. , под ред. проф. В. И. Тихонова. М., «Советское радио», 1972, 744 с.
Тяпкин В.Н. Основы построения радиолокационных станции? радиотехнических вои?ск: учебник / В.Н. Тяпкин, А.Н. Фомин, Е.Н. Гарин [и др.]; под общ. ред. В.Н. Тяпкина. – Красноярск : Сиб. федер. ун-т. – 2011. – 536 с.
Дополнительно
Ссылка на github с исходным кодом.
AmigoRRR
Очень интересно продолжайте! Как это будет выглядеть если у нас четыре излучающие антены и три принимающие?
prudent Автор
Трудно сказать, какое будет аналитическое выражение, при условии, что распределение будет таким же. Однако можно утверждать, что P_d будет больше, и, следовательно, P_fa будет меньше.
Когда у нас имеется несколько передающих и приемных устройств, то мы имеем дело с третичной обработкой информации (ТОИ), которая является объединением радиолокационной информации (РЛИ) о цели, полученной от нескольких источников.