2020-12-10 19:04:33 +01:00
|
|
|
from sklearn.linear_model import LogisticRegression
|
2021-01-06 14:58:29 +01:00
|
|
|
from sklearn.model_selection import GridSearchCV
|
2020-12-10 19:04:33 +01:00
|
|
|
from sklearn.svm import LinearSVC
|
|
|
|
import quapy as qp
|
|
|
|
import quapy.functional as F
|
2020-12-14 18:36:19 +01:00
|
|
|
import sys
|
2020-12-22 17:43:23 +01:00
|
|
|
import numpy as np
|
2021-01-06 14:58:29 +01:00
|
|
|
from classification.methods import PCALR
|
2020-12-29 20:33:59 +01:00
|
|
|
from classification.neural import NeuralClassifierTrainer, CNNnet
|
|
|
|
from quapy.model_selection import GridSearchQ
|
2020-12-10 19:04:33 +01:00
|
|
|
|
2021-01-06 14:58:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
#qp.datasets.fetch_UCIDataset('acute.b', verbose=True)
|
|
|
|
|
|
|
|
#sys.exit(0)
|
2020-12-29 20:33:59 +01:00
|
|
|
qp.environ['SAMPLE_SIZE'] = 500
|
2021-01-06 14:58:29 +01:00
|
|
|
#param_grid = {'C': np.logspace(-3,3,7), 'class_weight': ['balanced', None]}
|
|
|
|
param_grid = {'C': np.logspace(0,3,4), 'class_weight': ['balanced']}
|
|
|
|
max_evaluations = 5000
|
2020-12-14 18:36:19 +01:00
|
|
|
|
2020-12-29 20:33:59 +01:00
|
|
|
sample_size = qp.environ['SAMPLE_SIZE']
|
2021-01-15 17:42:19 +01:00
|
|
|
binary = False
|
2020-12-11 19:28:17 +01:00
|
|
|
svmperf_home = './svm_perf_quantification'
|
2020-12-10 19:04:33 +01:00
|
|
|
|
|
|
|
if binary:
|
2021-01-06 14:58:29 +01:00
|
|
|
dataset = qp.datasets.fetch_reviews('kindle', tfidf=True, min_df=5)
|
|
|
|
#qp.data.preprocessing.index(dataset, inplace=True)
|
2020-12-10 19:04:33 +01:00
|
|
|
|
|
|
|
else:
|
2020-12-22 17:43:23 +01:00
|
|
|
dataset = qp.datasets.fetch_twitter('hcr', for_model_selection=False, min_df=10, pickle=True)
|
2021-01-15 17:42:19 +01:00
|
|
|
#dataset.training = dataset.training.sampling(sample_size, 0.2, 0.5, 0.3)
|
2020-12-11 19:28:17 +01:00
|
|
|
|
2020-12-29 20:33:59 +01:00
|
|
|
print(f'dataset loaded: #training={len(dataset.training)} #test={len(dataset.test)}')
|
|
|
|
|
2020-12-10 19:04:33 +01:00
|
|
|
|
|
|
|
# training a quantifier
|
2020-12-29 20:33:59 +01:00
|
|
|
# learner = LogisticRegression(max_iter=1000)
|
2021-01-06 14:58:29 +01:00
|
|
|
#model = qp.method.aggregative.ClassifyAndCount(learner)
|
2020-12-29 20:33:59 +01:00
|
|
|
# model = qp.method.aggregative.AdjustedClassifyAndCount(learner)
|
2020-12-10 19:04:33 +01:00
|
|
|
# model = qp.method.aggregative.ProbabilisticClassifyAndCount(learner)
|
|
|
|
# model = qp.method.aggregative.ProbabilisticAdjustedClassifyAndCount(learner)
|
2021-01-06 14:58:29 +01:00
|
|
|
# model = qp.method.aggregative.HellingerDistanceY(learner)
|
2020-12-10 19:04:33 +01:00
|
|
|
# model = qp.method.aggregative.ExpectationMaximizationQuantifier(learner)
|
2020-12-11 19:28:17 +01:00
|
|
|
# model = qp.method.aggregative.ExplicitLossMinimisationBinary(svmperf_home, loss='q', C=100)
|
2020-12-22 17:43:23 +01:00
|
|
|
# model = qp.method.aggregative.SVMQ(svmperf_home, C=1)
|
2020-12-11 19:28:17 +01:00
|
|
|
|
2021-01-06 14:58:29 +01:00
|
|
|
#learner = PCALR()
|
|
|
|
#learner = NeuralClassifierTrainer(CNNnet(dataset.vocabulary_size, dataset.n_classes))
|
|
|
|
#print(learner.get_params())
|
|
|
|
#model = qp.method.meta.QuaNet(learner, sample_size, device='cpu')
|
|
|
|
|
|
|
|
#learner = GridSearchCV(LogisticRegression(max_iter=1000), param_grid=param_grid, n_jobs=-1, verbose=1)
|
|
|
|
learner = LogisticRegression(max_iter=1000)
|
2021-01-15 17:42:19 +01:00
|
|
|
model = qp.method.aggregative.ClassifyAndCount(learner)
|
|
|
|
#model = qp.method.meta.ECC(learner, size=20, red_size=10, param_grid=None, optim=None, policy='ds')
|
2021-01-06 14:58:29 +01:00
|
|
|
#model = qp.method.meta.EHDy(learner, param_grid=param_grid, optim='mae',
|
|
|
|
# sample_size=sample_size, eval_budget=max_evaluations//10, n_jobs=-1)
|
|
|
|
#model = qp.method.aggregative.ClassifyAndCount(learner)
|
2020-12-29 20:33:59 +01:00
|
|
|
|
2021-01-06 14:58:29 +01:00
|
|
|
|
2021-01-15 17:42:19 +01:00
|
|
|
if qp.isbinary(model) and not qp.isbinary(dataset):
|
|
|
|
model = qp.method.aggregative.OneVsAll(model)
|
2020-12-09 12:46:50 +01:00
|
|
|
|
2020-12-10 19:04:33 +01:00
|
|
|
|
2020-12-22 17:43:23 +01:00
|
|
|
# Model fit and Evaluation on the test data
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
print(f'fitting model {model.__class__.__name__}')
|
2020-12-29 20:33:59 +01:00
|
|
|
#train, val = dataset.training.split_stratified(0.6)
|
|
|
|
#model.fit(train, val_split=val)
|
|
|
|
model.fit(dataset.training)
|
2021-01-06 14:58:29 +01:00
|
|
|
#for i,e in enumerate(model.ensemble):
|
|
|
|
#print(i, e.learner.best_estimator_)
|
|
|
|
# print(i, e.best_model_.learner)
|
|
|
|
|
2020-12-11 19:28:17 +01:00
|
|
|
|
2020-12-10 19:04:33 +01:00
|
|
|
# estimating class prevalences
|
2020-12-11 19:28:17 +01:00
|
|
|
print('quantifying')
|
2020-12-10 19:04:33 +01:00
|
|
|
prevalences_estim = model.quantify(dataset.test.instances)
|
|
|
|
prevalences_true = dataset.test.prevalence()
|
|
|
|
|
|
|
|
# evaluation (one single prediction)
|
|
|
|
error = qp.error.mae(prevalences_true, prevalences_estim)
|
|
|
|
|
|
|
|
print(f'Evaluation in test (1 eval)')
|
|
|
|
print(f'true prevalence {F.strprev(prevalences_true)}')
|
|
|
|
print(f'estim prevalence {F.strprev(prevalences_estim)}')
|
|
|
|
print(f'mae={error:.3f}')
|
|
|
|
|
|
|
|
|
2020-12-22 17:43:23 +01:00
|
|
|
# Model fit and Evaluation according to the artificial sampling protocol
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
|
2020-12-11 19:28:17 +01:00
|
|
|
n_prevpoints = F.get_nprevpoints_approximation(combinations_budget=max_evaluations, n_classes=dataset.n_classes)
|
|
|
|
n_evaluations = F.num_prevalence_combinations(n_prevpoints, dataset.n_classes)
|
2020-12-14 18:36:19 +01:00
|
|
|
print(f'the prevalence interval [0,1] will be split in {n_prevpoints} prevalence points for each class, so that\n'
|
|
|
|
f'the requested maximum number of sample evaluations ({max_evaluations}) is not exceeded.\n'
|
2020-12-11 19:28:17 +01:00
|
|
|
f'For the {dataset.n_classes} classes this dataset has, this will yield a total of {n_evaluations} evaluations.')
|
|
|
|
|
2020-12-29 20:33:59 +01:00
|
|
|
true_prev, estim_prev = qp.evaluation.artificial_sampling_prediction(model, dataset.test, sample_size, n_prevpoints)
|
2020-12-11 19:28:17 +01:00
|
|
|
|
2021-01-06 14:58:29 +01:00
|
|
|
#qp.error.SAMPLE_SIZE = sample_size
|
2020-12-10 19:04:33 +01:00
|
|
|
print(f'Evaluation according to the artificial sampling protocol ({len(true_prev)} evals)')
|
|
|
|
for error in qp.error.QUANTIFICATION_ERROR:
|
|
|
|
score = error(true_prev, estim_prev)
|
|
|
|
print(f'{error.__name__}={score:.5f}')
|
2020-12-10 19:08:22 +01:00
|
|
|
|
2020-12-22 17:43:23 +01:00
|
|
|
|
|
|
|
# Model selection and Evaluation according to the artificial sampling protocol
|
|
|
|
# ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
model_selection = GridSearchQ(model,
|
|
|
|
param_grid=param_grid,
|
2020-12-29 20:33:59 +01:00
|
|
|
sample_size=sample_size,
|
2020-12-22 17:43:23 +01:00
|
|
|
eval_budget=max_evaluations//10,
|
|
|
|
error='mae',
|
|
|
|
refit=True,
|
2021-01-15 17:42:19 +01:00
|
|
|
verbose=True,
|
|
|
|
timeout=4)
|
2020-12-22 17:43:23 +01:00
|
|
|
|
2021-01-06 14:58:29 +01:00
|
|
|
model = model_selection.fit(dataset.training, validation=0.3)
|
|
|
|
#model = model_selection.fit(train, validation=val)
|
2020-12-22 17:43:23 +01:00
|
|
|
print(f'Model selection: best_params = {model_selection.best_params_}')
|
|
|
|
print(f'param scores:')
|
|
|
|
for params, score in model_selection.param_scores_.items():
|
|
|
|
print(f'\t{params}: {score:.5f}')
|
|
|
|
|
2020-12-29 20:33:59 +01:00
|
|
|
true_prev, estim_prev = qp.evaluation.artificial_sampling_prediction(model, dataset.test, sample_size, n_prevpoints)
|
2020-12-22 17:43:23 +01:00
|
|
|
|
|
|
|
print(f'After model selection: Evaluation according to the artificial sampling protocol ({len(true_prev)} evals)')
|
|
|
|
for error in qp.error.QUANTIFICATION_ERROR:
|
|
|
|
score = error(true_prev, estim_prev)
|
|
|
|
print(f'{error.__name__}={score:.5f}')
|