gonum.org/v1/gonum@v0.14.0/stat/roc_example_test.go (about)

     1  // Copyright ©2016 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package stat_test
     6  
     7  import (
     8  	"fmt"
     9  	"math"
    10  
    11  	"gonum.org/v1/gonum/floats"
    12  	"gonum.org/v1/gonum/integrate"
    13  	"gonum.org/v1/gonum/stat"
    14  )
    15  
    16  func ExampleROC_weighted() {
    17  	y := []float64{0, 3, 5, 6, 7.5, 8}
    18  	classes := []bool{false, true, false, true, true, true}
    19  	weights := []float64{4, 1, 6, 3, 2, 2}
    20  
    21  	tpr, fpr, _ := stat.ROC(nil, y, classes, weights)
    22  	fmt.Printf("true  positive rate: %v\n", tpr)
    23  	fmt.Printf("false positive rate: %v\n", fpr)
    24  
    25  	// Output:
    26  	// true  positive rate: [0 0.25 0.5 0.875 0.875 1 1]
    27  	// false positive rate: [0 0 0 0 0.6 0.6 1]
    28  }
    29  
    30  func ExampleROC_unweighted() {
    31  	y := []float64{0, 3, 5, 6, 7.5, 8}
    32  	classes := []bool{false, true, false, true, true, true}
    33  
    34  	tpr, fpr, _ := stat.ROC(nil, y, classes, nil)
    35  	fmt.Printf("true  positive rate: %v\n", tpr)
    36  	fmt.Printf("false positive rate: %v\n", fpr)
    37  
    38  	// Output:
    39  	// true  positive rate: [0 0.25 0.5 0.75 0.75 1 1]
    40  	// false positive rate: [0 0 0 0 0.5 0.5 1]
    41  }
    42  
    43  func ExampleROC_threshold() {
    44  	y := []float64{0.1, 0.4, 0.35, 0.8}
    45  	classes := []bool{false, false, true, true}
    46  	stat.SortWeightedLabeled(y, classes, nil)
    47  
    48  	tpr, fpr, thresh := stat.ROC(nil, y, classes, nil)
    49  	fmt.Printf("true  positive rate: %v\n", tpr)
    50  	fmt.Printf("false positive rate: %v\n", fpr)
    51  	fmt.Printf("cutoff thresholds: %v\n", thresh)
    52  
    53  	// Output:
    54  	// true  positive rate: [0 0.5 0.5 1 1]
    55  	// false positive rate: [0 0 0.5 0.5 1]
    56  	// cutoff thresholds: [+Inf 0.8 0.4 0.35 0.1]
    57  }
    58  
    59  func ExampleROC_unsorted() {
    60  	y := []float64{8, 7.5, 6, 5, 3, 0}
    61  	classes := []bool{true, true, true, false, true, false}
    62  	weights := []float64{2, 2, 3, 6, 1, 4}
    63  
    64  	stat.SortWeightedLabeled(y, classes, weights)
    65  
    66  	tpr, fpr, _ := stat.ROC(nil, y, classes, weights)
    67  	fmt.Printf("true  positive rate: %v\n", tpr)
    68  	fmt.Printf("false positive rate: %v\n", fpr)
    69  
    70  	// Output:
    71  	// true  positive rate: [0 0.25 0.5 0.875 0.875 1 1]
    72  	// false positive rate: [0 0 0 0 0.6 0.6 1]
    73  }
    74  
    75  func ExampleROC_knownCutoffs() {
    76  	y := []float64{8, 7.5, 6, 5, 3, 0}
    77  	classes := []bool{true, true, true, false, true, false}
    78  	weights := []float64{2, 2, 3, 6, 1, 4}
    79  	cutoffs := []float64{-1, 3, 4}
    80  
    81  	stat.SortWeightedLabeled(y, classes, weights)
    82  
    83  	tpr, fpr, _ := stat.ROC(cutoffs, y, classes, weights)
    84  	fmt.Printf("true  positive rate: %v\n", tpr)
    85  	fmt.Printf("false positive rate: %v\n", fpr)
    86  
    87  	// Output:
    88  	// true  positive rate: [0.875 1 1]
    89  	// false positive rate: [0.6 0.6 1]
    90  }
    91  
    92  func ExampleROC_equallySpacedCutoffs() {
    93  	y := []float64{8, 7.5, 6, 5, 3, 0}
    94  	classes := []bool{true, true, true, false, true, true}
    95  	weights := []float64{2, 2, 3, 6, 1, 4}
    96  	n := 9
    97  
    98  	stat.SortWeightedLabeled(y, classes, weights)
    99  	cutoffs := make([]float64, n)
   100  	floats.Span(cutoffs, math.Nextafter(y[0], y[0]-1), y[len(y)-1])
   101  
   102  	tpr, fpr, _ := stat.ROC(cutoffs, y, classes, weights)
   103  	fmt.Printf("true  positive rate: %.3v\n", tpr)
   104  	fmt.Printf("false positive rate: %.3v\n", fpr)
   105  
   106  	// Output:
   107  	// true  positive rate: [0.167 0.333 0.583 0.583 0.583 0.667 0.667 0.667 1]
   108  	// false positive rate: [0 0 0 1 1 1 1 1 1]
   109  }
   110  
   111  func ExampleROC_aUC_unweighted() {
   112  	y := []float64{0.1, 0.35, 0.4, 0.8}
   113  	classes := []bool{true, false, true, false}
   114  
   115  	tpr, fpr, _ := stat.ROC(nil, y, classes, nil)
   116  
   117  	// Compute Area Under Curve.
   118  	auc := integrate.Trapezoidal(fpr, tpr)
   119  	fmt.Printf("true  positive rate: %v\n", tpr)
   120  	fmt.Printf("false positive rate: %v\n", fpr)
   121  	fmt.Printf("auc: %v\n", auc)
   122  
   123  	// Output:
   124  	// true  positive rate: [0 0 0.5 0.5 1]
   125  	// false positive rate: [0 0.5 0.5 1 1]
   126  	// auc: 0.25
   127  }
   128  
   129  func ExampleROC_aUC_weighted() {
   130  	y := []float64{0.1, 0.35, 0.4, 0.8}
   131  	classes := []bool{true, false, true, false}
   132  	weights := []float64{1, 2, 2, 1}
   133  
   134  	tpr, fpr, _ := stat.ROC(nil, y, classes, weights)
   135  
   136  	// Compute Area Under Curve.
   137  	auc := integrate.Trapezoidal(fpr, tpr)
   138  	fmt.Printf("auc: %f\n", auc)
   139  
   140  	// Output:
   141  	// auc: 0.444444
   142  
   143  }
   144  
   145  func ExampleTOC() {
   146  	classes := []bool{
   147  		false, false, false, false, false, false,
   148  		false, false, false, false, false, false,
   149  		false, false, true, true, true, true,
   150  		true, true, true, false, false, true,
   151  		false, true, false, false, true, false,
   152  	}
   153  
   154  	min, ntp, max := stat.TOC(classes, nil)
   155  	fmt.Printf("minimum bound: %v\n", min)
   156  	fmt.Printf("TOC:           %v\n", ntp)
   157  	fmt.Printf("maximum bound: %v\n", max)
   158  
   159  	// Output:
   160  	// minimum bound: [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10]
   161  	// TOC:           [0 0 1 1 1 2 2 3 3 3 4 5 6 7 8 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10]
   162  	// maximum bound: [0 1 2 3 4 5 6 7 8 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10]
   163  }
   164  
   165  func ExampleTOC_unsorted() {
   166  	y := []float64{8, 7.5, 6, 5, 3, 0}
   167  	classes := []bool{true, false, true, false, false, false}
   168  	weights := []float64{4, 1, 6, 3, 2, 2}
   169  
   170  	stat.SortWeightedLabeled(y, classes, weights)
   171  
   172  	min, ntp, max := stat.TOC(classes, weights)
   173  	fmt.Printf("minimum bound: %v\n", min)
   174  	fmt.Printf("TOC:           %v\n", ntp)
   175  	fmt.Printf("maximum bound: %v\n", max)
   176  
   177  	// Output:
   178  	// minimum bound: [0 0 0 3 6 8 10]
   179  	// TOC:           [0 4 4 10 10 10 10]
   180  	// maximum bound: [0 4 5 10 10 10 10]
   181  }
   182  
   183  func ExampleTOC_aUC_unweighted() {
   184  	classes := []bool{true, false, true, false}
   185  
   186  	_, ntp, _ := stat.TOC(classes, nil)
   187  	pos := ntp[len(ntp)-1]
   188  	base := float64(len(classes)) - pos
   189  
   190  	// Compute the area under ntp and under the
   191  	// minimum bound.
   192  	x := floats.Span(make([]float64, len(classes)+1), 0, float64(len(classes)))
   193  	aucNTP := integrate.Trapezoidal(x, ntp)
   194  	aucMin := pos * pos / 2
   195  
   196  	// Calculate the the area under the curve
   197  	// within the bounding parallelogram.
   198  	auc := aucNTP - aucMin
   199  
   200  	// Calculate the area within the bounding
   201  	// parallelogram.
   202  	par := pos * base
   203  
   204  	// The AUC is the ratio of the area under
   205  	// the curve within the bounding parallelogram
   206  	// and the total parallelogram bound.
   207  	auc /= par
   208  
   209  	fmt.Printf("number of true positives: %v\n", ntp)
   210  	fmt.Printf("auc: %v\n", auc)
   211  
   212  	// Output:
   213  	// number of true positives: [0 0 1 1 2]
   214  	// auc: 0.25
   215  }
   216  
   217  func ExampleTOC_aUC_weighted() {
   218  	classes := []bool{true, false, true, false}
   219  	weights := []float64{1, 2, 2, 1}
   220  
   221  	min, ntp, max := stat.TOC(classes, weights)
   222  
   223  	// Compute the area under ntp and under the
   224  	// minimum and maximum bounds.
   225  	x := make([]float64, len(classes)+1)
   226  	floats.CumSum(x[1:], weights)
   227  	aucNTP := integrate.Trapezoidal(x, ntp)
   228  	aucMin := integrate.Trapezoidal(x, min)
   229  	aucMax := integrate.Trapezoidal(x, max)
   230  
   231  	// Calculate the the area under the curve
   232  	// within the bounding parallelogram.
   233  	auc := aucNTP - aucMin
   234  
   235  	// Calculate the area within the bounding
   236  	// parallelogram.
   237  	par := aucMax - aucMin
   238  
   239  	// The AUC is the ratio of the area under
   240  	// the curve within the bounding parallelogram
   241  	// and the total parallelogram bound.
   242  	auc /= par
   243  
   244  	fmt.Printf("number of true positives: %v\n", ntp)
   245  	fmt.Printf("auc: %f\n", auc)
   246  
   247  	// Output:
   248  	// number of true positives: [0 0 2 2 3]
   249  	// auc: 0.444444
   250  }