confusion_matrix 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.rdoc +22 -22
  3. data/README.rdoc +88 -88
  4. data/lib/confusion_matrix.rb +383 -451
  5. data/test/matrix_test.rb +160 -160
  6. metadata +10 -15
data/test/matrix_test.rb CHANGED
@@ -1,160 +1,160 @@
1
- require 'confusion_matrix'
2
- require 'minitest/autorun'
3
-
4
- class TestConfusionMatrix < MiniTest::Test
5
- def test_empty_case
6
- cm = ConfusionMatrix.new
7
- assert(0, cm.total)
8
- assert(0, cm.true_positive(:none))
9
- assert(0, cm.false_negative(:none))
10
- assert(0, cm.false_positive(:none))
11
- assert(0, cm.true_negative(:none))
12
- assert_in_delta(0, cm.true_rate(:none))
13
- end
14
-
15
- def test_two_classes
16
- cm = ConfusionMatrix.new
17
- 10.times { cm.add_for(:pos, :pos) }
18
- 5.times { cm.add_for(:pos, :neg) }
19
- 20.times { cm.add_for(:neg, :neg) }
20
- 5.times { cm.add_for(:neg, :pos) }
21
-
22
- assert_equal([:neg, :pos], cm.labels)
23
- assert_equal(10, cm.count_for(:pos, :pos))
24
- assert_equal(5, cm.count_for(:pos, :neg))
25
- assert_equal(20, cm.count_for(:neg, :neg))
26
- assert_equal(5, cm.count_for(:neg, :pos))
27
-
28
- assert_equal(40, cm.total)
29
- assert_equal(10, cm.true_positive(:pos))
30
- assert_equal(5, cm.false_negative(:pos))
31
- assert_equal(5, cm.false_positive(:pos))
32
- assert_equal(20, cm.true_negative(:pos))
33
- assert_equal(20, cm.true_positive(:neg))
34
- assert_equal(5, cm.false_negative(:neg))
35
- assert_equal(5, cm.false_positive(:neg))
36
- assert_equal(10, cm.true_negative(:neg))
37
-
38
- assert_in_delta(0.6667, cm.true_rate(:pos))
39
- assert_in_delta(0.8, cm.true_rate(:neg))
40
- assert_in_delta(0.2, cm.false_rate(:pos))
41
- assert_in_delta(0.3333, cm.false_rate(:neg))
42
- assert_in_delta(0.6667, cm.precision(:pos))
43
- assert_in_delta(0.8, cm.precision(:neg))
44
- assert_in_delta(0.6667, cm.recall(:pos))
45
- assert_in_delta(0.8, cm.recall(:neg))
46
- assert_in_delta(0.6667, cm.sensitivity(:pos))
47
- assert_in_delta(0.8, cm.sensitivity(:neg))
48
- assert_in_delta(0.75, cm.overall_accuracy)
49
- assert_in_delta(0.6667, cm.f_measure(:pos))
50
- assert_in_delta(0.8, cm.f_measure(:neg))
51
- assert_in_delta(0.7303, cm.geometric_mean)
52
- end
53
-
54
- # Example from:
55
- # https://www.datatechnotes.com/2019/02/accuracy-metrics-in-classification.html
56
- def test_two_classes_2
57
- cm = ConfusionMatrix.new
58
- 5.times { cm.add_for(:pos, :pos) }
59
- 1.times { cm.add_for(:pos, :neg) }
60
- 3.times { cm.add_for(:neg, :neg) }
61
- 2.times { cm.add_for(:neg, :pos) }
62
-
63
- assert_equal(11, cm.total)
64
- assert_equal(5, cm.true_positive(:pos))
65
- assert_equal(1, cm.false_negative(:pos))
66
- assert_equal(2, cm.false_positive(:pos))
67
- assert_equal(3, cm.true_negative(:pos))
68
-
69
- assert_in_delta(0.7142, cm.precision(:pos))
70
- assert_in_delta(0.8333, cm.recall(:pos))
71
- assert_in_delta(0.7272, cm.overall_accuracy)
72
- assert_in_delta(0.7692, cm.f_measure(:pos))
73
- assert_in_delta(0.8333, cm.sensitivity(:pos))
74
- assert_in_delta(0.6, cm.specificity(:pos))
75
- assert_in_delta(0.4407, cm.kappa(:pos))
76
- assert_in_delta(0.5454, cm.prevalence(:pos))
77
- end
78
-
79
- # Examples from:
80
- # https://standardwisdom.com/softwarejournal/2011/12/matthews-correlation-coefficient-how-well-does-it-do/
81
- def two_class_case(a,b,c,d,e,f,g,h,i)
82
- cm = ConfusionMatrix.new
83
- a.times { cm.add_for(:pos, :pos) }
84
- b.times { cm.add_for(:pos, :neg) }
85
- c.times { cm.add_for(:neg, :neg) }
86
- d.times { cm.add_for(:neg, :pos) }
87
-
88
- assert_in_delta(e, cm.matthews_correlation(:pos))
89
- assert_in_delta(f, cm.precision(:pos))
90
- assert_in_delta(g, cm.recall(:pos))
91
- assert_in_delta(h, cm.f_measure(:pos))
92
- assert_in_delta(i, cm.kappa(:pos))
93
- end
94
-
95
- def test_two_classes_3
96
- two_class_case(100, 0, 900, 0, 1.0, 1.0, 1.0, 1.0, 1.0)
97
- two_class_case(65, 35, 825, 75, 0.490, 0.4643, 0.65, 0.542, 0.4811)
98
- two_class_case(50, 50, 700, 200, 0.192, 0.2, 0.5, 0.286, 0.1666)
99
- end
100
-
101
- def test_three_classes
102
- cm = ConfusionMatrix.new
103
- 10.times { cm.add_for(:red, :red) }
104
- 7.times { cm.add_for(:red, :blue) }
105
- 5.times { cm.add_for(:red, :green) }
106
- 20.times { cm.add_for(:blue, :red) }
107
- 5.times { cm.add_for(:blue, :blue) }
108
- 15.times { cm.add_for(:blue, :green) }
109
- 30.times { cm.add_for(:green, :red) }
110
- 12.times { cm.add_for(:green, :blue) }
111
- 8.times { cm.add_for(:green, :green) }
112
-
113
- assert_equal([:blue, :green, :red], cm.labels)
114
- assert_equal(112, cm.total)
115
- assert_equal(10, cm.true_positive(:red))
116
- assert_equal(12, cm.false_negative(:red))
117
- assert_equal(50, cm.false_positive(:red))
118
- assert_equal(13, cm.true_negative(:red))
119
- assert_equal(5, cm.true_positive(:blue))
120
- assert_equal(35, cm.false_negative(:blue))
121
- assert_equal(19, cm.false_positive(:blue))
122
- assert_equal(18, cm.true_negative(:blue))
123
- assert_equal(8, cm.true_positive(:green))
124
- assert_equal(42, cm.false_negative(:green))
125
- assert_equal(20, cm.false_positive(:green))
126
- assert_equal(15, cm.true_negative(:green))
127
- end
128
-
129
- def test_add_for_n
130
- cm = ConfusionMatrix.new
131
- cm.add_for(:pos, :pos, 3)
132
- cm.add_for(:pos, :neg)
133
- cm.add_for(:neg, :pos, 2)
134
- cm.add_for(:neg, :neg, 1)
135
- assert_equal(7, cm.total)
136
- assert_equal(3, cm.count_for(:pos, :pos))
137
- # - check errors
138
- assert_raises(ArgumentError) { cm.add_for(:pos, :pos, 0) }
139
- assert_raises(ArgumentError) { cm.add_for(:pos, :pos, -3) }
140
- assert_raises(ArgumentError) { cm.add_for(:pos, :pos, nil) }
141
- end
142
-
143
- def test_use_labels
144
- # - check errors
145
- assert_raises(ArgumentError) { ConfusionMatrix.new(:pos) }
146
- assert_raises(ArgumentError) { ConfusionMatrix.new(:pos, :pos) }
147
- # - check created matrix
148
- cm = ConfusionMatrix.new(:pos, :neg)
149
- assert_equal([:pos, :neg], cm.labels)
150
- assert_raises(ArgumentError) { cm.add_for(:pos, :nothing) }
151
- cm.add_for(:pos, :neg, 3)
152
- cm.add_for(:neg, :pos, 2)
153
- assert_equal(2, cm.false_negative(:neg))
154
- assert_equal(3, cm.false_negative(:pos))
155
- assert_equal(3, cm.false_negative())
156
- assert_raises(ArgumentError) { cm.false_negative(:nothing) }
157
- assert_raises(ArgumentError) { cm.false_negative(nil) }
158
- end
159
- end
160
-
1
+ require 'confusion_matrix'
2
+ require 'minitest/autorun'
3
+
4
+ class TestConfusionMatrix < Minitest::Test
5
+ def test_empty_case
6
+ cm = ConfusionMatrix.new
7
+ assert(0, cm.total)
8
+ assert(0, cm.true_positive(:none))
9
+ assert(0, cm.false_negative(:none))
10
+ assert(0, cm.false_positive(:none))
11
+ assert(0, cm.true_negative(:none))
12
+ assert_in_delta(0, cm.true_rate(:none))
13
+ end
14
+
15
+ def test_two_classes
16
+ cm = ConfusionMatrix.new
17
+ 10.times { cm.add_for(:pos, :pos) }
18
+ 5.times { cm.add_for(:pos, :neg) }
19
+ 20.times { cm.add_for(:neg, :neg) }
20
+ 5.times { cm.add_for(:neg, :pos) }
21
+
22
+ assert_equal([:neg, :pos], cm.labels)
23
+ assert_equal(10, cm.count_for(:pos, :pos))
24
+ assert_equal(5, cm.count_for(:pos, :neg))
25
+ assert_equal(20, cm.count_for(:neg, :neg))
26
+ assert_equal(5, cm.count_for(:neg, :pos))
27
+
28
+ assert_equal(40, cm.total)
29
+ assert_equal(10, cm.true_positive(:pos))
30
+ assert_equal(5, cm.false_negative(:pos))
31
+ assert_equal(5, cm.false_positive(:pos))
32
+ assert_equal(20, cm.true_negative(:pos))
33
+ assert_equal(20, cm.true_positive(:neg))
34
+ assert_equal(5, cm.false_negative(:neg))
35
+ assert_equal(5, cm.false_positive(:neg))
36
+ assert_equal(10, cm.true_negative(:neg))
37
+
38
+ assert_in_delta(0.6667, cm.true_rate(:pos))
39
+ assert_in_delta(0.8, cm.true_rate(:neg))
40
+ assert_in_delta(0.2, cm.false_rate(:pos))
41
+ assert_in_delta(0.3333, cm.false_rate(:neg))
42
+ assert_in_delta(0.6667, cm.precision(:pos))
43
+ assert_in_delta(0.8, cm.precision(:neg))
44
+ assert_in_delta(0.6667, cm.recall(:pos))
45
+ assert_in_delta(0.8, cm.recall(:neg))
46
+ assert_in_delta(0.6667, cm.sensitivity(:pos))
47
+ assert_in_delta(0.8, cm.sensitivity(:neg))
48
+ assert_in_delta(0.75, cm.overall_accuracy)
49
+ assert_in_delta(0.6667, cm.f_measure(:pos))
50
+ assert_in_delta(0.8, cm.f_measure(:neg))
51
+ assert_in_delta(0.7303, cm.geometric_mean)
52
+ end
53
+
54
+ # Example from:
55
+ # https://www.datatechnotes.com/2019/02/accuracy-metrics-in-classification.html
56
+ def test_two_classes_2
57
+ cm = ConfusionMatrix.new
58
+ 5.times { cm.add_for(:pos, :pos) }
59
+ 1.times { cm.add_for(:pos, :neg) }
60
+ 3.times { cm.add_for(:neg, :neg) }
61
+ 2.times { cm.add_for(:neg, :pos) }
62
+
63
+ assert_equal(11, cm.total)
64
+ assert_equal(5, cm.true_positive(:pos))
65
+ assert_equal(1, cm.false_negative(:pos))
66
+ assert_equal(2, cm.false_positive(:pos))
67
+ assert_equal(3, cm.true_negative(:pos))
68
+
69
+ assert_in_delta(0.7142, cm.precision(:pos))
70
+ assert_in_delta(0.8333, cm.recall(:pos))
71
+ assert_in_delta(0.7272, cm.overall_accuracy)
72
+ assert_in_delta(0.7692, cm.f_measure(:pos))
73
+ assert_in_delta(0.8333, cm.sensitivity(:pos))
74
+ assert_in_delta(0.6, cm.specificity(:pos))
75
+ assert_in_delta(0.4407, cm.kappa(:pos))
76
+ assert_in_delta(0.5454, cm.prevalence(:pos))
77
+ end
78
+
79
+ # Examples from:
80
+ # https://standardwisdom.com/softwarejournal/2011/12/matthews-correlation-coefficient-how-well-does-it-do/
81
+ def two_class_case(a,b,c,d,e,f,g,h,i)
82
+ cm = ConfusionMatrix.new
83
+ a.times { cm.add_for(:pos, :pos) }
84
+ b.times { cm.add_for(:pos, :neg) }
85
+ c.times { cm.add_for(:neg, :neg) }
86
+ d.times { cm.add_for(:neg, :pos) }
87
+
88
+ assert_in_delta(e, cm.matthews_correlation(:pos))
89
+ assert_in_delta(f, cm.precision(:pos))
90
+ assert_in_delta(g, cm.recall(:pos))
91
+ assert_in_delta(h, cm.f_measure(:pos))
92
+ assert_in_delta(i, cm.kappa(:pos))
93
+ end
94
+
95
+ def test_two_classes_3
96
+ two_class_case(100, 0, 900, 0, 1.0, 1.0, 1.0, 1.0, 1.0)
97
+ two_class_case(65, 35, 825, 75, 0.490, 0.4643, 0.65, 0.542, 0.4811)
98
+ two_class_case(50, 50, 700, 200, 0.192, 0.2, 0.5, 0.286, 0.1666)
99
+ end
100
+
101
+ def test_three_classes
102
+ cm = ConfusionMatrix.new
103
+ 10.times { cm.add_for(:red, :red) }
104
+ 7.times { cm.add_for(:red, :blue) }
105
+ 5.times { cm.add_for(:red, :green) }
106
+ 20.times { cm.add_for(:blue, :red) }
107
+ 5.times { cm.add_for(:blue, :blue) }
108
+ 15.times { cm.add_for(:blue, :green) }
109
+ 30.times { cm.add_for(:green, :red) }
110
+ 12.times { cm.add_for(:green, :blue) }
111
+ 8.times { cm.add_for(:green, :green) }
112
+
113
+ assert_equal([:blue, :green, :red], cm.labels)
114
+ assert_equal(112, cm.total)
115
+ assert_equal(10, cm.true_positive(:red))
116
+ assert_equal(12, cm.false_negative(:red))
117
+ assert_equal(50, cm.false_positive(:red))
118
+ assert_equal(13, cm.true_negative(:red))
119
+ assert_equal(5, cm.true_positive(:blue))
120
+ assert_equal(35, cm.false_negative(:blue))
121
+ assert_equal(19, cm.false_positive(:blue))
122
+ assert_equal(18, cm.true_negative(:blue))
123
+ assert_equal(8, cm.true_positive(:green))
124
+ assert_equal(42, cm.false_negative(:green))
125
+ assert_equal(20, cm.false_positive(:green))
126
+ assert_equal(15, cm.true_negative(:green))
127
+ end
128
+
129
+ def test_add_for_n
130
+ cm = ConfusionMatrix.new
131
+ cm.add_for(:pos, :pos, 3)
132
+ cm.add_for(:pos, :neg)
133
+ cm.add_for(:neg, :pos, 2)
134
+ cm.add_for(:neg, :neg, 1)
135
+ assert_equal(7, cm.total)
136
+ assert_equal(3, cm.count_for(:pos, :pos))
137
+ # - check errors
138
+ assert_raises(ArgumentError) { cm.add_for(:pos, :pos, 0) }
139
+ assert_raises(ArgumentError) { cm.add_for(:pos, :pos, -3) }
140
+ assert_raises(ArgumentError) { cm.add_for(:pos, :pos, nil) }
141
+ end
142
+
143
+ def test_use_labels
144
+ # - check errors
145
+ assert_raises(ArgumentError) { ConfusionMatrix.new(:pos) }
146
+ assert_raises(ArgumentError) { ConfusionMatrix.new(:pos, :pos) }
147
+ # - check created matrix
148
+ cm = ConfusionMatrix.new(:pos, :neg)
149
+ assert_equal([:pos, :neg], cm.labels)
150
+ assert_raises(ArgumentError) { cm.add_for(:pos, :nothing) }
151
+ cm.add_for(:pos, :neg, 3)
152
+ cm.add_for(:neg, :pos, 2)
153
+ assert_equal(2, cm.false_negative(:neg))
154
+ assert_equal(3, cm.false_negative(:pos))
155
+ assert_equal(3, cm.false_negative())
156
+ assert_raises(ArgumentError) { cm.false_negative(:nothing) }
157
+ assert_raises(ArgumentError) { cm.false_negative(nil) }
158
+ end
159
+ end
160
+
metadata CHANGED
@@ -1,34 +1,33 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: confusion_matrix
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Lane
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-02-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
- description: "A confusion matrix is used in data-mining as a summary of the performance
14
- of a\nclassification algorithm. This library allows the user to incrementally add
15
- \nresults to a confusion matrix, and then retrieve statistical information.\n"
12
+ description: A confusion matrix is used to represent predicted vs observed values
13
+ in a classification or recognition task. This library allows the user to incrementally
14
+ add results to a confusion matrix, and then retrieve statistical information.
16
15
  email: peterlane@gmx.com
