Ответ 1
В этом случае имеет смысл разделить ваш вопрос на 2 темы, так как нейронные сети вряд ли непосредственно связаны с кривыми ROC.
Нейронные сети
Я думаю, что нет ничего лучше, чтобы научиться на примере, поэтому я покажу вам подход к вашей проблеме, используя проблему двоичной классификации, обученную нейронной сетью Feed-Forward, и вдохновленная этот учебник из pybrain.
Прежде всего, нужно определить набор данных. Самый простой способ визуализации - использовать бинарный набор данных на 2D-плоскости с точками, генерируемыми из нормальных распределений, каждый из которых принадлежит к одному из двух классов. В этом случае это будет линейно отделимо.
from pybrain.datasets import ClassificationDataSet
from pybrain.utilities import percentError
from pybrain.tools.shortcuts import buildNetwork
from pybrain.supervised.trainers import BackpropTrainer
from pybrain.structure.modules import SoftmaxLayer
from pylab import ion, ioff, figure, draw, contourf, clf, show, hold, plot
from scipy import diag, arange, meshgrid, where
from numpy.random import multivariate_normal
means = [(-1,0),(2,4),(3,1)]
cov = [diag([1,1]), diag([0.5,1.2]), diag([1.5,0.7])]
n_klass = 2
alldata = ClassificationDataSet(2, 1, nb_classes=n_klass)
for n in xrange(400):
for klass in range(n_klass):
input = multivariate_normal(means[klass],cov[klass])
alldata.addSample(input, [klass])
Чтобы визуализировать, он выглядит примерно так:
Теперь вы хотите разбить его на тренировочный и тестовый набор:
tstdata, trndata = alldata.splitWithProportion(0.25)
trndata._convertToOneOfMany()
tstdata._convertToOneOfMany()
И для создания вашей сети:
fnn = buildNetwork( trndata.indim, 5, trndata.outdim, outclass=SoftmaxLayer )
trainer = BackpropTrainer( fnn, dataset=trndata, momentum=0.1, verbose=True, weightdecay=0.01)
ticks = arange(-3.,6.,0.2)
X, Y = meshgrid(ticks, ticks)
# need column vectors in dataset, not arrays
griddata = ClassificationDataSet(2,1, nb_classes=n_klass)
for i in xrange(X.size):
griddata.addSample([X.ravel()[i],Y.ravel()[i]], [0])
griddata._convertToOneOfMany() # this is still needed to make the fnn feel comfy
Теперь вам нужно обучить свою сеть и посмотреть, какие результаты вы получите в конце:
for i in range(20):
trainer.trainEpochs( 1 )
trnresult = percentError( trainer.testOnClassData(),
trndata['class'] )
tstresult = percentError( trainer.testOnClassData(
dataset=tstdata ), tstdata['class'] )
print "epoch: %4d" % trainer.totalepochs, \
" train error: %5.2f%%" % trnresult, \
" test error: %5.2f%%" % tstresult
out = fnn.activateOnDataset(griddata)
out = out.argmax(axis=1) # the highest output activation gives the class
out = out.reshape(X.shape)
figure(1)
ioff() # interactive graphics off
clf() # clear the plot
hold(True) # overplot on
for c in range(n_klass):
here, _ = where(tstdata['class']==c)
plot(tstdata['input'][here,0],tstdata['input'][here,1],'o')
if out.max()!=out.min(): # safety check against flat field
contourf(X, Y, out) # plot the contour
ion() # interactive graphics on
draw() # update the plot
Это дает вам очень плохую границу в начале:
Но в итоге довольно хороший результат:
Кривые ROC
Что касается кривых ROC, здесь - это хорошая и простая библиотека Python, чтобы сделать это по случайной проблеме игрушек:
from pyroc import *
random_sample = random_mixture_model() # Generate a custom set randomly
#Example instance labels (first index) with the decision function , score (second index)
#-- positive class should be +1 and negative 0.
roc = ROCData(random_sample) #Create the ROC Object
roc.auc() #get the area under the curve
roc.plot(title='ROC Curve') #Create a plot of the ROC curve
Что дает вам одну кривую ROC:
Конечно, вы можете также построить несколько кривых ROC на одном и том же графике:
x = random_mixture_model()
r1 = ROCData(x)
y = random_mixture_model()
r2 = ROCData(y)
lista = [r1,r2]
plot_multiple_roc(lista,'Multiple ROC Curves',include_baseline=True)
(помните, что диагональ просто означает, что ваш классификатор случайен и что вы, вероятно, что-то не так)
Возможно, вы можете легко использовать свои модули в любой из ваших задач классификации (не ограничиваясь нейронными сетями), и он будет создавать кривые ROC для вас.
Теперь, чтобы получить класс/вероятность, необходимую для построения кривой ROC из вашей нейронной сети, вам просто нужно посмотреть на активацию вашей нейронной сети: activateOnDataset
в pybrain даст вам вероятность для обоих классов (в моем пример выше, мы просто берем максимум вероятностей, чтобы определить, какой класс рассмотреть). Оттуда просто преобразуйте его в формат, ожидаемый PyroC, как для random_mixture_model
, и он должен дать вам вашу кривую ROC.