@@ -59,11 +59,15 @@ class RSquare(Metric):
59
59
](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.r2_score.html)
60
60
of the same metric.
61
61
62
+ Can also calculate the Adjusted R2 Score.
63
+
62
64
Args:
63
65
multioutput: `string`, the reduce method for scores.
64
66
Should be one of `["raw_values", "uniform_average", "variance_weighted"]`.
65
67
name: (Optional) string name of the metric instance.
66
68
dtype: (Optional) data type of the metric result.
69
+ num_regressors: (Optional) Number of indepedent regressors used (Adjusted R2).
70
+ Defaults to zero(standard R2 score).
67
71
68
72
Usage:
69
73
@@ -83,6 +87,7 @@ def __init__(
83
87
dtype : AcceptableDTypes = None ,
84
88
y_shape : Tuple [int , ...] = (),
85
89
multioutput : str = "uniform_average" ,
90
+ num_regressors : tf .int32 = 0 ,
86
91
** kwargs ,
87
92
):
88
93
super ().__init__ (name = name , dtype = dtype , ** kwargs )
@@ -95,6 +100,7 @@ def __init__(
95
100
)
96
101
)
97
102
self .multioutput = multioutput
103
+ self .num_regressors = num_regressors
98
104
self .squared_sum = self .add_weight (
99
105
name = "squared_sum" , shape = y_shape , initializer = "zeros" , dtype = dtype
100
106
)
@@ -107,6 +113,7 @@ def __init__(
107
113
self .count = self .add_weight (
108
114
name = "count" , shape = y_shape , initializer = "zeros" , dtype = dtype
109
115
)
116
+ self .num_samples = self .add_weight (name = "num_samples" , dtype = tf .int32 )
110
117
111
118
def update_state (self , y_true , y_pred , sample_weight = None ) -> None :
112
119
y_true = tf .cast (y_true , dtype = self ._dtype )
@@ -125,6 +132,7 @@ def update_state(self, y_true, y_pred, sample_weight=None) -> None:
125
132
tf .reduce_sum ((y_true - y_pred ) ** 2 * sample_weight , axis = 0 )
126
133
)
127
134
self .count .assign_add (tf .reduce_sum (sample_weight , axis = 0 ))
135
+ self .num_samples .assign_add (tf .size (y_true ))
128
136
129
137
def result (self ) -> tf .Tensor :
130
138
mean = self .sum / self .count
@@ -133,11 +141,42 @@ def result(self) -> tf.Tensor:
133
141
raw_scores = tf .where (tf .math .is_inf (raw_scores ), 0.0 , raw_scores )
134
142
135
143
if self .multioutput == "raw_values" :
136
- return raw_scores
137
- if self .multioutput == "uniform_average" :
138
- return tf .reduce_mean (raw_scores )
139
- if self .multioutput == "variance_weighted" :
140
- return _reduce_average (raw_scores , weights = total )
144
+ r2_score = raw_scores
145
+ elif self .multioutput == "uniform_average" :
146
+ r2_score = tf .reduce_mean (raw_scores )
147
+ elif self .multioutput == "variance_weighted" :
148
+ r2_score = _reduce_average (raw_scores , weights = total )
149
+ else :
150
+ raise RuntimeError (
151
+ "The multioutput attribute must be one of {}, but was: {}" .format (
152
+ _VALID_MULTIOUTPUT , self .multioutput
153
+ )
154
+ )
155
+
156
+ if self .num_regressors < 0 :
157
+ raise ValueError (
158
+ "num_regressors parameter should be greater than or equal to zero"
159
+ )
160
+
161
+ if self .num_regressors != 0 :
162
+ if self .num_regressors > self .num_samples - 1 :
163
+ UserWarning (
164
+ "More independent predictors than datapoints in adjusted r2 score. Falls back to standard r2 "
165
+ "score."
166
+ )
167
+ elif self .num_regressors == self .num_samples - 1 :
168
+ UserWarning (
169
+ "Division by zero in adjusted r2 score. Falls back to standard r2 score."
170
+ )
171
+ else :
172
+ n = tf .cast (self .num_samples , dtype = tf .float32 )
173
+ p = tf .cast (self .num_regressors , dtype = tf .float32 )
174
+
175
+ num = tf .multiply (tf .subtract (1.0 , r2_score ), tf .subtract (n , 1.0 ))
176
+ den = tf .subtract (tf .subtract (n , p ), 1.0 )
177
+ r2_score = tf .subtract (1.0 , tf .divide (num , den ))
178
+
179
+ return r2_score
141
180
142
181
def reset_states (self ) -> None :
143
182
# The state of the metric will be reset at the start of each epoch.
0 commit comments