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 }