1- import os
2- from os .path import dirname as up
1+ from importlib .resources import files
32
43import numpy as np
54import scipy .stats as stats
98from sklearn .preprocessing import MinMaxScaler
109from sklearn .utils import check_array
1110
12- from pythresh .utils .rank_utility import (
13- BREG_metric ,
14- Contam_score ,
15- GNB_score ,
16- mclain_rao_index
17- )
11+ from pythresh .utils .rank_utility import BREG_metric , Contam_score , GNB_score , mclain_rao_index
1812
1913
20- class RANK () :
14+ class RANK :
2115 """RANK class for ranking outlier detection and thresholding methods.
2216
23- Use the RANK class to rank outlier detection and thresholding methods' capabilities
24- to provide the best matthews correlation with respect to the
25- selected threshold method
26-
27- Parameters
28- ----------
17+ Use the RANK class to rank outlier detection and thresholding methods' capabilities
18+ to provide the best matthews correlation with respect to the
19+ selected threshold method
2920
21+ Parameters
22+ ----------
3023 od_models : {list of pyod.model classes}
3124
32- thresh : {pythresh.threshold class, float, int, list of pythresh.threshold classes, list of floats, list of ints}
33-
34- method : {'model', 'native'}, optional (default='model')
25+ thresh : {pythresh.threshold class, float, int, list of pythresh.threshold classes, list of floats, list of ints}
3526
36- weights : list of shape 3, optional (default=None)
37- These weights are applied to the combined rank score. The first
38- is for the cdf rankings, the second for the clust rankings, and
39- the third for the mode rankings. Default applies equal weightings
40- to all proxy-metrics. Only applies when method = 'native'.
27+ method : {'model', 'native'}, optional (default='model')
4128
42- Attributes
43- ----------
29+ weights : list of shape 3, optional (default=None)
30+ These weights are applied to the combined rank score. The first
31+ is for the cdf rankings, the second for the clust rankings, and
32+ the third for the mode rankings. Default applies equal weightings
33+ to all proxy-metrics. Only applies when method = 'native'.
4434
35+ Attributes
36+ ----------
4537 cdf_rank_ : list of tuples shape (2, n_od_models) of cdf based rankings
4638
47- clust_rank_ : list of tuples shape (2, n_od_models) of cluster based rankings
48-
49- consensus_rank_ : list of tuples shape (2, n_od_models) of consensus based rankings
39+ clust_rank_ : list of tuples shape (2, n_od_models) of cluster based rankings
5040
51- Notes
52- -----
41+ consensus_rank_ : list of tuples shape (2, n_od_models) of consensus based rankings
5342
43+ Notes
44+ -----
5445 The RANK class ranks the outlier detection methods by evaluating
55- three distinct proxy-metrics. The first proxy-metric looks at the outlier
56- likelihood scores by class and measures the cumulative distribution
57- separation using the the Wasserstein distance, and the Exponential Euclidean
58- Bregman distance. The second proxy-metric looks at the relationship between the
59- fitted features (X) and the evaluated classes (y) using the Calinski-Harabasz scores
60- and between the outlier likihood score and the evaluated classes using the
61- Mclain Rao Index. The third proxy-metric evaluates the class difference for each outlier
62- detection and thresholding method with respect to consensus based metrics of all the evaluated
63- outlier detection class labels. This is done using the mean contamination deviation based on
64- TruncatedSVD decomposed scores and Gaussian Naive-Bayes trained consensus score
65-
66- Each proxy-metric is ranked separately and a final ranking is applied
67- using all three proxy-metric to get a single ranked result of each
68- outlier detection and thresholding method using the 'native' method. The model method uses
69- a trained LambdaMART ranking model using all the proxy-metrics as input.
70-
71- Please note that the data is standardized using
72- ``from pyod.utils.utility import standardizer`` during this ranking process
73-
74- Examples
75- --------
76-
77- .. code:: python
78-
79- # Import libraries
80- from pyod.models.knn import KNN
81- from pyod.models.iforest import IForest
82- from pyod.models.pca import PCA
83- from pyod.models.mcd import MCD
84- from pyod.models.qmcd import QMCD
85- from pythresh.thresholds.filter import FILTER
86- from pythresh.utils.ranking import RANK
87-
88- # Initialize models
89- clfs = [KNN(), IForest(), PCA(), MCD(), QMCD()]
90- thres = FILTER()
91-
92- # Get rankings
93- ranker = RANK(clfs, thres)
94- rankings = ranker.eval(X)
46+ three distinct proxy-metrics. The first proxy-metric looks at the outlier
47+ likelihood scores by class and measures the cumulative distribution
48+ separation using the the Wasserstein distance, and the Exponential Euclidean
49+ Bregman distance. The second proxy-metric looks at the relationship between the
50+ fitted features (X) and the evaluated classes (y) using the Calinski-Harabasz scores
51+ and between the outlier likihood score and the evaluated classes using the
52+ Mclain Rao Index. The third proxy-metric evaluates the class difference for each outlier
53+ detection and thresholding method with respect to consensus based metrics of all the evaluated
54+ outlier detection class labels. This is done using the mean contamination deviation based on
55+ TruncatedSVD decomposed scores and Gaussian Naive-Bayes trained consensus score
56+
57+ Each proxy-metric is ranked separately and a final ranking is applied
58+ using all three proxy-metric to get a single ranked result of each
59+ outlier detection and thresholding method using the 'native' method. The model method uses
60+ a trained LambdaMART ranking model using all the proxy-metrics as input.
61+
62+ Please note that the data is standardized using
63+ ``from pyod.utils.utility import standardizer`` during this ranking process
64+
65+ Examples
66+ --------
67+
68+ .. code:: python
69+
70+ # Import libraries
71+ from pyod.models.knn import KNN
72+ from pyod.models.iforest import IForest
73+ from pyod.models.pca import PCA
74+ from pyod.models.mcd import MCD
75+ from pyod.models.qmcd import QMCD
76+ from pythresh.thresholds.filter import FILTER
77+ from pythresh.utils.ranking import RANK
78+
79+ # Initialize models
80+ clfs = [KNN(), IForest(), PCA(), MCD(), QMCD()]
81+ thres = FILTER()
82+
83+ # Get rankings
84+ ranker = RANK(clfs, thres)
85+ rankings = ranker.eval(X)
9586 """
9687
9788 def __init__ (self , od_models , thresh , method = 'model' , weights = None ):
@@ -119,7 +110,6 @@ def eval(self, X):
119110 thresholder ranked from best to worst in terms of
120111 performance
121112 """
122-
123113 X = check_array (X , ensure_2d = True )
124114 X = standardizer (X )
125115
@@ -193,9 +183,9 @@ def eval(self, X):
193183
194184 # Load trained ranking model
195185 clf = 'rank_model_XGB.json'
196- parent = up ( up ( __file__ ) )
186+ model_path = files ( 'pythresh.models' ). joinpath ( clf )
197187 ranker = xgb .XGBRanker ()
198- ranker .load_model (os . path . join ( parent , 'models' , clf ) )
188+ ranker .load_model (model_path )
199189
200190 # Transform data
201191 scaler = MinMaxScaler ()
@@ -217,7 +207,6 @@ def eval(self, X):
217207
218208 def _cdf_metric (self , scores , labels ):
219209 """Calculate CDF based metrics."""
220-
221210 if len (np .unique (labels )) == 1 :
222211 return [- 1e6 , - 1e6 ]
223212
@@ -254,7 +243,6 @@ def _cdf_metric(self, scores, labels):
254243
255244 def _clust_metric (self , X , scores , labels ):
256245 """Calculate clustering based metrics."""
257-
258246 if len (np .unique (labels )) == 1 :
259247 return [- 1e6 , - 1e6 ]
260248
@@ -265,15 +253,13 @@ def _clust_metric(self, X, scores, labels):
265253
266254 def _consensus_metric (self , X , scores , labels , contam ):
267255 """Calculate consensus based metrics."""
268-
269256 gnb = GNB_score (X , labels )
270257 contam = Contam_score (scores , labels , contam )
271258
272259 return np .vstack ([gnb , contam ]).T .tolist ()
273260
274261 def _equi_rank (self , data , order ):
275262 """Get equally weighted rankings from metrics."""
276-
277263 # Get indexes of best to worst for data
278264 sortings = []
279265
@@ -292,10 +278,9 @@ def _equi_rank(self, data, order):
292278
293279 def _rank_sort (self , sortings , weights ):
294280 """Sort weighted rankings."""
295-
296281 # Get unique index values for ranking
297282 unique_values = {value for ls in sortings for value in ls }
298- scores = { value : 0 for value in unique_values }
283+ scores = dict . fromkeys ( unique_values , 0 )
299284
300285 # Get equally weighted rank
301286 for value in unique_values :
0 commit comments