gov.sandia.cognition.statistics.method.ConvexReceiverOperatingCharacteristic Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cognitive-foundry Show documentation
Show all versions of cognitive-foundry Show documentation
A single jar with all the Cognitive Foundry components.
/*
* File: ConvexReceiverOperatingCharacteristic.java
* Authors: Kevin R. Dixon
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright Sep 2, 2011, Sandia Corporation.
* Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
* license for use of this work by or on behalf of the U.S. Government.
* Export of this program may require a license from the United States
* Government. See CopyrightHistory.txt for complete details.
*
*/
package gov.sandia.cognition.statistics.method;
import gov.sandia.cognition.annotation.PublicationReference;
import gov.sandia.cognition.annotation.PublicationReferences;
import gov.sandia.cognition.annotation.PublicationType;
import gov.sandia.cognition.evaluator.Evaluator;
import gov.sandia.cognition.statistics.method.ReceiverOperatingCharacteristic.DataPoint;
import gov.sandia.cognition.util.AbstractCloneableSerializable;
import gov.sandia.cognition.util.ObjectUtil;
import java.util.ArrayList;
/**
* Computes the convex hull of the Receiver Operating Characteristic (ROC),
* which a mathematician might call a "concave down" function.
* curve.
* @author Kevin R. Dixon
* @since 3.2.1
*/
@PublicationReferences(
references={
@PublicationReference(
author="Wikipedia",
title="Concave function",
type=PublicationType.WebPage,
year=2011,
url="http://en.wikipedia.org/wiki/Concave_function"
)
,
@PublicationReference(
author="Wikipedia",
title="Convex hull",
type=PublicationType.WebPage,
year=2011,
url="http://en.wikipedia.org/wiki/Convex_hull"
)
}
)
public class ConvexReceiverOperatingCharacteristic
extends AbstractCloneableSerializable
implements Evaluator
{
/**
* Convex hull of the ROC curve
*/
private ArrayList convexHull;
/**
* Creates a new instance of HandHMeasure
* @param convexHull
* Convex hull of the ROC curve
*/
private ConvexReceiverOperatingCharacteristic(
ArrayList convexHull )
{
this.setConvexHull(convexHull);
}
@Override
public ConvexReceiverOperatingCharacteristic clone()
{
ConvexReceiverOperatingCharacteristic clone =
(ConvexReceiverOperatingCharacteristic) super.clone();
clone.setConvexHull(
ObjectUtil.cloneSmartElementsAsArrayList( this.getConvexHull() ) );
return clone;
}
/**
* Computes the convex hull values using a trapezoid interpolation.
* @param input
* falsePositiveRate from which to estimate the truePositiveRate
* @return
* TruePositiveRate for the given FalsePositiveRate
*/
@Override
public Double evaluate(
Double input )
{
final double falsePositiveRate = input;
double truePositiveRate = 0.0;
ArrayList data = this.getConvexHull();
final int N = data.size();
for( int i = N-1; i >= 0; i-- )
{
ReceiverOperatingCharacteristic.DataPoint value = data.get(i);
final double x = value.getFalsePositiveRate();
// No need to interpolate if we're exactly on a point
if( x == falsePositiveRate )
{
truePositiveRate = value.getTruePositiveRate();
break;
}
else if( x < falsePositiveRate )
{
if( i < N-1 )
{
ReceiverOperatingCharacteristic.DataPoint right = data.get(i+1);
final double run = right.getFalsePositiveRate() - x;
final double y = value.getTruePositiveRate();
final double rise = right.getTruePositiveRate() - y;
final double slope = rise/run;
final double delta = falsePositiveRate - x;
truePositiveRate = y + delta*slope;
}
else
{
truePositiveRate = 1.0;
}
break;
}
}
return truePositiveRate;
}
/**
* Computes the convex hull of a ROC curve
* @param roc
* ROC curve from which to extract the convex hull
* @return
* Convex hull over the ROC curve
*/
public static ConvexReceiverOperatingCharacteristic computeConvexNull(
ReceiverOperatingCharacteristic roc )
{
ArrayList origRocData =
roc.getSortedROCData();
ArrayList convexRoc =
new ArrayList( origRocData.size() );
int leftIndex = 0;
ReceiverOperatingCharacteristic.DataPoint left =
origRocData.get(leftIndex);
convexRoc.add( left );
boolean done = false;
while( !done )
{
// Walk the "right" point toward the "left" point until no points
// between them are in between on the y-axis
left = origRocData.get(leftIndex);
int rightIndex = origRocData.size()-1;
if( leftIndex >= rightIndex )
{
done = true;
break;
}
boolean foundAbove = false;
while( rightIndex > leftIndex )
{
foundAbove = false;
ReceiverOperatingCharacteristic.DataPoint right =
origRocData.get(rightIndex);
double rise = right.getTruePositiveRate() - left.getTruePositiveRate();
double run = right.getFalsePositiveRate() - left.getFalsePositiveRate();
if( run == 0.0 )
{
// If we get here then we've seen nothing but points above
// us... that means we're done.
foundAbove = false;
}
else
{
double slope = rise / run;
for( int i = rightIndex-1; i > leftIndex; i-- )
{
ReceiverOperatingCharacteristic.DataPoint point =
origRocData.get(i);
double xdiff = point.getFalsePositiveRate() - right.getFalsePositiveRate();
// This is y-value the estimated convex hull without this point
double yhat = right.getTruePositiveRate() + xdiff * slope;
// If "point" is above estimated convex hull, then keep
// walking the right point toward the left point
if( yhat < point.getTruePositiveRate() )
{
rightIndex = i;
foundAbove = true;
break;
}
}
}
// No points were above the convex hull with the (left,right)
// combo... so we've found the next pair!!
// The "right" point becomes the next "left" point
if( !foundAbove )
{
convexRoc.add( right );
leftIndex = rightIndex;
break;
}
}
leftIndex = rightIndex;
}
ConvexReceiverOperatingCharacteristic roch =
new ConvexReceiverOperatingCharacteristic(convexRoc);
return roch;
}
/**
* Computes the area under the convex hull
* @return
* Area under the convex hull
*/
public double computeAreaUnderConvexHull()
{
return ReceiverOperatingCharacteristic.Statistic.computeAreaUnderCurveTrapezoid(
this.getConvexHull() );
}
/**
* Getter for convexHull
* @return
* Convex hull of the ROC curve
*/
public ArrayList getConvexHull()
{
return this.convexHull;
}
/**
* Setter for convexHull
* @param convexHull
* Convex hull of the ROC curve
*/
protected void setConvexHull(
ArrayList convexHull)
{
this.convexHull = convexHull;
}
}