refs-mcc 1.0.0__py3-none-any.whl

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.
aBioInf100.py ADDED
@@ -0,0 +1,58 @@
1
+ from features import *
2
+ from reduceData import *
3
+
4
+ from joblib import Parallel, delayed
5
+ import multiprocessing
6
+ import time
7
+ import argparse
8
+
9
+ def mainRun(indexRun, numberOfFolds) :
10
+ run=indexRun
11
+ start_time = time.time()
12
+ globalAnt=0.0
13
+ globalIndex=0
14
+ globalAccuracy=0.0
15
+
16
+ X, y, biomarkerNames = loadDatasetOriginal(run)
17
+
18
+ if (int(len(X[0]))>1000):
19
+ numberOfTopFeatures = 1000
20
+ else :
21
+ numberOfTopFeatures = int(len(X[0])*0.80)
22
+
23
+ variableSize=numberOfTopFeatures;
24
+ while True:
25
+ globalAnt=globalAccuracy
26
+ globalAccuracy=featureSelection(globalIndex,variableSize, run,numberOfFolds)
27
+ print(globalAccuracy)
28
+ print(globalIndex)
29
+ print(variableSize)
30
+ size,sizereduced=reduceDataset(globalIndex, run)
31
+
32
+ if(variableSize==0):
33
+ break
34
+ variableSize=int(variableSize*0.80)
35
+
36
+ globalIndex=globalIndex + 1
37
+
38
+ elapsed_time = time.time() - start_time
39
+ print("time")
40
+ print(elapsed_time)
41
+ return
42
+
43
+ def main(threads, totalRuns, numberOfFolds) :
44
+ Parallel(n_jobs=threads, verbose=5, backend="multiprocessing")(delayed(mainRun)(i, numberOfFolds) for i in range(0,totalRuns))
45
+ return
46
+
47
+ if __name__ == "__main__" :
48
+ parser = argparse.ArgumentParser(description="Run REFS-MCC - part 1")
49
+ parser.add_argument('--threads', type=int, default=10, help='Number of threads (default: 10)')
50
+ parser.add_argument('--totalRuns', type=int, default=10, help='Total number of runs (default: 10)')
51
+ parser.add_argument('--folds', type=int, default=10, help='Number of folds (default: 10)')
52
+ args = parser.parse_args()
53
+
54
+ threads=args.threads
55
+ totalRuns=args.totalRuns
56
+ numberOfFolds=args.folds
57
+
58
+ sys.exit( main(threads, totalRuns, numberOfFolds) )
classifiersMulti.py ADDED
@@ -0,0 +1,227 @@
1
+ import copy
2
+ import datetime
3
+ import logging
4
+ import numpy as np
5
+ import os
6
+ import sys
7
+ import pandas as pd
8
+ import argparse
9
+
10
+ from sklearn.ensemble import AdaBoostClassifier
11
+ from sklearn.ensemble import BaggingClassifier
12
+ from sklearn.ensemble import ExtraTreesClassifier
13
+ from sklearn.ensemble import GradientBoostingClassifier
14
+ from sklearn.ensemble import RandomForestClassifier
15
+
16
+ from sklearn.linear_model import ElasticNet
17
+ from sklearn.linear_model import ElasticNetCV
18
+ from sklearn.linear_model import Lasso
19
+ from sklearn.linear_model import LassoCV
20
+ from sklearn.linear_model import LogisticRegression
21
+ from sklearn.linear_model import LogisticRegressionCV
22
+ from sklearn.linear_model import PassiveAggressiveClassifier
23
+ from sklearn.linear_model import RidgeClassifier
24
+ from sklearn.linear_model import RidgeClassifierCV
25
+ from sklearn.linear_model import SGDClassifier
26
+
27
+ from sklearn.multiclass import OneVsOneClassifier
28
+ from sklearn.multiclass import OneVsRestClassifier
29
+ from sklearn.multiclass import OutputCodeClassifier
30
+
31
+ from sklearn.naive_bayes import BernoulliNB
32
+ from sklearn.naive_bayes import GaussianNB
33
+ from sklearn.naive_bayes import MultinomialNB
34
+
35
+ from sklearn.neighbors import KNeighborsClassifier
36
+ from sklearn.neighbors import NearestCentroid
37
+ from sklearn.neighbors import RadiusNeighborsClassifier
38
+
39
+ from sklearn.svm import SVC
40
+
41
+ from sklearn.tree import DecisionTreeClassifier
42
+ from sklearn.tree import ExtraTreeClassifier
43
+ from sklearn.neural_network import MLPClassifier
44
+
45
+ # used for normalization
46
+ from sklearn.preprocessing import Normalizer
47
+ from sklearn.preprocessing import StandardScaler
48
+ from sklearn.preprocessing import MinMaxScaler
49
+ # used for cross-validation
50
+ from sklearn.model_selection import StratifiedKFold
51
+ from sklearn.metrics import roc_curve, auc
52
+ from numpy import interp
53
+ import matplotlib.pyplot as plt
54
+ from pandas import read_csv
55
+
56
+ from statsmodels.multivariate.manova import MANOVA
57
+ import statsmodels.api as sm
58
+ from scipy import stats
59
+ from sklearn.metrics import f1_score
60
+ def loadDataset() :
61
+
62
+ # data used for the predictions
63
+ dfData = read_csv("./best/data_0.csv", header=None, sep=',')
64
+ dfLabels = read_csv("./best/labels.csv", header=None)
65
+
66
+ return dfData.values, dfLabels.values.ravel() # to have it in the format that the classifiers like
67
+
68
+
69
+ def runFeatureReduce(numberOfFolds) :
70
+
71
+ # list of classifiers, selected on the basis of our previous paper "
72
+ classifierList = [
73
+
74
+ [GradientBoostingClassifier(n_estimators=300), "GradientBoostingClassifier(n_estimators=300)"],
75
+ [RandomForestClassifier(n_estimators=300), "RandomForestClassifier(n_estimators=300)"],
76
+ [LogisticRegression(solver='lbfgs',), "LogisticRegression"],
77
+ [PassiveAggressiveClassifier(),"PassiveAggressiveClassifier"],
78
+ [SGDClassifier(), "SGDClassifier"],
79
+ [SVC(kernel='linear'), "SVC(linear)"],
80
+ [RidgeClassifier(), "RidgeClassifier"],
81
+ [BaggingClassifier(n_estimators=300), "BaggingClassifier(n_estimators=300)"],
82
+ # ensemble
83
+ #[AdaBoostClassifier(), "AdaBoostClassifier"],
84
+ #[AdaBoostClassifier(n_estimators=300), "AdaBoostClassifier(n_estimators=300)"],
85
+ #[AdaBoostClassifier(n_estimators=1500), "AdaBoostClassifier(n_estimators=1500)"],
86
+ #[BaggingClassifier(), "BaggingClassifier"],
87
+
88
+ #[ExtraTreesClassifier(), "ExtraTreesClassifier"],
89
+ #[ExtraTreesClassifier(n_estimators=300), "ExtraTreesClassifier(n_estimators=300)"],
90
+ # features_importances_
91
+ #[GradientBoostingClassifier(n_estimators=300), "GradientBoostingClassifier(n_estimators=300)"],
92
+ #[GradientBoostingClassifier(n_estimators=1000), "GradientBoostingClassifier(n_estimators=1000)"],
93
+
94
+ #[RandomForestClassifier(n_estimators=300), "RandomForestClassifier(n_estimators=300)"],
95
+ #[RandomForestClassifier(n_estimators=1000), "RandomForestClassifier(n_estimators=1000)"], # features_importances_
96
+
97
+ # linear
98
+ #[ElasticNet(), "ElasticNet"],
99
+ #[ElasticNetCV(), "ElasticNetCV"],
100
+ #[Lasso(), "Lasso"],
101
+ #[LassoCV(), "LassoCV"],
102
+ # coef_
103
+ #[LogisticRegressionCV(), "LogisticRegressionCV"],
104
+ # coef_
105
+ # coef_
106
+ #[RidgeClassifierCV(), "RidgeClassifierCV"],
107
+ # coef_
108
+ # coef_, but only if the kernel is linear...the default is 'rbf', which is NOT linear
109
+
110
+ # naive Bayes
111
+ #[BernoulliNB(), "BernoulliNB"],
112
+ #[GaussianNB(), "GaussianNB"],
113
+ #[MultinomialNB(), "MultinomialNB"],
114
+
115
+ # neighbors
116
+ #[KNeighborsClassifier(), "KNeighborsClassifier"], # no way to return feature importance
117
+ # TODO this one creates issues
118
+ #[NearestCentroid(), "NearestCentroid"], # it does not have some necessary methods, apparently
119
+ #[RadiusNeighborsClassifier(), "RadiusNeighborsClassifier"],
120
+
121
+ # tree
122
+ #[DecisionTreeClassifier(), "DecisionTreeClassifier"],
123
+ #[ExtraTreeClassifier(), "ExtraTreeClassifier"],
124
+ [AdaBoostClassifier(n_estimators=300), "AdaBoostClassifier(n_estimators=300)"],
125
+ [ExtraTreesClassifier(n_estimators=300), "ExtraTreesClassifier(n_estimators=300)"],
126
+ [KNeighborsClassifier(), "KNeighborsClassifier"],
127
+ #[LassoCV(), "LassoCV"],
128
+ [MLPClassifier(), "MLPClassifier"],
129
+ [LassoCV(), "LassoCV"]
130
+ ]
131
+
132
+ # this is just a hack to check a few things
133
+ #classifierList = [
134
+ # [RandomForestClassifier(), "RandomForestClassifier"]
135
+ # ]
136
+
137
+ print("Loading dataset...")
138
+ X, y = loadDataset()
139
+
140
+ print(len(X))
141
+ print(len(X[0]))
142
+ print(len(y))
143
+
144
+
145
+ labels=np.max(y)+1
146
+ # prepare folds
147
+ skf = StratifiedKFold(n_splits=numberOfFolds, shuffle=True)
148
+ indexes = [ (training, test) for training, test in skf.split(X, y) ]
149
+
150
+ # this will be used for the top features
151
+ topFeatures = dict()
152
+
153
+ # iterate over all classifiers
154
+ classifierIndex = 0
155
+
156
+
157
+
158
+
159
+ for originalClassifier, classifierName in classifierList :
160
+
161
+ print("\nClassifier " + classifierName)
162
+ classifierPerformance = []
163
+ F1score= []
164
+
165
+ cMatrix=np.zeros((labels, labels))
166
+ # iterate over all folds
167
+
168
+ indexFold = 0
169
+
170
+ yTest=[]
171
+ yNew=[]
172
+
173
+ for train_index, test_index in indexes :
174
+
175
+ X_train, X_test = X[train_index], X[test_index]
176
+ y_train, y_test = y[train_index], y[test_index]
177
+
178
+ # let's normalize, anyway
179
+ # MinMaxScaler StandardScaler Normalizer
180
+ scaler = StandardScaler()
181
+ X_train = scaler.fit_transform(X_train)
182
+ X_test = scaler.transform(X_test)
183
+
184
+
185
+
186
+ classifier = copy.deepcopy(originalClassifier)
187
+ classifier.fit(X_train, y_train)
188
+ scoreTraining = classifier.score(X_train, y_train)
189
+ scoreTest = classifier.score(X_test, y_test)
190
+
191
+ y_new = classifier.predict(X_test)
192
+
193
+
194
+
195
+ yNew.append(y_new)
196
+ yTest.append(y_test)
197
+
198
+
199
+ for i in range(0,len(y_new)):
200
+ cMatrix[y_test[i]][round(y_new[i])]+=1
201
+ y_new[i]=round(y_new[i])
202
+
203
+ print("\ttraining: %.4f, test: %.4f" % (scoreTraining, scoreTest))
204
+ classifierPerformance.append( scoreTest )
205
+
206
+
207
+ F1scoreTest = f1_score(y_test, y_new, average='weighted')
208
+ F1score.append(F1scoreTest)
209
+
210
+ pd.DataFrame(cMatrix).to_csv("./best/cMatrix"+str(classifierIndex)+".csv", header=None, index =None)
211
+ classifierIndex+=1
212
+ line ="%s \t %.4f \t %.4f \t %.4f \t %.4f\n" % (classifierName, np.mean(classifierPerformance), np.std(classifierPerformance), np.mean(F1score), np.std(F1score))
213
+
214
+
215
+ print(line)
216
+ fo = open("./best/results.txt", 'a')
217
+ fo.write( line )
218
+ fo.close()
219
+
220
+ return
221
+
222
+ if __name__ == "__main__" :
223
+ parser = argparse.ArgumentParser(description="Run multiple classifiers based on the best run")
224
+ parser.add_argument('--folds', type=int, default=10, help='Number of folds (default: 10)')
225
+ args = parser.parse_args()
226
+
227
+ sys.exit( runFeatureReduce(args.folds) )
features.py ADDED
@@ -0,0 +1,354 @@
1
+ import copy
2
+ import datetime
3
+ import logging
4
+ import numpy as np
5
+ import os
6
+ import sys
7
+
8
+ from sklearn.ensemble import AdaBoostClassifier
9
+ from sklearn.ensemble import BaggingClassifier
10
+ from sklearn.ensemble import ExtraTreesClassifier
11
+ from sklearn.ensemble import GradientBoostingClassifier
12
+ from sklearn.ensemble import RandomForestClassifier
13
+
14
+ from sklearn.linear_model import ElasticNet
15
+ from sklearn.linear_model import ElasticNetCV
16
+ from sklearn.linear_model import Lasso
17
+ from sklearn.linear_model import LassoCV
18
+ from sklearn.linear_model import LogisticRegression
19
+ from sklearn.linear_model import LogisticRegressionCV
20
+ from sklearn.linear_model import PassiveAggressiveClassifier
21
+ from sklearn.linear_model import RidgeClassifier
22
+ from sklearn.linear_model import RidgeClassifierCV
23
+ from sklearn.linear_model import SGDClassifier
24
+
25
+ from sklearn.multiclass import OneVsOneClassifier
26
+ from sklearn.multiclass import OneVsRestClassifier
27
+ from sklearn.multiclass import OutputCodeClassifier
28
+
29
+ from sklearn.naive_bayes import BernoulliNB
30
+ from sklearn.naive_bayes import GaussianNB
31
+ from sklearn.naive_bayes import MultinomialNB
32
+
33
+ from sklearn.neighbors import KNeighborsClassifier
34
+ from sklearn.neighbors import NearestCentroid
35
+ from sklearn.neighbors import RadiusNeighborsClassifier
36
+
37
+ from sklearn.svm import SVC
38
+
39
+ from sklearn.tree import DecisionTreeClassifier
40
+ from sklearn.tree import ExtraTreeClassifier
41
+
42
+ # used for normalization
43
+ from sklearn.preprocessing import StandardScaler
44
+
45
+ # used for cross-validation
46
+ from sklearn.model_selection import StratifiedKFold
47
+ from sklearn.metrics import matthews_corrcoef
48
+
49
+ from pandas import read_csv
50
+ import pandas as pd
51
+
52
+ def loadDatasetOriginal(run) :
53
+
54
+ # data used for the predictions
55
+ dfData = read_csv("../data/data_0.csv", header=None, sep=',')
56
+ dfLabels = read_csv("../data/labels.csv", header=None)
57
+ biomarkers = read_csv("../data/features_0.csv", header=None)
58
+
59
+ # create folder
60
+ folderName ="./run"+str(run)+"/"
61
+ if not os.path.exists(folderName) : os.makedirs(folderName)
62
+
63
+ pd.DataFrame(dfData.values).to_csv("./run"+str(run)+"/data_0.csv", header=None, index =None)
64
+ pd.DataFrame(biomarkers.values.ravel()).to_csv("./run"+str(run)+"/features_0.csv", header=None, index =None)
65
+ pd.DataFrame(dfLabels.values.ravel()).to_csv("./run"+str(run)+"/labels.csv", header=None, index =None)
66
+ return dfData.values, dfLabels.values.ravel(), biomarkers.values.ravel() # to have it in the format that the classifiers like
67
+
68
+
69
+ def loadDataset(globalIndex, run) :
70
+
71
+ # data used for the predictions
72
+ dfData = read_csv("./run"+str(run)+"/data_"+str(globalIndex)+".csv", header=None, sep=',')
73
+ dfLabels = read_csv("./run"+str(run)+"/labels.csv", header=None)
74
+ biomarkers = read_csv("./run"+str(run)+"/features_"+str(globalIndex)+".csv", header=None)
75
+
76
+ return dfData.values, dfLabels.values.ravel(), biomarkers.values.ravel() # to have it in the format that the classifiers like
77
+
78
+ # this function returns a list of features, in relative order of importance
79
+ def relativeFeatureImportance(classifier) :
80
+
81
+ # this is the output; it will be a sorted list of tuples (importance, index)
82
+ # the index is going to be used to find the "true name" of the feature
83
+ orderedFeatures = []
84
+
85
+ # the simplest case: the classifier already has a method that returns relative importance of features
86
+ if hasattr(classifier, "feature_importances_") :
87
+
88
+ orderedFeatures = zip(classifier.feature_importances_ , range(0, len(classifier.feature_importances_)))
89
+ orderedFeatures = sorted(orderedFeatures, key = lambda x : x[0], reverse=True)
90
+
91
+ # some classifiers are ensembles, and if each element in the ensemble is able to return a list of feature importances
92
+ # (that are going to be all scored following the same logic, so they could be easily aggregated, in theory)
93
+ elif hasattr(classifier, "estimators_") and hasattr(classifier.estimators_[0], "feature_importances_") :
94
+
95
+ # add up the scores given by each estimator to all features
96
+ global_score = np.zeros(classifier.estimators_[0].feature_importances_.shape[0])
97
+
98
+ for estimator in classifier.estimators_ :
99
+ for i in range(0, estimator.feature_importances_.shape[0]) :
100
+ global_score[i] += estimator.feature_importances_[i]
101
+
102
+ # "normalize", dividing by the number of estimators
103
+ for i in range(0, global_score.shape[0]) : global_score[i] /= len(classifier.estimators_)
104
+
105
+ # proceed as above to obtain the ranked list of features
106
+ orderedFeatures = zip(global_score, range(0, len(global_score)))
107
+ orderedFeatures = sorted(orderedFeatures, key = lambda x : x[0], reverse=True)
108
+
109
+ # the classifier does not have "feature_importances_" but can return a list
110
+ # of all features used by a lot of estimators (typical of ensembles)
111
+ elif hasattr(classifier, "estimators_features_") :
112
+
113
+ numberOfFeaturesUsed = 0
114
+ featureFrequency = dict()
115
+ for listOfFeatures in classifier.estimators_features_ :
116
+ for feature in listOfFeatures :
117
+ if feature in featureFrequency :
118
+ featureFrequency[feature] += 1
119
+ else :
120
+ featureFrequency[feature] = 1
121
+ numberOfFeaturesUsed += len(listOfFeatures)
122
+
123
+ for feature in featureFrequency :
124
+ featureFrequency[feature] /= numberOfFeaturesUsed
125
+
126
+ # prepare a list of tuples (name, value), to be sorted
127
+ orderedFeatures = [ (featureFrequency[feature], feature) for feature in featureFrequency ]
128
+ orderedFeatures = sorted(orderedFeatures, key=lambda x : x[0], reverse=True)
129
+
130
+ # the classifier does not even have the "estimators_features_", but it's
131
+ # some sort of linear/hyperplane classifier, so it does have a list of
132
+ # coefficients; for the coefficients, the absolute value might be relevant
133
+ elif hasattr(classifier, "coef_") :
134
+
135
+ # now, "coef_" is usually multi-dimensional, so we iterate on
136
+ # all dimensions, and take a look at the features whose coefficients
137
+ # more often appear close to the top; but it could be mono-dimensional,
138
+ # so we need two special cases
139
+ dimensions = len(classifier.coef_.shape)
140
+ #print("dimensions=", len(dimensions))
141
+ featureFrequency = None # to be initialized later
142
+
143
+ # check on the dimensions
144
+ if dimensions == 1 :
145
+ featureFrequency = np.zeros(len(classifier.coef_))
146
+
147
+ relativeFeatures = zip(classifier.coef_, range(0, len(classifier.coef_)))
148
+ relativeFeatures = sorted(relativeFeatures, key=lambda x : abs(x[0]), reverse=True)
149
+
150
+ for index, values in enumerate(relativeFeatures) :
151
+ value, feature = values
152
+ featureFrequency[feature] += 1/(1+index)
153
+
154
+ elif dimensions > 1 :
155
+ featureFrequency = np.zeros(len(classifier.coef_[0]))
156
+
157
+ # so, for each dimension (corresponding to a class, I guess)
158
+ for i in range(0, len(classifier.coef_)) :
159
+ # we give a bonus to the feature proportional to
160
+ # its relative order, good ol' 1/(1+index)
161
+ relativeFeatures = zip(classifier.coef_[i], range(0, len(classifier.coef_[i])))
162
+ relativeFeatures = sorted(relativeFeatures, key=lambda x : abs(x[0]), reverse=True)
163
+
164
+ for index, values in enumerate(relativeFeatures) :
165
+ value, feature = values
166
+ featureFrequency[feature] += 1/(1+index)
167
+
168
+ # finally, let's sort
169
+ orderedFeatures = [ (featureFrequency[feature], feature) for feature in range(0, len(featureFrequency)) ]
170
+ orderedFeatures = sorted(orderedFeatures, key=lambda x : x[0], reverse=True)
171
+
172
+ else :
173
+ print("The classifier does not have any way to return a list with the relative importance of the features")
174
+
175
+ return np.array(orderedFeatures)
176
+
177
+ def featureSelection(globalIndex, variableSize,run, numberOfFolds) :
178
+
179
+ classifierList = [
180
+ # ensemble
181
+ #[AdaBoostClassifier(), "AdaBoostClassifier"],
182
+ #[AdaBoostClassifier(n_estimators=300), "AdaBoostClassifier(n_estimators=300)"],
183
+ #[AdaBoostClassifier(n_estimators=1500), "AdaBoostClassifier(n_estimators=1500)"],
184
+ #[BaggingClassifier(), "BaggingClassifier"],
185
+
186
+ [GradientBoostingClassifier(n_estimators=300), "GradientBoostingClassifier(n_estimators=300)"],
187
+ [RandomForestClassifier(n_estimators=300), "RandomForestClassifier(n_estimators=300)"],
188
+ [LogisticRegression(), "LogisticRegression"],
189
+ [PassiveAggressiveClassifier(),"PassiveAggressiveClassifier"],
190
+ [SGDClassifier(), "SGDClassifier"],
191
+ [SVC(kernel='linear'), "SVC(linear)"],
192
+ [RidgeClassifier(), "RidgeClassifier"],
193
+ [BaggingClassifier(n_estimators=300), "BaggingClassifier(n_estimators=300)"],
194
+ #[ExtraTreesClassifier(), "ExtraTreesClassifier"],
195
+ #[ExtraTreesClassifier(n_estimators=300), "ExtraTreesClassifier(n_estimators=300)"],
196
+ #[GradientBoostingClassifier(), "GradientBoostingClassifier"], # features_importances_
197
+ #[GradientBoostingClassifier(n_estimators=300), "GradientBoostingClassifier(n_estimators=300)"],
198
+ #[GradientBoostingClassifier(n_estimators=1000), "GradientBoostingClassifier(n_estimators=1000)"],
199
+ #[RandomForestClassifier(), "RandomForestClassifier"],
200
+ #[RandomForestClassifier(n_estimators=300), "RandomForestClassifier(n_estimators=300)"],
201
+ #[RandomForestClassifier(n_estimators=1000), "RandomForestClassifier(n_estimators=1000)"], # features_importances_
202
+
203
+ # linear
204
+ #[ElasticNet(), "ElasticNet"],
205
+ #[ElasticNetCV(), "ElasticNetCV"],
206
+ #[Lasso(), "Lasso"],
207
+ #[LassoCV(), "LassoCV"],
208
+ #[LogisticRegression(), "LogisticRegression"], # coef_
209
+ #[LogisticRegressionCV(), "LogisticRegressionCV"],
210
+ #[PassiveAggressiveClassifier(), "PassiveAggressiveClassifier"], # coef_
211
+ #[RidgeClassifier(), "RidgeClassifier"], # coef_
212
+ #[RidgeClassifierCV(), "RidgeClassifierCV"],
213
+ #[SGDClassifier(), "SGDClassifier"], # coef_
214
+ #[SVC(kernel='linear'), "SVC(linear)"], # coef_, but only if the kernel is linear...the default is 'rbf', which is NOT linear
215
+
216
+ # naive Bayes
217
+ #[BernoulliNB(), "BernoulliNB"],
218
+ #[GaussianNB(), "GaussianNB"],
219
+ #[MultinomialNB(), "MultinomialNB"],
220
+
221
+ # neighbors
222
+ #[KNeighborsClassifier(), "KNeighborsClassifier"], # no way to return feature importance
223
+ # TODO this one creates issues
224
+ #[NearestCentroid(), "NearestCentroid"], # it does not have some necessary methods, apparently
225
+ #[RadiusNeighborsClassifier(), "RadiusNeighborsClassifier"],
226
+
227
+ # tree
228
+ #[DecisionTreeClassifier(), "DecisionTreeClassifier"],
229
+ #[ExtraTreeClassifier(), "ExtraTreeClassifier"],
230
+
231
+ ]
232
+
233
+ # this is just a hack to check a few things
234
+ #classifierList = [
235
+ # [RandomForestClassifier(), "RandomForestClassifier"]
236
+ # ]
237
+
238
+ print("Loading dataset...")
239
+ if (globalIndex==0):
240
+ X, y, biomarkerNames = loadDatasetOriginal(run)
241
+ else:
242
+ X, y, biomarkerNames = loadDataset(globalIndex, run)
243
+
244
+
245
+
246
+ numberOfTopFeatures=int(variableSize)
247
+ # create folder
248
+ folderName ="./run"+str(run)+"/"
249
+ if not os.path.exists(folderName) : os.makedirs(folderName)
250
+
251
+ # prepare folds
252
+ skf = StratifiedKFold(n_splits=numberOfFolds, shuffle=True)
253
+ indexes = [ (training, test) for training, test in skf.split(X, y) ]
254
+
255
+ # this will be used for the top features
256
+ topFeatures = dict()
257
+
258
+ # iterate over all classifiers
259
+ classifierIndex = 0
260
+
261
+ globalAccuracy=0;
262
+
263
+ for originalClassifier, classifierName in classifierList :
264
+
265
+ print("\nClassifier " + classifierName)
266
+ classifierPerformance = []
267
+ classifierTopFeatures = dict()
268
+
269
+ # iterate over all folds
270
+ for train_index, test_index in indexes :
271
+
272
+ X_train, X_test = X[train_index], X[test_index]
273
+ y_train, y_test = y[train_index], y[test_index]
274
+
275
+ # let's normalize, anyway
276
+ scaler = StandardScaler()
277
+ X_train = scaler.fit_transform(X_train)
278
+ X_test = scaler.transform(X_test)
279
+
280
+ classifier = copy.deepcopy(originalClassifier)
281
+ classifier.fit(X_train, y_train)
282
+ #scoreTraining = classifier.score(X_train, y_train)
283
+ #scoreTest = classifier.score(X_test, y_test)
284
+
285
+ y_new_test = classifier.predict(X_test)
286
+ for i in range(0, len(y_new_test)):
287
+ y_new_test[i]=round(y_new_test[i])
288
+ y_new_train = classifier.predict(X_train)
289
+ for i in range(0, len(y_new_train)):
290
+ y_new_train[i]=round(y_new_train[i])
291
+
292
+ scoreTest = matthews_corrcoef(y_test, y_new_test)
293
+ scoreTraining = matthews_corrcoef(y_train, y_new_train)
294
+
295
+
296
+
297
+ print("\ttraining: %.4f, test: %.4f" % (scoreTraining, scoreTest))
298
+ classifierPerformance.append( scoreTest )
299
+
300
+ # now, let's get a list of the most important features, then mark the ones in the top X
301
+ orderedFeatures = relativeFeatureImportance(classifier)
302
+ for i in range(0, numberOfTopFeatures) :
303
+
304
+ feature = int(orderedFeatures[i][1])
305
+
306
+ if feature in topFeatures :
307
+ topFeatures[ feature ] += 1
308
+ else :
309
+ topFeatures[ feature ] = 1
310
+
311
+ if feature in classifierTopFeatures :
312
+ classifierTopFeatures[ feature ] += 1
313
+ else :
314
+ classifierTopFeatures[ feature ] = 1
315
+
316
+ line ="%s\t%.4f\t%.4f\n" % (classifierName, np.mean(classifierPerformance), np.std(classifierPerformance))
317
+
318
+ globalAccuracy=globalAccuracy+np.mean(classifierPerformance)
319
+
320
+ print(line)
321
+ fileName=folderName+"results.txt"
322
+ fo = open(fileName, 'a')
323
+ fo.write( line )
324
+ fo.close()
325
+ # save most important features for the classifier
326
+ with open( os.path.join(folderName, classifierName + ".csv"), "w" ) as fp :
327
+
328
+ fp.write("feature,frequencyInTop" + str(numberOfTopFeatures) + "\n")
329
+
330
+ # transform dictionary into list
331
+ listOfClassifierTopFeatures = [ (key, classifierTopFeatures[key]) for key in classifierTopFeatures ]
332
+ listOfClassifierTopFeatures = sorted( listOfClassifierTopFeatures, key = lambda x : x[1], reverse=True )
333
+
334
+ for feature, frequency in listOfClassifierTopFeatures :
335
+ fp.write( str(biomarkerNames[feature]) + "," + str(float(frequency/numberOfFolds)) + "\n")
336
+
337
+ # save most important features overall
338
+ with open( os.path.join(folderName, "global_"+str(int(globalIndex))+".csv"), "w" ) as fp :
339
+
340
+ fp.write("feature,frequencyInTop" + str(numberOfTopFeatures) + "\n")
341
+
342
+ # transform dictionary into list
343
+ listOfTopFeatures = [ (key, topFeatures[key]) for key in topFeatures ]
344
+ listOfTopFeatures = sorted( listOfTopFeatures, key = lambda x : x[1], reverse=True )
345
+
346
+ tempIndex=0
347
+ for feature, frequency in listOfTopFeatures :
348
+ if tempIndex<numberOfTopFeatures:
349
+ fp.write( str(biomarkerNames[feature]) + "," + str(float(frequency/numberOfFolds)) + "\n")
350
+ tempIndex=tempIndex+1
351
+
352
+ globalAccuracy=globalAccuracy/8
353
+ return globalAccuracy
354
+
reduceData.py ADDED
@@ -0,0 +1,49 @@
1
+ from pandas import read_csv
2
+ import numpy as np
3
+
4
+ import pandas as pd
5
+
6
+ def reduceDataset(globalIndex, run) :
7
+
8
+ # data used for the predictions
9
+ if(globalIndex==0):
10
+ dfData = read_csv("../data/data_"+str(globalIndex)+".csv", header=None, sep=',')
11
+ ids=read_csv("../data/features_"+str(globalIndex)+".csv", header=None, sep=',')
12
+ else:
13
+ dfData = read_csv("./run"+str(run)+"/data_"+str(globalIndex)+".csv", header=None, sep=',')
14
+ ids=read_csv("./run"+str(run)+"/features_"+str(globalIndex)+".csv", header=None, sep=',')
15
+
16
+ idsRed=read_csv("./run"+str(run)+"/global_"+str(globalIndex)+".csv", sep=',')
17
+
18
+ data=dfData.values
19
+ idsRed=idsRed.values
20
+
21
+ ids=ids.values
22
+
23
+ print("data Y %d" %(len(data)))
24
+ print("data X %d" %(len(data[0])))
25
+ print(len(ids))
26
+ print(len(idsRed))
27
+
28
+ tempIds=[]
29
+ for i in range(0,len(idsRed)):
30
+ if (idsRed[i,1]>=1):
31
+ tempIds.append(idsRed[i,0])
32
+ print(len(tempIds))
33
+ count=0
34
+
35
+ dataRed=np.zeros((len(data),len(tempIds)))
36
+
37
+ for i in range(0,len(tempIds)):
38
+ for j in range (0,len(ids)):
39
+ if (ids[j]== tempIds[i]):
40
+ count=count+1
41
+ for k in range(0,len(data)):
42
+ dataRed[k,i]=data[k,j]
43
+
44
+
45
+ pd.DataFrame(tempIds).to_csv("./run"+str(run)+"/features_"+str(globalIndex+1)+".csv", header=None, index =None)
46
+ pd.DataFrame(dataRed).to_csv("./run"+str(run)+"/data_"+str(globalIndex+1)+".csv", header=None, index =None)
47
+ print(count)
48
+
49
+ return len(ids),len(tempIds)
@@ -0,0 +1,73 @@
1
+ Metadata-Version: 2.4
2
+ Name: refs-mcc
3
+ Version: 1.0.0
4
+ Summary: Recursive Ensemble Feature Selection using Matthews Correlation Coefficient
5
+ Author: Alejandro Lopez-Rincon, Alberto Tonda, Brigitta Varga
6
+ Author-email: Alejandro Lopez-Rincon <alejandrolopezrn@gmail.com>
7
+ License: MIT
8
+ Project-URL: source, https://github.com/steppenwolf0/REFS-MCC/
9
+ Project-URL: tracker, https://github.com/steppenwolf0/REFS-MCC/issues
10
+ Keywords: feature-selection,matthews-correlation-coefficient,bioinformatics,machine-learning,ensemble-learning
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: Implementation :: CPython
22
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ Requires-Dist: joblib>=1.5.3
26
+ Requires-Dist: matplotlib>=3.10.8
27
+ Requires-Dist: numpy>=2.4.1
28
+ Requires-Dist: pandas>=2.3.3
29
+ Requires-Dist: scikit-learn>=1.8.0
30
+ Requires-Dist: scipy>=1.17.0
31
+ Requires-Dist: statsmodels>=0.14.6
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest>=7.0; extra == "dev"
34
+
35
+ # REFS-MCC
36
+ Recursive Ensemble Feauture Selection using Matthews Correlation Coefficient
37
+
38
+ --------------------------------------------------------------------
39
+ Installation
40
+
41
+ ```bash
42
+ pip install refs-mcc
43
+ ```
44
+
45
+ After installation it can be used as the following (using the default parameters):
46
+ ```python
47
+ from refs_mcc import REFS_MCC
48
+ REFS_MCC().run()
49
+ ```
50
+
51
+ Or from CLI. For more information, run:
52
+ ```bash
53
+ refs-mcc --help
54
+ ```
55
+
56
+ --------------------------------------------------------------------
57
+ Input
58
+
59
+ Next to the folder where the code is executed from, a `data` folder needs to be present with the following files:
60
+ - `data_0.csv`
61
+ - `features_0.csv`
62
+ - `ids.csv`
63
+ - `labels.csv`
64
+
65
+ --------------------------------------------------------------------
66
+ Output
67
+
68
+ The following folders and files will be created:
69
+ - run folders (`run0`, `run1`, ..., `run{n-1}`, where n is the selected number of total runs, 10 by default)
70
+ - `best` folder
71
+ - `sumFig.pdf` & `sumFig.png`
72
+
73
+ --------------------------------------------------------------------
@@ -0,0 +1,12 @@
1
+ aBioInf100.py,sha256=saaD9_GwyWCd--Wc6EFaif6lcn_tMwdUbZyUyyxwmhA,1679
2
+ classifiersMulti.py,sha256=uLSySF0v_cdcYQj6LWDHjwTYowxjju2c3sW35PW9YuU,7737
3
+ features.py,sha256=UHl6NCinqlqjU286nxfTfEG9UMrCQwrcN8hkMRXcHUY,14511
4
+ reduceData.py,sha256=sCzoheZn8clva2RQKWwH3B-4y3wilIi5DQPXyenSIcM,1444
5
+ refs_mcc.py,sha256=IHzbaeSfgAIA3FtfGrtqAOXBIP5r8EdPfYwELtdn4L0,1118
6
+ sumFig.py,sha256=sjljlTIeOhO7pzOxuFZHTqZzw9ikVYxIQWq47xrDnLY,2819
7
+ summaryMulti.py,sha256=Wo44vWXY3z8OOeqFpW_tJKNHytr0lVewyFc855CVJak,3697
8
+ refs_mcc-1.0.0.dist-info/METADATA,sha256=ZmZYO3QcYhNobci9wr2U-gRunWITqTnCCa4KTl0-hss,2615
9
+ refs_mcc-1.0.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
10
+ refs_mcc-1.0.0.dist-info/entry_points.txt,sha256=Wdp8mPnH0-qa4cbpPd_xKeOJpAwZ19IsN7758QhyLlU,43
11
+ refs_mcc-1.0.0.dist-info/top_level.txt,sha256=cihDROHg3c_S0-46mDNd9c59gG2s9tzrDySfZYnhpc8,77
12
+ refs_mcc-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (83.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ refs-mcc = refs_mcc:main
@@ -0,0 +1,7 @@
1
+ aBioInf100
2
+ classifiersMulti
3
+ features
4
+ reduceData
5
+ refs_mcc
6
+ sumFig
7
+ summaryMulti
refs_mcc.py ADDED
@@ -0,0 +1,30 @@
1
+ import argparse
2
+ import sys
3
+
4
+ from aBioInf100 import main as part1
5
+ from summaryMulti import fakeBootStrapper as part2
6
+ from sumFig import create_summary_figure as part3
7
+
8
+ class REFS_MCC:
9
+ def __init__(self, threads: int = 10, totalRuns: int = 10, numberOfFolds: int = 10):
10
+ self.threads = threads
11
+ self.totalRuns = totalRuns
12
+ self.numberOfFolds = numberOfFolds
13
+
14
+ def run(self):
15
+ part1(self.threads, self.totalRuns, self.numberOfFolds)
16
+ part2(self.totalRuns, self.numberOfFolds)
17
+ part3(self.totalRuns)
18
+
19
+ def main():
20
+ parser = argparse.ArgumentParser(description="REFS-MCC")
21
+ parser.add_argument('--threads', type=int, default=10, help='Number of threads (default: 10)')
22
+ parser.add_argument('--totalRuns', type=int, default=10, help='Total number of runs (default: 10)')
23
+ parser.add_argument('--folds', type=int, default=10, help='Number of folds (default: 10)')
24
+ args = parser.parse_args()
25
+
26
+ refs_mcc = REFS_MCC(args.threads, args.totalRuns, args.folds)
27
+ return refs_mcc.run()
28
+
29
+ if __name__ == "__main__":
30
+ sys.exit(main())
sumFig.py ADDED
@@ -0,0 +1,103 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Thu Jan 7 12:15:27 2021
4
+
5
+ @author: alber
6
+ """
7
+ # convert float to percentage string
8
+ def convert_to_percentage(f) :
9
+ if f != "" :
10
+ print("Converting \"%.4f\"..." % f)
11
+ percentage = f
12
+ return "%.1f" % percentage
13
+ else :
14
+ return ""
15
+
16
+ # script to create a figure
17
+ import sys
18
+
19
+ import numpy as np
20
+ import pandas as pd
21
+ import matplotlib as mpl
22
+ import matplotlib.cm
23
+ import argparse
24
+
25
+ def create_summary_figure(totalRuns):
26
+
27
+ file2 = open('./best/sumA.csv', 'w')
28
+
29
+ #file2.write("features, run0, run1, run2, run3, run4, run5, run6, run7, run8, run9\n")
30
+
31
+ k = totalRuns
32
+
33
+ header = "features, " + ", ".join(f"run{i}" for i in range(k)) + "\n"
34
+ file2.write(header)
35
+
36
+ filepath = './best/sum.csv'
37
+ with open(filepath) as file1:
38
+ line = file1.readline()
39
+ cnt = 1
40
+ while line:
41
+ #print("Line {}: {}".format(cnt, line.strip()))
42
+ file2.write(line)
43
+ line = file1.readline()
44
+ cnt += 1
45
+ file1.close()
46
+ file2.close()
47
+
48
+
49
+
50
+ df = pd.read_csv("./best/sumA.csv")
51
+
52
+ x = df['features'].values
53
+
54
+ features=pd.read_csv("./best/features_0.csv", header=None)
55
+ print("len features:"+str(len(features.values)))
56
+
57
+ maxValue=len(features.values)
58
+
59
+
60
+ runs = [r for r in list(df) if r != 'features']
61
+
62
+ #We declare 15 because numbers 0-5 are almost white.
63
+ n_lines=15
64
+ c = np.arange(1, n_lines + 1)
65
+
66
+ norm = mpl.colors.Normalize(vmin=c.min(), vmax=c.max())
67
+ cmap = mpl.cm.ScalarMappable(norm=norm, cmap=mpl.cm.Blues)
68
+ cmap.set_array([])
69
+
70
+ import matplotlib.pyplot as plt
71
+ fig = plt.figure(figsize=(8,6))
72
+ ax = fig.add_subplot(111)
73
+ ax.set_xscale('log')
74
+
75
+ #starts in 5 because numbers 0-5 are almost white.
76
+ i=5
77
+ for r in runs :
78
+ y = df[r].values
79
+ ax.plot(x, y, label=r, c=cmap.to_rgba(i))
80
+ i=i+1
81
+
82
+ plt.xticks(x, [str(a) for a in list(x)], rotation=90, fontsize=6)
83
+ y_locs = ax.get_yticks()
84
+ print(y_locs)
85
+ plt.yticks(y_locs, [convert_to_percentage(p) for p in y_locs])
86
+
87
+ ax.axvline(linewidth=2, color='r', x=maxValue)
88
+ ax.grid(linestyle='--')
89
+ ax.legend(loc='best')
90
+ ax.set_xlabel("Number of features (log scale)")
91
+ ax.set_ylabel("Ensemble MCC")
92
+ ax.set_title("MCC vs number of features in REFS runs")
93
+ plt.savefig("sumFig.pdf")
94
+ plt.savefig("sumFig.png", dpi=300)
95
+
96
+ if __name__ == "__main__" :
97
+ parser = argparse.ArgumentParser(description="Create summary figure")
98
+ parser.add_argument('--totalRuns', type=int, default=10, help='Total number of runs (default: 10)')
99
+ args = parser.parse_args()
100
+
101
+ totalRuns = args.totalRuns
102
+
103
+ sys.exit( create_summary_figure(totalRuns) )
summaryMulti.py ADDED
@@ -0,0 +1,128 @@
1
+ import numpy as np
2
+ import os
3
+ import sys
4
+ import pandas as pd
5
+ import argparse
6
+
7
+ from classifiersMulti import *
8
+
9
+
10
+ from pandas import read_csv
11
+
12
+ directory="data"
13
+
14
+ def fakeBootStrapper(runs, numberOfFolds):
15
+ # create folder
16
+ folderName ="./best/"
17
+ if not os.path.exists(folderName) : os.makedirs(folderName)
18
+
19
+ orig_stdout = sys.stdout
20
+ f = open('./best/out.txt', 'w')
21
+ sys.stdout = f
22
+
23
+ directory="run"+str(0)
24
+ f=open("./"+directory+"/results.txt", "r")
25
+ fl =f.readlines()
26
+ blocks=int(len(fl)/8)
27
+ print(blocks)
28
+ results=np.zeros((blocks,runs+1))
29
+ for j in range(0,runs):
30
+ directory="run"+str(j)
31
+ f=open("./"+directory+"/results.txt", "r")
32
+ fl =f.readlines()
33
+ blocks=int(len(fl)/8)
34
+ count=0
35
+ value=0
36
+ variables=np.zeros(blocks)
37
+ accuracy=np.zeros(blocks)
38
+ indexResults=0
39
+ for x in fl:
40
+ a=x.split("\t")
41
+ value=value+float(a[1])/8.0
42
+ count=count+1
43
+ if (count==8):
44
+ accuracy[indexResults]=value
45
+ value=0
46
+ count=0
47
+ indexResults=indexResults+1
48
+ indexResults=0
49
+
50
+ for i in range (0,blocks):
51
+ dfFeats = (read_csv("./"+directory+"/features_"+str(i)+".csv", header=None)).values.ravel()
52
+ variables[i]=len(dfFeats)
53
+ results[i,j+1]=accuracy[i]
54
+ results[i,0]=variables[i]
55
+
56
+
57
+
58
+ pd.DataFrame(results).to_csv("./best/sum.csv", header=None, index =None)
59
+
60
+ bestVal=np.zeros(runs)
61
+ bestSize=np.zeros(runs)
62
+ bestPos=np.zeros(runs)
63
+ for j in range(0,runs):
64
+ bestVal[j]=np.max(results[:,j+1])
65
+
66
+ for j in range(0,runs):
67
+ for i in range (0,blocks):
68
+ if ( bestVal[j]==results[i,j+1]):
69
+ bestSize[j]=int(results[i,0])
70
+ bestPos[j]=i
71
+ print(bestVal)
72
+ print(bestSize)
73
+ print(bestPos)
74
+
75
+ bestFeatures=[]
76
+ signatures=[]
77
+ for j in range(0,runs):
78
+ dfFeats = (read_csv("./run"+str(j)+"/features_"+str(int(bestPos[j]))+".csv", header=None))
79
+ bestFeatures.extend(dfFeats.values.ravel())
80
+ signatures.append(dfFeats.values.ravel())
81
+ #print(bestFeatures)
82
+ signatures.append(bestVal)
83
+ signatures.append(bestSize)
84
+ pd.DataFrame(signatures).to_csv("./best/signatures.csv", header=None, index =None)
85
+
86
+ unique, counts = np.unique(bestFeatures, return_counts=True)
87
+
88
+ resultsFeatures=np.zeros((len(unique),2), 'U16')
89
+ for j in range(0,len(unique)):
90
+ resultsFeatures[j,0]=unique[j]
91
+ resultsFeatures[j,1]=counts[j]
92
+
93
+
94
+ pd.DataFrame(resultsFeatures).to_csv("./best/resultsFeatures.csv", header=None, index =None)
95
+
96
+ print(np.max(bestVal))
97
+ print(np.argmax(bestVal))
98
+ print(int(bestPos[np.argmax(bestVal)]))
99
+
100
+ runBest=int(np.argmax(bestVal))
101
+ indexBest=int(bestPos[np.argmax(bestVal)])
102
+
103
+
104
+
105
+ # data used for the predictions
106
+ dfData = read_csv("./run"+str(runBest)+"/data_"+str(indexBest)+".csv", header=None, sep=',')
107
+ dfLabels = read_csv("./run"+str(runBest)+"/labels.csv", header=None)
108
+ biomarkers = read_csv("./run"+str(runBest)+"/features_"+str(indexBest)+".csv", header=None)
109
+
110
+ pd.DataFrame(dfData.values).to_csv("./best/data_0.csv", header=None, index =None)
111
+ pd.DataFrame(biomarkers.values.ravel()).to_csv("./best/features_0.csv", header=None, index =None)
112
+ pd.DataFrame(dfLabels.values.ravel()).to_csv("./best/labels.csv", header=None, index =None)
113
+
114
+ runFeatureReduce(numberOfFolds)
115
+ sys.stdout = orig_stdout
116
+ f.close()
117
+ return
118
+
119
+ if __name__ == "__main__" :
120
+ parser = argparse.ArgumentParser(description="Run REFS-MCC - part 2")
121
+ parser.add_argument('--totalRuns', type=int, default=10, help='Total number of runs (default: 10)')
122
+ parser.add_argument('--folds', type=int, default=10, help='Number of folds (default: 10)')
123
+ args = parser.parse_args()
124
+
125
+ runs=args.totalRuns
126
+ numberOfFolds=args.folds
127
+
128
+ sys.exit( fakeBootStrapper(runs, numberOfFolds) )