在这种情况下,将您的问题分为 2 个主题是有意义的,因为神经网络与 ROC 曲线几乎没有直接关系。
神经网络
我认为没有什么比通过示例学习更好的方法了,所以我将向您展示一种解决问题的方法,该方法使用由 Feed-Forward 神经网络训练并受 @987654321 启发的二元分类问题@来自pybrain。
首先要定义一个数据集。最简单的可视化方法是在 2D 平面上使用二进制数据集,点从正态分布生成,每个点都属于 2 个类之一。在这种情况下,这将是线性可分的。
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 曲线,here 是一个不错且简单的 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 曲线所需的类别/概率,您只需查看神经网络的激活情况:pybrain 中的activateOnDataset 将为您提供这两个类别的概率(在我的上面的例子我们只取概率的最大值来确定要考虑哪个类)。从那里,只需将其转换为 PyROC 所期望的格式,例如 random_mixture_model,它就会为您提供 ROC 曲线。