17
16
  executables: []
18
17
  extensions: []
19
18
  extra_rdoc_files:
20
- - README.rdoc
21
19
  - LICENSE.rdoc
20
+ - README.rdoc
22
21
  files:
23
22
  - LICENSE.rdoc
24
23
  - README.rdoc
25
24
  - lib/confusion_matrix.rb
26
25
  - test/matrix_test.rb
27
- homepage:
26
+ homepage: https://rubygems.org/gems/confusion_matrix
28
27
  licenses:
29
28
  - MIT
30
- metadata: {}
31
- post_install_message:
29
+ metadata:
30
+ source_code_uri: https://codeberg.org/peterlane/confusion-matrix
32
31
  rdoc_options:
33
32
  - "-m"
34
33
  - README.rdoc
@@ -39,17 +38,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
39
38
  - - ">="
40
39
  - !ruby/object:Gem::Version
41
40
  version: '2.5'
42
- - - "<"
43
- - !ruby/object:Gem::Version
44
- version: '4.0'
45
41
  required_rubygems_version: !ruby/object:Gem::Requirement
46
42
  requirements:
47
43
  - - ">="
48
44
  - !ruby/object:Gem::Version
49
45
  version: '0'
50
46
  requirements: []
51
- rubygems_version: 3.4.5
52
- signing_key:
47
+ rubygems_version: 3.6.9
53
48
  specification_version: 4
54
49
  summary: Construct a confusion matrix and retrieve statistical information from it.
55
50
  test_files: []