From 168c109794351eb3821e15cb705e3facee996695 Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Wed, 10 Mar 2021 11:25:42 +0100 Subject: [PATCH 01/10] adding fgsld --- NewMethods/fgsld/em.py | 116 ------------ NewMethods/fgsld/fglsd_test.py | 75 -------- NewMethods/fgsld/fine_grained_sld.py | 107 ----------- NewMethods/fgsld/metrics.py | 260 --------------------------- NewMethods/fgsld/plot_fglsd.png | Bin 165809 -> 0 bytes 5 files changed, 558 deletions(-) diff --git a/NewMethods/fgsld/em.py b/NewMethods/fgsld/em.py index 0f6ab6d..e69de29 100644 --- a/NewMethods/fgsld/em.py +++ b/NewMethods/fgsld/em.py @@ -1,116 +0,0 @@ -import numpy as np -import logging -from collections import namedtuple - -from sklearn.metrics import brier_score_loss -from sklearn.preprocessing import MultiLabelBinarizer - -from metrics import smoothmacroF1, isometric_brier_decomposition, isomerous_brier_decomposition - -History = namedtuple('History', ('posteriors', 'priors', 'y', 'iteration', 'stopping_criterium')) -MeasureSingleHistory = namedtuple('MeasureSingleHistory', ( - 'soft_acc', 'soft_f1', 'abs_errors', 'test_priors', 'train_priors', 'predict_priors', 'brier', - 'isometric_ref_loss', 'isometric_cal_loss', 'isomerous_ref_loss', 'isomerous_cal_loss' -)) - - -def get_measures_single_history(history: History, multi_class) -> MeasureSingleHistory: - y = history.y - - y_bin = MultiLabelBinarizer(classes=list(range(history.posteriors.shape[1]))).fit_transform(np.expand_dims(y, 1)) - - soft_acc = soft_accuracy(y, history.posteriors) - f1 = smoothmacroF1(y_bin, history.posteriors) - - if multi_class: - test_priors = np.mean(y_bin, 0) - abs_errors = abs(test_priors - history.priors) - train_priors = history.priors - predict_priors = np.mean(history.posteriors, 0) - brier = 0 - else: - test_priors = np.mean(y_bin, 0)[1] - abs_errors = abs(test_priors - history.priors[1]) - train_priors = history.priors[1] - predict_priors = np.mean(history.posteriors[:, 1]) - brier = brier_score_loss(y, history.posteriors[:, 1]) - - isometric_cal_loss, isometric_ref_loss = isometric_brier_decomposition(y, history.posteriors) - isomerous_em_cal_loss, isomerous_em_ref_loss = isomerous_brier_decomposition(y, history.posteriors) - - return MeasureSingleHistory( - soft_acc, f1, abs_errors, test_priors, train_priors, predict_priors, brier, isometric_ref_loss, - isometric_cal_loss, isomerous_em_ref_loss, isomerous_em_cal_loss - ) - - -def soft_accuracy(y, posteriors): - return sum(posteriors[y == c][:, c].sum() for c in range(posteriors.shape[1])) / posteriors.sum() - - -def soft_f1(y, posteriors): - cont_matrix = { - 'TPM': posteriors[y == 1][:, 1].sum(), - 'TNM': posteriors[y == 0][:, 0].sum(), - 'FPM': posteriors[y == 0][:, 1].sum(), - 'FNM': posteriors[y == 1][:, 0].sum() - } - precision = cont_matrix['TPM'] / (cont_matrix['TPM'] + cont_matrix['FPM']) - recall = cont_matrix['TPM'] / (cont_matrix['TPM'] + cont_matrix['FNM']) - return 2 * (precision * recall / (precision + recall)) - - -def em(y, posteriors_zero, priors_zero, epsilon=1e-6, multi_class=False, return_posteriors_hist=False): - """ - Implements the prior correction method based on EM presented in: - "Adjusting the Outputs of a Classifier to New a Priori Probabilities: A Simple Procedure" - Saerens, Latinne and Decaestecker, 2002 - http://www.isys.ucl.ac.be/staff/marco/Publications/Saerens2002a.pdf - - :param y: true labels of test items, to measure accuracy, precision and recall. - :param posteriors_zero: posterior probabilities on test items, as returned by a classifier. A 2D-array with shape - Ø(items, classes). - :param priors_zero: prior probabilities measured on training set. - :param epsilon: stopping threshold. - :param multi_class: whether the algorithm is running in a multi-label multi-class context or not. - :param return_posteriors_hist: whether posteriors for each iteration should be returned or not. If true, the returned - posteriors_s will actually be the list of posteriors for every iteration. - :return: posteriors_s, priors_s, history: final adjusted posteriors, final adjusted priors, a list of length s - where each element is a tuple with the step counter, the current priors (as list), the stopping criterium value, - accuracy, precision and recall. - """ - s = 0 - priors_s = np.copy(priors_zero) - posteriors_s = np.copy(posteriors_zero) - if return_posteriors_hist: - posteriors_hist = [posteriors_s.copy()] - val = 2 * epsilon - history = list() - history.append(get_measures_single_history(History(posteriors_zero, priors_zero, y, s, 1), multi_class)) - while not val < epsilon and s < 999: - # M step - priors_s_minus_one = priors_s.copy() - priors_s = posteriors_s.mean(0) - - # E step - ratios = priors_s / priors_zero - denominators = 0 - for c in range(priors_zero.shape[0]): - denominators += ratios[c] * posteriors_zero[:, c] - for c in range(priors_zero.shape[0]): - posteriors_s[:, c] = ratios[c] * posteriors_zero[:, c] / denominators - - # check for stop - val = 0 - for i in range(len(priors_s_minus_one)): - val += abs(priors_s_minus_one[i] - priors_s[i]) - - logging.debug(f"Em iteration: {s}; Val: {val}") - s += 1 - if return_posteriors_hist: - posteriors_hist.append(posteriors_s.copy()) - history.append(get_measures_single_history(History(posteriors_s, priors_s, y, s, val), multi_class)) - - if return_posteriors_hist: - return posteriors_hist, priors_s, history - return posteriors_s, priors_s, history diff --git a/NewMethods/fgsld/fglsd_test.py b/NewMethods/fgsld/fglsd_test.py index 4735a53..e69de29 100644 --- a/NewMethods/fgsld/fglsd_test.py +++ b/NewMethods/fgsld/fglsd_test.py @@ -1,75 +0,0 @@ -from sklearn.calibration import CalibratedClassifierCV -from sklearn.svm import LinearSVC - -from NewMethods.fgsld.fine_grained_sld import FineGrainedSLD -from method.aggregative import EMQ, CC -from quapy.data import LabelledCollection -from quapy.method.base import BaseQuantifier -import quapy as qp -import quapy.functional as F -from sklearn.linear_model import LogisticRegression - - -class FakeFGLSD(BaseQuantifier): - def __init__(self, learner, nbins, isomerous): - self.learner = learner - self.nbins = nbins - self.isomerous = isomerous - - def fit(self, data: LabelledCollection): - self.Xtr, self.ytr = data.Xy - self.learner.fit(self.Xtr, self.ytr) - return self - - def quantify(self, instances): - tr_priors = F.prevalence_from_labels(self.ytr, n_classes=2) - fgsld = FineGrainedSLD(self.Xtr, instances, self.ytr, tr_priors, self.learner, n_bins=self.nbins) - priors, posteriors = fgsld.run(self.isomerous) - return priors - - def get_params(self, deep=True): - pass - - def set_params(self, **parameters): - pass - - - -qp.environ['SAMPLE_SIZE'] = 500 - -dataset = qp.datasets.fetch_reviews('hp') -qp.data.preprocessing.text2tfidf(dataset, min_df=5, inplace=True) - -training = dataset.training -test = dataset.test - -cls = CalibratedClassifierCV(LinearSVC()) - - -method_names, true_prevs, estim_prevs, tr_prevs = [], [], [], [] - -for model, model_name in [ - (CC(cls), 'CC'), - (FakeFGLSD(cls, nbins=1, isomerous=False), 'FGSLD-1'), - (FakeFGLSD(cls, nbins=2, isomerous=False), 'FGSLD-2'), - #(FakeFGLSD(cls, nbins=5, isomerous=False), 'FGSLD-5'), - #(FakeFGLSD(cls, nbins=10, isomerous=False), 'FGSLD-10'), - #(FakeFGLSD(cls, nbins=50, isomerous=False), 'FGSLD-50'), - #(FakeFGLSD(cls, nbins=100, isomerous=False), 'FGSLD-100'), -# (FakeFGLSD(cls, nbins=1, isomerous=False), 'FGSLD-1'), - #(FakeFGLSD(cls, nbins=10, isomerous=True), 'FGSLD-10-ISO'), - # (FakeFGLSD(cls, nbins=50, isomerous=False), 'FGSLD-50'), - (EMQ(cls), 'SLD'), -]: - print('running ', model_name) - model.fit(training) - true_prev, estim_prev = qp.evaluation.artificial_sampling_prediction( - model, test, qp.environ['SAMPLE_SIZE'], n_repetitions=10, n_prevpoints=21, n_jobs=-1 - ) - method_names.append(model_name) - true_prevs.append(true_prev) - estim_prevs.append(estim_prev) - tr_prevs.append(training.prevalence()) - - -qp.plot.binary_diagonal(method_names, true_prevs, estim_prevs, train_prev=tr_prevs[0], savepath='./plot_fglsd.png') diff --git a/NewMethods/fgsld/fine_grained_sld.py b/NewMethods/fgsld/fine_grained_sld.py index f955491..e69de29 100644 --- a/NewMethods/fgsld/fine_grained_sld.py +++ b/NewMethods/fgsld/fine_grained_sld.py @@ -1,107 +0,0 @@ -import numpy as np -from metrics import isomerous_bins, isometric_bins -from em import History, get_measures_single_history - - -class FineGrainedSLD: - def __init__(self, x_tr, x_te, y_tr, tr_priors, clf, n_bins=10): - self.y_tr = y_tr - self.clf = clf - self.tr_priors = tr_priors - self.tr_preds = clf.predict_proba(x_tr) - self.te_preds = clf.predict_proba(x_te) - self.n_bins = n_bins - self.history: [History] = [] - self.multi_class = False - - def run(self, isomerous_binning, epsilon=1e-6, compute_bins_at_every_iter=False, return_posteriors_hist=False): - """ - Run the FGSLD algorithm. - - :param isomerous_binning: whether to use isomerous or isometric binning. - :param epsilon: stopping condition. - :param compute_bins_at_every_iter: whether FGSLD should recompute the posterior bins at every iteration or not. - :param return_posteriors_hist: whether to return posteriors at every iteration or not. - :return: If `return_posteriors_hist` is true, the returned posteriors will be a list of numpy arrays, else a single numpy array with posteriors at last iteration. - """ - smoothing_tr = 1 / (2 * self.y_tr.shape[0]) - smoothing_te = smoothing_tr - s = 0 - tr_bin_priors = np.zeros((self.n_bins, self.tr_preds.shape[1]), dtype=np.float) - te_bin_priors = np.zeros((self.n_bins, self.te_preds.shape[1]), dtype=np.float) - tr_bins = self.__create_bins(training=True, isomerous_binning=isomerous_binning) - te_bins = self.__create_bins(training=False, isomerous_binning=isomerous_binning) - self.__compute_bins_priors(tr_bin_priors, self.tr_preds, tr_bins, smoothing_tr) - - val = 2 * epsilon - if return_posteriors_hist: - posteriors_hist = [self.te_preds.copy()] - while not val < epsilon and s < 1000: - assert np.all(np.around(self.te_preds.sum(axis=1), 4) == 1), f"Probabilities do not sum to 1:\ns={s}, " \ - f"probs={self.te_preds.sum(axis=1)}" - if compute_bins_at_every_iter: - te_bins = self.__create_bins(training=False, isomerous_binning=isomerous_binning) - - if s == 0: - te_bin_priors_prev = tr_bin_priors.copy() - else: - te_bin_priors_prev = te_bin_priors.copy() - self.__compute_bins_priors(te_bin_priors, self.te_preds, te_bins, smoothing_te) - - te_preds_cp = self.te_preds.copy() - for label_idx, bins in te_bins.items(): - for i, bin_ in enumerate(bins): - if bin_.shape[0] == 0: - continue - self.te_preds[:, label_idx][bin_] = (te_preds_cp[:, label_idx][bin_]) * \ - (te_bin_priors[i][label_idx] / te_bin_priors_prev[i][label_idx]) - - # Normalization step - self.te_preds = (self.te_preds.T / self.te_preds.sum(axis=1)).T - - val = 0 - for label_idx in range(te_bin_priors.shape[1]): - if (temp := max(abs((te_bin_priors[:, label_idx] / te_bin_priors_prev[:, label_idx]) - 1))) > val: - val = temp - s += 1 - if return_posteriors_hist: - posteriors_hist.append(self.te_preds.copy()) - if return_posteriors_hist: - return self.te_preds.mean(axis=0), posteriors_hist - return self.te_preds.mean(axis=0), self.te_preds - - def __compute_bins_priors(self, bin_priors_placeholder, posteriors, bins, smoothing): - for label_idx, bins in bins.items(): - for i, bin_ in enumerate(bins): - if bin_.shape[0] == 0: - bin_priors_placeholder[i, label_idx] = smoothing - continue - numerator = posteriors[:, label_idx][bin_].mean() - bin_prior = (numerator + smoothing) / (1 + self.n_bins * smoothing) # normalize priors - bin_priors_placeholder[i, label_idx] = bin_prior - - def __find_bin_idx(self, label_bins: [np.array], idx: int or list): - if hasattr(idx, '__len__'): - idxs = np.zeros(len(idx), dtype=np.int) - for i, bin_ in enumerate(label_bins): - for j, id_ in enumerate(idx): - if id_ in bin_: - idxs[j] = i - return idxs - else: - for i, bin_ in enumerate(label_bins): - if idx in bin_: - return i - - def __create_bins(self, training: bool, isomerous_binning: bool): - bins = {} - preds = self.tr_preds if training else self.te_preds - if isomerous_binning: - for label_idx in range(preds.shape[1]): - bins[label_idx] = isomerous_bins(label_idx, preds, self.n_bins) - else: - intervals = np.linspace(0., 1., num=self.n_bins, endpoint=False) - for label_idx in range(preds.shape[1]): - bins_ = isometric_bins(label_idx, preds, intervals, 0.1) - bins[label_idx] = [bins_[i] for i in intervals] - return bins diff --git a/NewMethods/fgsld/metrics.py b/NewMethods/fgsld/metrics.py index c95e757..e69de29 100644 --- a/NewMethods/fgsld/metrics.py +++ b/NewMethods/fgsld/metrics.py @@ -1,260 +0,0 @@ -import numpy as np - -""" -Scikit learn provides a full set of evaluation metrics, but they treat special cases differently. -I.e., when the number of true positives, false positives, and false negatives ammount to 0, all -affected metrics (precision, recall, and thus f1) output 0 in Scikit learn. -We adhere to the common practice of outputting 1 in this case since the classifier has correctly -classified all examples as negatives. -""" - - -def isometric_brier_decomposition(true_labels, predicted_labels, bin_intervals=np.arange(0., 1.1, 0.1), step=0.1): - """ - The Isometric Brier decomposition or score is obtained by partitioning U into intervals I_1j,...,I_bj that - have equal length, where U is the total size of our test set (i.e., true_labels.shape[0]). This means that, - if b=10 then I_1j = [0.0,0.1), I_2j = [0.2, 0.3),...,I_bj = [0.9,1.0). - - bin_intervals is a numpy.array containing the range of the different intervals. Since it is a single dimensional - array, for every interval I_n we take the posterior probabilities Pr_n(x) such that I_n <= Pr_n(x) < I_n + step. - This variable defaults to np.arange(0., 1.0, 0.1), i.e. an array like [0.1, 0.2, ..., 1.0]. - - :return: a tuple (calibration score, refinement score) - """ - labels = set(true_labels) - calibration_score, refinement_score = 0.0, 0.0 - for i in range(len(labels)): - bins = isometric_bins(i, predicted_labels, bin_intervals, step) - c_score, r_score = brier_decomposition(bins.values(), true_labels, predicted_labels, class_=i) - calibration_score += c_score - refinement_score += r_score - return calibration_score, refinement_score - - -def isomerous_brier_decomposition(true_labels, predicted_labels, n=10): - """ - The Isomerous Brier decomposition or score is obtained by partitioning U into intervals I_1j,...,I_bj such that - the corresponding bins B_1j,...,B_bj have equal size, where U is our test set. This means that, for every x' in - B_sj and x'' in B_tj with s < t, it holds that Pr(c_j|x') <= Pr(c_j|x'') and |B_sj| == |B_tj|, for any s,t in - {1,...,b}. - - The n variable holds the number of bins we want (defaults to 10). Notice that we perform a numpy.array_split on - the predicted_labels, creating l % n sub-arrays of size l//n + 1 and the rest of size l//n, where l is the length - of the array. - - :return: a tuple (calibration score, refinement score) - """ - - labels = set(true_labels) - calibration_score, refinement_score = 0.0, 0.0 - for i in range(len(labels)): - bins = isomerous_bins(i, predicted_labels, n) - c_score, r_score = brier_decomposition(bins, true_labels, predicted_labels, class_=i) - calibration_score += c_score - refinement_score += r_score - return calibration_score, refinement_score - - -def brier_decomposition(bins, true_labels, predicted_labels, class_=1): - """ - :param bins: must be an array of indices - :return: a tuple (calibration_score, refinement_score) - """ - calibration_score = 0 - refinement_score = 0 - for bin_ in bins: - if bin_.size <= 0: - continue - v_x = (bin_.shape[0] / true_labels.shape[0]) - ro_x = np.mean(true_labels[bin_] == class_) - calibration_score += v_x * (predicted_labels[bin_, class_].mean() - ro_x)**2 - refinement_score += (v_x * ro_x) * (1 - ro_x) - labels_len = len(set(true_labels)) - return calibration_score / (labels_len * len(bins)), refinement_score / (labels_len * len(bins)) - - -def isometric_bins(label_index, predicted_labels, bin_intervals, step): - predicted_class_label = predicted_labels[:, label_index] - return {interv: np.where(np.logical_and(interv <= predicted_class_label, predicted_class_label < interv + step))[0] - for interv in bin_intervals} - - -def isomerous_bins(label_index, predicted_labels, n): - sorted_indices = predicted_labels[:, label_index].argsort() - return np.array_split(sorted_indices, n) - - -# true_labels and predicted_labels are two matrices in sklearn.preprocessing.MultiLabelBinarizer format -def macroF1(true_labels, predicted_labels): - return macro_average(true_labels, predicted_labels, f1) - - -# true_labels and predicted_labels are two matrices in sklearn.preprocessing.MultiLabelBinarizer format -def microF1(true_labels, predicted_labels): - return micro_average(true_labels, predicted_labels, f1) - - -# true_labels and predicted_labels are two matrices in sklearn.preprocessing.MultiLabelBinarizer format -def macroK(true_labels, predicted_labels): - return macro_average(true_labels, predicted_labels, K) - - -# true_labels and predicted_labels are two matrices in sklearn.preprocessing.MultiLabelBinarizer format -def microK(true_labels, predicted_labels): - return micro_average(true_labels, predicted_labels, K) - - -# true_labels is a matrix in sklearn.preprocessing.MultiLabelBinarizer format and posterior_probabilities is a matrix -# of the same shape containing real values in [0,1] -def smoothmacroF1(true_labels, posterior_probabilities): - return macro_average(true_labels, posterior_probabilities, f1, metric_statistics=soft_single_metric_statistics) - - -# true_labels is a matrix in sklearn.preprocessing.MultiLabelBinarizer format and posterior_probabilities is a matrix -# of the same shape containing real values in [0,1] -def smoothmicroF1(true_labels, posterior_probabilities): - return micro_average(true_labels, posterior_probabilities, f1, metric_statistics=soft_single_metric_statistics) - - -# true_labels is a matrix in sklearn.preprocessing.MultiLabelBinarizer format and posterior_probabilities is a matrix -# of the same shape containing real values in [0,1] -def smoothmacroK(true_labels, posterior_probabilities): - return macro_average(true_labels, posterior_probabilities, K, metric_statistics=soft_single_metric_statistics) - - -# true_labels is a matrix in sklearn.preprocessing.MultiLabelBinarizer format and posterior_probabilities is a matrix -# of the same shape containing real values in [0,1] -def smoothmicroK(true_labels, posterior_probabilities): - return micro_average(true_labels, posterior_probabilities, K, metric_statistics=soft_single_metric_statistics) - - -class ContTable: - def __init__(self, tp=0, tn=0, fp=0, fn=0): - self.tp = tp - self.tn = tn - self.fp = fp - self.fn = fn - - def get_d(self): return self.tp + self.tn + self.fp + self.fn - - def get_c(self): return self.tp + self.fn - - def get_not_c(self): return self.tn + self.fp - - def get_f(self): return self.tp + self.fp - - def get_not_f(self): return self.tn + self.fn - - def p_c(self): return (1.0 * self.get_c()) / self.get_d() - - def p_not_c(self): return 1.0 - self.p_c() - - def p_f(self): return (1.0 * self.get_f()) / self.get_d() - - def p_not_f(self): return 1.0 - self.p_f() - - def p_tp(self): return (1.0 * self.tp) / self.get_d() - - def p_tn(self): return (1.0 * self.tn) / self.get_d() - - def p_fp(self): return (1.0 * self.fp) / self.get_d() - - def p_fn(self): return (1.0 * self.fn) / self.get_d() - - def tpr(self): - c = 1.0 * self.get_c() - return self.tp / c if c > 0.0 else 0.0 - - def fpr(self): - _c = 1.0 * self.get_not_c() - return self.fp / _c if _c > 0.0 else 0.0 - - def __add__(self, other): - return ContTable(tp=self.tp + other.tp, tn=self.tn + other.tn, fp=self.fp + other.fp, fn=self.fn + other.fn) - - -def accuracy(cell): - return (cell.tp + cell.tn) * 1.0 / (cell.tp + cell.fp + cell.fn + cell.tn) - - -def f1(cell): - num = 2.0 * cell.tp - den = 2.0 * cell.tp + cell.fp + cell.fn - if den > 0: return num / den - # we define f1 to be 1 if den==0 since the classifier has correctly classified all instances as negative - return 1.0 - - -def K(cell): - specificity, recall = 0., 0. - - AN = cell.tn + cell.fp - if AN != 0: - specificity = cell.tn * 1. / AN - - AP = cell.tp + cell.fn - if AP != 0: - recall = cell.tp * 1. / AP - - if AP == 0: - return 2. * specificity - 1. - elif AN == 0: - return 2. * recall - 1. - else: - return specificity + recall - 1. - - -# computes the (hard) counters tp, fp, fn, and tn fron a true and predicted vectors of hard decisions -# true_labels and predicted_labels are two vectors of shape (number_documents,) -def hard_single_metric_statistics(true_labels, predicted_labels): - assert len(true_labels) == len(predicted_labels), "Format not consistent between true and predicted labels." - nd = len(true_labels) - tp = np.sum(predicted_labels[true_labels == 1]) - fp = np.sum(predicted_labels[true_labels == 0]) - fn = np.sum(true_labels[predicted_labels == 0]) - tn = nd - (tp + fp + fn) - return ContTable(tp=tp, tn=tn, fp=fp, fn=fn) - - -# computes the (soft) contingency table where tp, fp, fn, and tn are the cumulative masses for the posterioir -# probabilitiesfron with respect to the true binary labels -# true_labels and posterior_probabilities are two vectors of shape (number_documents,) -def soft_single_metric_statistics(true_labels, posterior_probabilities): - assert len(true_labels) == len(posterior_probabilities), "Format not consistent between true and predicted labels." - pos_probs = posterior_probabilities[true_labels == 1] - neg_probs = posterior_probabilities[true_labels == 0] - tp = np.sum(pos_probs) - fn = np.sum(1. - pos_probs) - fp = np.sum(neg_probs) - tn = np.sum(1. - neg_probs) - return ContTable(tp=tp, tn=tn, fp=fp, fn=fn) - - -# if the classifier is single class, then the prediction is a vector of shape=(nD,) which causes issues when compared -# to the true labels (of shape=(nD,1)). This method increases the dimensions of the predictions. -def __check_consistency_and_adapt(true_labels, predictions): - if predictions.ndim == 1: - return __check_consistency_and_adapt(true_labels, np.expand_dims(predictions, axis=1)) - if true_labels.ndim == 1: - return __check_consistency_and_adapt(np.expand_dims(true_labels, axis=1), predictions) - if true_labels.shape != predictions.shape: - raise ValueError("True and predicted label matrices shapes are inconsistent %s %s." - % (true_labels.shape, predictions.shape)) - _, nC = true_labels.shape - return true_labels, predictions, nC - - -def macro_average(true_labels, predicted_labels, metric, metric_statistics=hard_single_metric_statistics): - true_labels, predicted_labels, nC = __check_consistency_and_adapt(true_labels, predicted_labels) - return np.mean([metric(metric_statistics(true_labels[:, c], predicted_labels[:, c])) for c in range(nC)]) - - -def micro_average(true_labels, predicted_labels, metric, metric_statistics=hard_single_metric_statistics): - true_labels, predicted_labels, nC = __check_consistency_and_adapt(true_labels, predicted_labels) - - accum = ContTable() - for c in range(nC): - other = metric_statistics(true_labels[:, c], predicted_labels[:, c]) - accum = accum + other - - return metric(accum) diff --git a/NewMethods/fgsld/plot_fglsd.png b/NewMethods/fgsld/plot_fglsd.png index e434eadd72f21ab3a304ea83f3cc6c7ccff50bb1..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 165809 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 From daeb3cdd884a0c9952830ac28042bccde29269e0 Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Wed, 10 Mar 2021 11:40:28 +0100 Subject: [PATCH 02/10] cleaning master --- NewMethods/fgsld/__init__.py | 0 NewMethods/fgsld/em.py | 116 -------- NewMethods/fgsld/fglsd_test.py | 75 ----- NewMethods/fgsld/fine_grained_sld.py | 107 -------- NewMethods/fgsld/metrics.py | 260 ------------------ NewMethods/fgsld/plot_fglsd.png | Bin 165809 -> 0 bytes NewMethods/methods.py | 174 ------------ NewMethods/new_experiments.py | 48 ---- NewMethods/new_gen_tables.py | 148 ---------- NewMethods/settings.py | 4 - TweetSentQuant/Gao_Sebastiani_results.txt | 89 ------ TweetSentQuant/evaluate_results.py | 35 --- TweetSentQuant/experiments.py | 214 --------------- TweetSentQuant/gen_plots.py | 95 ------- TweetSentQuant/gen_tables.py | 145 ---------- TweetSentQuant/settings.py | 8 - TweetSentQuant/tabular.py | 318 ---------------------- TweetSentQuant/util.py | 89 ------ 18 files changed, 1925 deletions(-) delete mode 100644 NewMethods/fgsld/__init__.py delete mode 100644 NewMethods/fgsld/em.py delete mode 100644 NewMethods/fgsld/fglsd_test.py delete mode 100644 NewMethods/fgsld/fine_grained_sld.py delete mode 100644 NewMethods/fgsld/metrics.py delete mode 100644 NewMethods/fgsld/plot_fglsd.png delete mode 100644 NewMethods/methods.py delete mode 100644 NewMethods/new_experiments.py delete mode 100644 NewMethods/new_gen_tables.py delete mode 100644 NewMethods/settings.py delete mode 100644 TweetSentQuant/Gao_Sebastiani_results.txt delete mode 100644 TweetSentQuant/evaluate_results.py delete mode 100644 TweetSentQuant/experiments.py delete mode 100644 TweetSentQuant/gen_plots.py delete mode 100644 TweetSentQuant/gen_tables.py delete mode 100644 TweetSentQuant/settings.py delete mode 100644 TweetSentQuant/tabular.py delete mode 100644 TweetSentQuant/util.py diff --git a/NewMethods/fgsld/__init__.py b/NewMethods/fgsld/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/NewMethods/fgsld/em.py b/NewMethods/fgsld/em.py deleted file mode 100644 index 0f6ab6d..0000000 --- a/NewMethods/fgsld/em.py +++ /dev/null @@ -1,116 +0,0 @@ -import numpy as np -import logging -from collections import namedtuple - -from sklearn.metrics import brier_score_loss -from sklearn.preprocessing import MultiLabelBinarizer - -from metrics import smoothmacroF1, isometric_brier_decomposition, isomerous_brier_decomposition - -History = namedtuple('History', ('posteriors', 'priors', 'y', 'iteration', 'stopping_criterium')) -MeasureSingleHistory = namedtuple('MeasureSingleHistory', ( - 'soft_acc', 'soft_f1', 'abs_errors', 'test_priors', 'train_priors', 'predict_priors', 'brier', - 'isometric_ref_loss', 'isometric_cal_loss', 'isomerous_ref_loss', 'isomerous_cal_loss' -)) - - -def get_measures_single_history(history: History, multi_class) -> MeasureSingleHistory: - y = history.y - - y_bin = MultiLabelBinarizer(classes=list(range(history.posteriors.shape[1]))).fit_transform(np.expand_dims(y, 1)) - - soft_acc = soft_accuracy(y, history.posteriors) - f1 = smoothmacroF1(y_bin, history.posteriors) - - if multi_class: - test_priors = np.mean(y_bin, 0) - abs_errors = abs(test_priors - history.priors) - train_priors = history.priors - predict_priors = np.mean(history.posteriors, 0) - brier = 0 - else: - test_priors = np.mean(y_bin, 0)[1] - abs_errors = abs(test_priors - history.priors[1]) - train_priors = history.priors[1] - predict_priors = np.mean(history.posteriors[:, 1]) - brier = brier_score_loss(y, history.posteriors[:, 1]) - - isometric_cal_loss, isometric_ref_loss = isometric_brier_decomposition(y, history.posteriors) - isomerous_em_cal_loss, isomerous_em_ref_loss = isomerous_brier_decomposition(y, history.posteriors) - - return MeasureSingleHistory( - soft_acc, f1, abs_errors, test_priors, train_priors, predict_priors, brier, isometric_ref_loss, - isometric_cal_loss, isomerous_em_ref_loss, isomerous_em_cal_loss - ) - - -def soft_accuracy(y, posteriors): - return sum(posteriors[y == c][:, c].sum() for c in range(posteriors.shape[1])) / posteriors.sum() - - -def soft_f1(y, posteriors): - cont_matrix = { - 'TPM': posteriors[y == 1][:, 1].sum(), - 'TNM': posteriors[y == 0][:, 0].sum(), - 'FPM': posteriors[y == 0][:, 1].sum(), - 'FNM': posteriors[y == 1][:, 0].sum() - } - precision = cont_matrix['TPM'] / (cont_matrix['TPM'] + cont_matrix['FPM']) - recall = cont_matrix['TPM'] / (cont_matrix['TPM'] + cont_matrix['FNM']) - return 2 * (precision * recall / (precision + recall)) - - -def em(y, posteriors_zero, priors_zero, epsilon=1e-6, multi_class=False, return_posteriors_hist=False): - """ - Implements the prior correction method based on EM presented in: - "Adjusting the Outputs of a Classifier to New a Priori Probabilities: A Simple Procedure" - Saerens, Latinne and Decaestecker, 2002 - http://www.isys.ucl.ac.be/staff/marco/Publications/Saerens2002a.pdf - - :param y: true labels of test items, to measure accuracy, precision and recall. - :param posteriors_zero: posterior probabilities on test items, as returned by a classifier. A 2D-array with shape - Ø(items, classes). - :param priors_zero: prior probabilities measured on training set. - :param epsilon: stopping threshold. - :param multi_class: whether the algorithm is running in a multi-label multi-class context or not. - :param return_posteriors_hist: whether posteriors for each iteration should be returned or not. If true, the returned - posteriors_s will actually be the list of posteriors for every iteration. - :return: posteriors_s, priors_s, history: final adjusted posteriors, final adjusted priors, a list of length s - where each element is a tuple with the step counter, the current priors (as list), the stopping criterium value, - accuracy, precision and recall. - """ - s = 0 - priors_s = np.copy(priors_zero) - posteriors_s = np.copy(posteriors_zero) - if return_posteriors_hist: - posteriors_hist = [posteriors_s.copy()] - val = 2 * epsilon - history = list() - history.append(get_measures_single_history(History(posteriors_zero, priors_zero, y, s, 1), multi_class)) - while not val < epsilon and s < 999: - # M step - priors_s_minus_one = priors_s.copy() - priors_s = posteriors_s.mean(0) - - # E step - ratios = priors_s / priors_zero - denominators = 0 - for c in range(priors_zero.shape[0]): - denominators += ratios[c] * posteriors_zero[:, c] - for c in range(priors_zero.shape[0]): - posteriors_s[:, c] = ratios[c] * posteriors_zero[:, c] / denominators - - # check for stop - val = 0 - for i in range(len(priors_s_minus_one)): - val += abs(priors_s_minus_one[i] - priors_s[i]) - - logging.debug(f"Em iteration: {s}; Val: {val}") - s += 1 - if return_posteriors_hist: - posteriors_hist.append(posteriors_s.copy()) - history.append(get_measures_single_history(History(posteriors_s, priors_s, y, s, val), multi_class)) - - if return_posteriors_hist: - return posteriors_hist, priors_s, history - return posteriors_s, priors_s, history diff --git a/NewMethods/fgsld/fglsd_test.py b/NewMethods/fgsld/fglsd_test.py deleted file mode 100644 index 4735a53..0000000 --- a/NewMethods/fgsld/fglsd_test.py +++ /dev/null @@ -1,75 +0,0 @@ -from sklearn.calibration import CalibratedClassifierCV -from sklearn.svm import LinearSVC - -from NewMethods.fgsld.fine_grained_sld import FineGrainedSLD -from method.aggregative import EMQ, CC -from quapy.data import LabelledCollection -from quapy.method.base import BaseQuantifier -import quapy as qp -import quapy.functional as F -from sklearn.linear_model import LogisticRegression - - -class FakeFGLSD(BaseQuantifier): - def __init__(self, learner, nbins, isomerous): - self.learner = learner - self.nbins = nbins - self.isomerous = isomerous - - def fit(self, data: LabelledCollection): - self.Xtr, self.ytr = data.Xy - self.learner.fit(self.Xtr, self.ytr) - return self - - def quantify(self, instances): - tr_priors = F.prevalence_from_labels(self.ytr, n_classes=2) - fgsld = FineGrainedSLD(self.Xtr, instances, self.ytr, tr_priors, self.learner, n_bins=self.nbins) - priors, posteriors = fgsld.run(self.isomerous) - return priors - - def get_params(self, deep=True): - pass - - def set_params(self, **parameters): - pass - - - -qp.environ['SAMPLE_SIZE'] = 500 - -dataset = qp.datasets.fetch_reviews('hp') -qp.data.preprocessing.text2tfidf(dataset, min_df=5, inplace=True) - -training = dataset.training -test = dataset.test - -cls = CalibratedClassifierCV(LinearSVC()) - - -method_names, true_prevs, estim_prevs, tr_prevs = [], [], [], [] - -for model, model_name in [ - (CC(cls), 'CC'), - (FakeFGLSD(cls, nbins=1, isomerous=False), 'FGSLD-1'), - (FakeFGLSD(cls, nbins=2, isomerous=False), 'FGSLD-2'), - #(FakeFGLSD(cls, nbins=5, isomerous=False), 'FGSLD-5'), - #(FakeFGLSD(cls, nbins=10, isomerous=False), 'FGSLD-10'), - #(FakeFGLSD(cls, nbins=50, isomerous=False), 'FGSLD-50'), - #(FakeFGLSD(cls, nbins=100, isomerous=False), 'FGSLD-100'), -# (FakeFGLSD(cls, nbins=1, isomerous=False), 'FGSLD-1'), - #(FakeFGLSD(cls, nbins=10, isomerous=True), 'FGSLD-10-ISO'), - # (FakeFGLSD(cls, nbins=50, isomerous=False), 'FGSLD-50'), - (EMQ(cls), 'SLD'), -]: - print('running ', model_name) - model.fit(training) - true_prev, estim_prev = qp.evaluation.artificial_sampling_prediction( - model, test, qp.environ['SAMPLE_SIZE'], n_repetitions=10, n_prevpoints=21, n_jobs=-1 - ) - method_names.append(model_name) - true_prevs.append(true_prev) - estim_prevs.append(estim_prev) - tr_prevs.append(training.prevalence()) - - -qp.plot.binary_diagonal(method_names, true_prevs, estim_prevs, train_prev=tr_prevs[0], savepath='./plot_fglsd.png') diff --git a/NewMethods/fgsld/fine_grained_sld.py b/NewMethods/fgsld/fine_grained_sld.py deleted file mode 100644 index f955491..0000000 --- a/NewMethods/fgsld/fine_grained_sld.py +++ /dev/null @@ -1,107 +0,0 @@ -import numpy as np -from metrics import isomerous_bins, isometric_bins -from em import History, get_measures_single_history - - -class FineGrainedSLD: - def __init__(self, x_tr, x_te, y_tr, tr_priors, clf, n_bins=10): - self.y_tr = y_tr - self.clf = clf - self.tr_priors = tr_priors - self.tr_preds = clf.predict_proba(x_tr) - self.te_preds = clf.predict_proba(x_te) - self.n_bins = n_bins - self.history: [History] = [] - self.multi_class = False - - def run(self, isomerous_binning, epsilon=1e-6, compute_bins_at_every_iter=False, return_posteriors_hist=False): - """ - Run the FGSLD algorithm. - - :param isomerous_binning: whether to use isomerous or isometric binning. - :param epsilon: stopping condition. - :param compute_bins_at_every_iter: whether FGSLD should recompute the posterior bins at every iteration or not. - :param return_posteriors_hist: whether to return posteriors at every iteration or not. - :return: If `return_posteriors_hist` is true, the returned posteriors will be a list of numpy arrays, else a single numpy array with posteriors at last iteration. - """ - smoothing_tr = 1 / (2 * self.y_tr.shape[0]) - smoothing_te = smoothing_tr - s = 0 - tr_bin_priors = np.zeros((self.n_bins, self.tr_preds.shape[1]), dtype=np.float) - te_bin_priors = np.zeros((self.n_bins, self.te_preds.shape[1]), dtype=np.float) - tr_bins = self.__create_bins(training=True, isomerous_binning=isomerous_binning) - te_bins = self.__create_bins(training=False, isomerous_binning=isomerous_binning) - self.__compute_bins_priors(tr_bin_priors, self.tr_preds, tr_bins, smoothing_tr) - - val = 2 * epsilon - if return_posteriors_hist: - posteriors_hist = [self.te_preds.copy()] - while not val < epsilon and s < 1000: - assert np.all(np.around(self.te_preds.sum(axis=1), 4) == 1), f"Probabilities do not sum to 1:\ns={s}, " \ - f"probs={self.te_preds.sum(axis=1)}" - if compute_bins_at_every_iter: - te_bins = self.__create_bins(training=False, isomerous_binning=isomerous_binning) - - if s == 0: - te_bin_priors_prev = tr_bin_priors.copy() - else: - te_bin_priors_prev = te_bin_priors.copy() - self.__compute_bins_priors(te_bin_priors, self.te_preds, te_bins, smoothing_te) - - te_preds_cp = self.te_preds.copy() - for label_idx, bins in te_bins.items(): - for i, bin_ in enumerate(bins): - if bin_.shape[0] == 0: - continue - self.te_preds[:, label_idx][bin_] = (te_preds_cp[:, label_idx][bin_]) * \ - (te_bin_priors[i][label_idx] / te_bin_priors_prev[i][label_idx]) - - # Normalization step - self.te_preds = (self.te_preds.T / self.te_preds.sum(axis=1)).T - - val = 0 - for label_idx in range(te_bin_priors.shape[1]): - if (temp := max(abs((te_bin_priors[:, label_idx] / te_bin_priors_prev[:, label_idx]) - 1))) > val: - val = temp - s += 1 - if return_posteriors_hist: - posteriors_hist.append(self.te_preds.copy()) - if return_posteriors_hist: - return self.te_preds.mean(axis=0), posteriors_hist - return self.te_preds.mean(axis=0), self.te_preds - - def __compute_bins_priors(self, bin_priors_placeholder, posteriors, bins, smoothing): - for label_idx, bins in bins.items(): - for i, bin_ in enumerate(bins): - if bin_.shape[0] == 0: - bin_priors_placeholder[i, label_idx] = smoothing - continue - numerator = posteriors[:, label_idx][bin_].mean() - bin_prior = (numerator + smoothing) / (1 + self.n_bins * smoothing) # normalize priors - bin_priors_placeholder[i, label_idx] = bin_prior - - def __find_bin_idx(self, label_bins: [np.array], idx: int or list): - if hasattr(idx, '__len__'): - idxs = np.zeros(len(idx), dtype=np.int) - for i, bin_ in enumerate(label_bins): - for j, id_ in enumerate(idx): - if id_ in bin_: - idxs[j] = i - return idxs - else: - for i, bin_ in enumerate(label_bins): - if idx in bin_: - return i - - def __create_bins(self, training: bool, isomerous_binning: bool): - bins = {} - preds = self.tr_preds if training else self.te_preds - if isomerous_binning: - for label_idx in range(preds.shape[1]): - bins[label_idx] = isomerous_bins(label_idx, preds, self.n_bins) - else: - intervals = np.linspace(0., 1., num=self.n_bins, endpoint=False) - for label_idx in range(preds.shape[1]): - bins_ = isometric_bins(label_idx, preds, intervals, 0.1) - bins[label_idx] = [bins_[i] for i in intervals] - return bins diff --git a/NewMethods/fgsld/metrics.py b/NewMethods/fgsld/metrics.py deleted file mode 100644 index c95e757..0000000 --- a/NewMethods/fgsld/metrics.py +++ /dev/null @@ -1,260 +0,0 @@ -import numpy as np - -""" -Scikit learn provides a full set of evaluation metrics, but they treat special cases differently. -I.e., when the number of true positives, false positives, and false negatives ammount to 0, all -affected metrics (precision, recall, and thus f1) output 0 in Scikit learn. -We adhere to the common practice of outputting 1 in this case since the classifier has correctly -classified all examples as negatives. -""" - - -def isometric_brier_decomposition(true_labels, predicted_labels, bin_intervals=np.arange(0., 1.1, 0.1), step=0.1): - """ - The Isometric Brier decomposition or score is obtained by partitioning U into intervals I_1j,...,I_bj that - have equal length, where U is the total size of our test set (i.e., true_labels.shape[0]). This means that, - if b=10 then I_1j = [0.0,0.1), I_2j = [0.2, 0.3),...,I_bj = [0.9,1.0). - - bin_intervals is a numpy.array containing the range of the different intervals. Since it is a single dimensional - array, for every interval I_n we take the posterior probabilities Pr_n(x) such that I_n <= Pr_n(x) < I_n + step. - This variable defaults to np.arange(0., 1.0, 0.1), i.e. an array like [0.1, 0.2, ..., 1.0]. - - :return: a tuple (calibration score, refinement score) - """ - labels = set(true_labels) - calibration_score, refinement_score = 0.0, 0.0 - for i in range(len(labels)): - bins = isometric_bins(i, predicted_labels, bin_intervals, step) - c_score, r_score = brier_decomposition(bins.values(), true_labels, predicted_labels, class_=i) - calibration_score += c_score - refinement_score += r_score - return calibration_score, refinement_score - - -def isomerous_brier_decomposition(true_labels, predicted_labels, n=10): - """ - The Isomerous Brier decomposition or score is obtained by partitioning U into intervals I_1j,...,I_bj such that - the corresponding bins B_1j,...,B_bj have equal size, where U is our test set. This means that, for every x' in - B_sj and x'' in B_tj with s < t, it holds that Pr(c_j|x') <= Pr(c_j|x'') and |B_sj| == |B_tj|, for any s,t in - {1,...,b}. - - The n variable holds the number of bins we want (defaults to 10). Notice that we perform a numpy.array_split on - the predicted_labels, creating l % n sub-arrays of size l//n + 1 and the rest of size l//n, where l is the length - of the array. - - :return: a tuple (calibration score, refinement score) - """ - - labels = set(true_labels) - calibration_score, refinement_score = 0.0, 0.0 - for i in range(len(labels)): - bins = isomerous_bins(i, predicted_labels, n) - c_score, r_score = brier_decomposition(bins, true_labels, predicted_labels, class_=i) - calibration_score += c_score - refinement_score += r_score - return calibration_score, refinement_score - - -def brier_decomposition(bins, true_labels, predicted_labels, class_=1): - """ - :param bins: must be an array of indices - :return: a tuple (calibration_score, refinement_score) - """ - calibration_score = 0 - refinement_score = 0 - for bin_ in bins: - if bin_.size <= 0: - continue - v_x = (bin_.shape[0] / true_labels.shape[0]) - ro_x = np.mean(true_labels[bin_] == class_) - calibration_score += v_x * (predicted_labels[bin_, class_].mean() - ro_x)**2 - refinement_score += (v_x * ro_x) * (1 - ro_x) - labels_len = len(set(true_labels)) - return calibration_score / (labels_len * len(bins)), refinement_score / (labels_len * len(bins)) - - -def isometric_bins(label_index, predicted_labels, bin_intervals, step): - predicted_class_label = predicted_labels[:, label_index] - return {interv: np.where(np.logical_and(interv <= predicted_class_label, predicted_class_label < interv + step))[0] - for interv in bin_intervals} - - -def isomerous_bins(label_index, predicted_labels, n): - sorted_indices = predicted_labels[:, label_index].argsort() - return np.array_split(sorted_indices, n) - - -# true_labels and predicted_labels are two matrices in sklearn.preprocessing.MultiLabelBinarizer format -def macroF1(true_labels, predicted_labels): - return macro_average(true_labels, predicted_labels, f1) - - -# true_labels and predicted_labels are two matrices in sklearn.preprocessing.MultiLabelBinarizer format -def microF1(true_labels, predicted_labels): - return micro_average(true_labels, predicted_labels, f1) - - -# true_labels and predicted_labels are two matrices in sklearn.preprocessing.MultiLabelBinarizer format -def macroK(true_labels, predicted_labels): - return macro_average(true_labels, predicted_labels, K) - - -# true_labels and predicted_labels are two matrices in sklearn.preprocessing.MultiLabelBinarizer format -def microK(true_labels, predicted_labels): - return micro_average(true_labels, predicted_labels, K) - - -# true_labels is a matrix in sklearn.preprocessing.MultiLabelBinarizer format and posterior_probabilities is a matrix -# of the same shape containing real values in [0,1] -def smoothmacroF1(true_labels, posterior_probabilities): - return macro_average(true_labels, posterior_probabilities, f1, metric_statistics=soft_single_metric_statistics) - - -# true_labels is a matrix in sklearn.preprocessing.MultiLabelBinarizer format and posterior_probabilities is a matrix -# of the same shape containing real values in [0,1] -def smoothmicroF1(true_labels, posterior_probabilities): - return micro_average(true_labels, posterior_probabilities, f1, metric_statistics=soft_single_metric_statistics) - - -# true_labels is a matrix in sklearn.preprocessing.MultiLabelBinarizer format and posterior_probabilities is a matrix -# of the same shape containing real values in [0,1] -def smoothmacroK(true_labels, posterior_probabilities): - return macro_average(true_labels, posterior_probabilities, K, metric_statistics=soft_single_metric_statistics) - - -# true_labels is a matrix in sklearn.preprocessing.MultiLabelBinarizer format and posterior_probabilities is a matrix -# of the same shape containing real values in [0,1] -def smoothmicroK(true_labels, posterior_probabilities): - return micro_average(true_labels, posterior_probabilities, K, metric_statistics=soft_single_metric_statistics) - - -class ContTable: - def __init__(self, tp=0, tn=0, fp=0, fn=0): - self.tp = tp - self.tn = tn - self.fp = fp - self.fn = fn - - def get_d(self): return self.tp + self.tn + self.fp + self.fn - - def get_c(self): return self.tp + self.fn - - def get_not_c(self): return self.tn + self.fp - - def get_f(self): return self.tp + self.fp - - def get_not_f(self): return self.tn + self.fn - - def p_c(self): return (1.0 * self.get_c()) / self.get_d() - - def p_not_c(self): return 1.0 - self.p_c() - - def p_f(self): return (1.0 * self.get_f()) / self.get_d() - - def p_not_f(self): return 1.0 - self.p_f() - - def p_tp(self): return (1.0 * self.tp) / self.get_d() - - def p_tn(self): return (1.0 * self.tn) / self.get_d() - - def p_fp(self): return (1.0 * self.fp) / self.get_d() - - def p_fn(self): return (1.0 * self.fn) / self.get_d() - - def tpr(self): - c = 1.0 * self.get_c() - return self.tp / c if c > 0.0 else 0.0 - - def fpr(self): - _c = 1.0 * self.get_not_c() - return self.fp / _c if _c > 0.0 else 0.0 - - def __add__(self, other): - return ContTable(tp=self.tp + other.tp, tn=self.tn + other.tn, fp=self.fp + other.fp, fn=self.fn + other.fn) - - -def accuracy(cell): - return (cell.tp + cell.tn) * 1.0 / (cell.tp + cell.fp + cell.fn + cell.tn) - - -def f1(cell): - num = 2.0 * cell.tp - den = 2.0 * cell.tp + cell.fp + cell.fn - if den > 0: return num / den - # we define f1 to be 1 if den==0 since the classifier has correctly classified all instances as negative - return 1.0 - - -def K(cell): - specificity, recall = 0., 0. - - AN = cell.tn + cell.fp - if AN != 0: - specificity = cell.tn * 1. / AN - - AP = cell.tp + cell.fn - if AP != 0: - recall = cell.tp * 1. / AP - - if AP == 0: - return 2. * specificity - 1. - elif AN == 0: - return 2. * recall - 1. - else: - return specificity + recall - 1. - - -# computes the (hard) counters tp, fp, fn, and tn fron a true and predicted vectors of hard decisions -# true_labels and predicted_labels are two vectors of shape (number_documents,) -def hard_single_metric_statistics(true_labels, predicted_labels): - assert len(true_labels) == len(predicted_labels), "Format not consistent between true and predicted labels." - nd = len(true_labels) - tp = np.sum(predicted_labels[true_labels == 1]) - fp = np.sum(predicted_labels[true_labels == 0]) - fn = np.sum(true_labels[predicted_labels == 0]) - tn = nd - (tp + fp + fn) - return ContTable(tp=tp, tn=tn, fp=fp, fn=fn) - - -# computes the (soft) contingency table where tp, fp, fn, and tn are the cumulative masses for the posterioir -# probabilitiesfron with respect to the true binary labels -# true_labels and posterior_probabilities are two vectors of shape (number_documents,) -def soft_single_metric_statistics(true_labels, posterior_probabilities): - assert len(true_labels) == len(posterior_probabilities), "Format not consistent between true and predicted labels." - pos_probs = posterior_probabilities[true_labels == 1] - neg_probs = posterior_probabilities[true_labels == 0] - tp = np.sum(pos_probs) - fn = np.sum(1. - pos_probs) - fp = np.sum(neg_probs) - tn = np.sum(1. - neg_probs) - return ContTable(tp=tp, tn=tn, fp=fp, fn=fn) - - -# if the classifier is single class, then the prediction is a vector of shape=(nD,) which causes issues when compared -# to the true labels (of shape=(nD,1)). This method increases the dimensions of the predictions. -def __check_consistency_and_adapt(true_labels, predictions): - if predictions.ndim == 1: - return __check_consistency_and_adapt(true_labels, np.expand_dims(predictions, axis=1)) - if true_labels.ndim == 1: - return __check_consistency_and_adapt(np.expand_dims(true_labels, axis=1), predictions) - if true_labels.shape != predictions.shape: - raise ValueError("True and predicted label matrices shapes are inconsistent %s %s." - % (true_labels.shape, predictions.shape)) - _, nC = true_labels.shape - return true_labels, predictions, nC - - -def macro_average(true_labels, predicted_labels, metric, metric_statistics=hard_single_metric_statistics): - true_labels, predicted_labels, nC = __check_consistency_and_adapt(true_labels, predicted_labels) - return np.mean([metric(metric_statistics(true_labels[:, c], predicted_labels[:, c])) for c in range(nC)]) - - -def micro_average(true_labels, predicted_labels, metric, metric_statistics=hard_single_metric_statistics): - true_labels, predicted_labels, nC = __check_consistency_and_adapt(true_labels, predicted_labels) - - accum = ContTable() - for c in range(nC): - other = metric_statistics(true_labels[:, c], predicted_labels[:, c]) - accum = accum + other - - return metric(accum) diff --git a/NewMethods/fgsld/plot_fglsd.png b/NewMethods/fgsld/plot_fglsd.png deleted file mode 100644 index e434eadd72f21ab3a304ea83f3cc6c7ccff50bb1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165809 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 diff --git a/NewMethods/methods.py b/NewMethods/methods.py deleted file mode 100644 index b47927d..0000000 --- a/NewMethods/methods.py +++ /dev/null @@ -1,174 +0,0 @@ -import numpy as np -from sklearn.base import BaseEstimator -from sklearn.decomposition import PCA -from sklearn.preprocessing import StandardScaler - -import quapy as qp -from typing import Union - -from quapy.data import LabelledCollection -from quapy.method.base import BaseQuantifier, BinaryQuantifier -from quapy.method.aggregative import PACC, EMQ, HDy -import quapy.functional as F -from tqdm import tqdm -from scipy.sparse import issparse, csr_matrix -import scipy - - -class PACCSLD(PACC): - """ - This method combines the EMQ improved posterior probabilities with PACC. - Note: the posterior probabilities are re-calibrated with EMQ only during prediction, and not also during fit since, - for PACC, the validation split is known to have the same prevalence as the training set (this is because the split - is stratified) and thus the posterior probabilities should not be re-calibrated for a different prior (it actually - happens to degrades performance). - """ - - def fit(self, data: qp.data.LabelledCollection, fit_learner=True, val_split:Union[float, int, qp.data.LabelledCollection]=0.4): - self.train_prevalence = F.prevalence_from_labels(data.labels, data.n_classes) - return super(PACCSLD, self).fit(data, fit_learner, val_split) - - def aggregate(self, classif_posteriors): - priors, posteriors = EMQ.EM(self.train_prevalence, classif_posteriors, epsilon=1e-4) - return super(PACCSLD, self).aggregate(posteriors) - - -class HDySLD(HDy): - """ - This method combines the EMQ improved posterior probabilities with HDy. - Note: [same as PACCSLD] - """ - def fit(self, data: qp.data.LabelledCollection, fit_learner=True, - val_split: Union[float, int, qp.data.LabelledCollection] = 0.4): - self.train_prevalence = F.prevalence_from_labels(data.labels, data.n_classes) - return super(HDySLD, self).fit(data, fit_learner, val_split) - - def aggregate(self, classif_posteriors): - priors, posteriors = EMQ.EM(self.train_prevalence, classif_posteriors, epsilon=1e-4) - return super(HDySLD, self).aggregate(posteriors) - - - -class AveragePoolQuantification(BinaryQuantifier): - def __init__(self, learner, sample_size, trials, n_components=-1, zscore=False): - self.learner = learner - self.sample_size = sample_size - self.trials = trials - - self.do_zscore = zscore - self.zscore = StandardScaler() if self.do_zscore else None - - self.do_pca = n_components>0 - self.pca = PCA(n_components) if self.do_pca else None - - def fit(self, data: LabelledCollection): - training, validation = data.split_stratified(train_prop=0.7) - - X, y = [], [] - - nprevpoints = F.get_nprevpoints_approximation(self.trials, data.n_classes) - for sample in tqdm( - training.artificial_sampling_generator(self.sample_size, n_prevalences=nprevpoints, repeats=1), - desc='generating averages' - ): - X.append(sample.instances.mean(axis=0)) - y.append(sample.prevalence()[1]) - while len(X) < self.trials: - sample = training.sampling(self.sample_size, F.uniform_simplex_sampling(data.n_classes)) - X.append(sample.instances.mean(axis=0)) - y.append(sample.prevalence()) - X = np.asarray(np.vstack(X)) - y = np.asarray(y) - - if self.do_pca: - X = self.pca.fit_transform(X) - print(X.shape) - - if self.do_zscore: - X = self.zscore.fit_transform(X) - - print('training regressor...') - self.regressor = self.learner.fit(X, y) - - # correction at 0: - print('getting corrections...') - X0 = np.asarray(np.vstack([validation.sampling(self.sample_size, 0., shuffle=False).instances.mean(axis=0) for _ in range(100)])) - X1 = np.asarray(np.vstack([validation.sampling(self.sample_size, 1., shuffle=False).instances.mean(axis=0) for _ in range(100)])) - - if self.do_pca: - X0 = self.pca.transform(X0) - X1 = self.pca.transform(X1) - - if self.do_zscore: - X0 = self.zscore.transform(X0) - X1 = self.zscore.transform(X1) - - self.correction_0 = self.regressor.predict(X0).mean() - self.correction_1 = self.regressor.predict(X1).mean() - - print('correction-0', self.correction_0) - print('correction-1', self.correction_1) - print('done') - - def quantify(self, instances): - ave = np.asarray(instances.mean(axis=0)) - - if self.do_pca: - ave = self.pca.transform(ave) - if self.do_zscore: - ave = self.zscore.transform(ave) - phat = self.regressor.predict(ave).item() - phat = np.clip((phat-self.correction_0)/(self.correction_1-self.correction_0), 0, 1) - return np.asarray([1-phat, phat]) - - def set_params(self, **parameters): - self.learner.set_params(**parameters) - - def get_params(self, deep=True): - return self.learner.get_params(deep=deep) - - -class WinnowOrthogonal(BaseEstimator): - - def __init__(self): - pass - - def fit(self, X, y): - self.classes_ = np.asarray(sorted(np.unique(y))) - w1 = np.asarray(X[y == 0].mean(axis=0)).flatten() - w2 = np.asarray(X[y == 1].mean(axis=0)).flatten() - diff = w2 - w1 - orth = np.ones_like(diff) - orth[0] = -diff[1:].sum() / diff[0] - orth /= np.linalg.norm(orth) - self.w = orth - self.b = w1.dot(orth) - return self - - def decision_function(self, X): - if issparse(X): - Z = X.dot(csr_matrix(self.w).T).toarray().flatten() - return Z - self.b - else: - return np.matmul(X, self.w) - self.b - - def predict(self, X): - return 1 * (self.decision_function(X) > 0) - - def split(self, X, y): - s = self.predict(X) - X0a = X[np.logical_and(y == 0, s == 0)] - X0b = X[np.logical_and(y == 0, s == 1)] - X1a = X[np.logical_and(y == 1, s == 0)] - X1b = X[np.logical_and(y == 1, s == 1)] - y0a = np.zeros(X0a.shape[0], dtype=np.int) - y0b = np.zeros(X0b.shape[0], dtype=np.int) - y1a = np.ones(X1a.shape[0], dtype=np.int) - y1b = np.ones(X1b.shape[0], dtype=np.int) - return X0a, X0b, X1a, X1b, y0a, y0b, y1a, y1b - - def get_params(self): - return {} - - def set_params(self, **params): - pass diff --git a/NewMethods/new_experiments.py b/NewMethods/new_experiments.py deleted file mode 100644 index d60b158..0000000 --- a/NewMethods/new_experiments.py +++ /dev/null @@ -1,48 +0,0 @@ -from sklearn.linear_model import LogisticRegression -import quapy as qp -from classification.methods import PCALR -from method.meta import QuaNet -from quapy.method.aggregative import * -from NewMethods.methods import * -from experiments import run, SAMPLE_SIZE -import numpy as np -import itertools -from joblib import Parallel, delayed -import settings -import argparse -import torch - -parser = argparse.ArgumentParser(description='Run experiments for Tweeter Sentiment Quantification') -parser.add_argument('results', metavar='RESULT_PATH', type=str, help='path to the directory where to store the results') -#parser.add_argument('svmperfpath', metavar='SVMPERF_PATH', type=str, help='path to the directory with svmperf') -args = parser.parse_args() - - -def quantification_models(): - def newLR(): - return LogisticRegression(max_iter=1000, solver='lbfgs', n_jobs=-1) - __C_range = np.logspace(-4, 5, 10) - lr_params = {'C': __C_range, 'class_weight': [None, 'balanced']} - svmperf_params = {'C': __C_range} - #yield 'paccsld', PACCSLD(newLR()), lr_params - yield 'hdysld', OneVsAll(HDySLD(newLR())), lr_params # <-- promising! - - #device = 'cuda' if torch.cuda.is_available() else 'cpu' - #print(f'Running QuaNet in {device}') - #yield 'quanet', QuaNet(PCALR(**newLR().get_params()), SAMPLE_SIZE, device=device), lr_params - - -if __name__ == '__main__': - - print(f'Result folder: {args.results}') - np.random.seed(0) - - optim_losses = ['mae'] - datasets = qp.datasets.TWITTER_SENTIMENT_DATASETS_TRAIN - models = quantification_models() - - results = Parallel(n_jobs=settings.N_JOBS)( - delayed(run)(experiment) for experiment in itertools.product(optim_losses, datasets, models) - ) - - diff --git a/NewMethods/new_gen_tables.py b/NewMethods/new_gen_tables.py deleted file mode 100644 index c6aeb7e..0000000 --- a/NewMethods/new_gen_tables.py +++ /dev/null @@ -1,148 +0,0 @@ -import quapy as qp -import numpy as np -from os import makedirs -import sys, os -import pickle -from experiments import result_path -from gen_tables import save_table, experiment_errors -from tabular import Table -import argparse - -tables_path = './tables' -MAXTONE = 50 # sets the intensity of the maximum color reached by the worst (red) and best (green) results - -makedirs(tables_path, exist_ok=True) - -sample_size = 100 -qp.environ['SAMPLE_SIZE'] = sample_size - - -nice = { - 'mae':'AE', - 'mrae':'RAE', - 'ae':'AE', - 'rae':'RAE', - 'svmkld': 'SVM(KLD)', - 'svmnkld': 'SVM(NKLD)', - 'svmq': 'SVM(Q)', - 'svmae': 'SVM(AE)', - 'svmnae': 'SVM(NAE)', - 'svmmae': 'SVM(AE)', - 'svmmrae': 'SVM(RAE)', - 'quanet': 'QuaNet', - 'hdy': 'HDy', - 'hdysld': 'HDy-SLD', - 'dys': 'DyS', - 'svmperf':'', - 'sanders': 'Sanders', - 'semeval13': 'SemEval13', - 'semeval14': 'SemEval14', - 'semeval15': 'SemEval15', - 'semeval16': 'SemEval16', - 'Average': 'Average' -} - - -def nicerm(key): - return '\mathrm{'+nice[key]+'}' - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Generate tables for Tweeter Sentiment Quantification') - parser.add_argument('results', metavar='RESULT_PATH', type=str, - help='path to the directory containing the results of the methods tested in Gao & Sebastiani') - parser.add_argument('newresults', metavar='RESULT_PATH', type=str, - help='path to the directory containing the results for the experimental methods') - args = parser.parse_args() - - datasets = qp.datasets.TWITTER_SENTIMENT_DATASETS_TEST - evaluation_measures = [qp.error.ae, qp.error.rae] - gao_seb_methods = ['cc', 'acc', 'pcc', 'pacc', 'sld', 'svmq', 'svmkld', 'svmnkld'] - new_methods = ['hdy'] # methods added to the Gao & Sebastiani methods - experimental_methods = ['hdysld'] # experimental - - for i, eval_func in enumerate(evaluation_measures): - - # Tables evaluation scores for AE and RAE (two tables) - # ---------------------------------------------------- - - eval_name = eval_func.__name__ - - added_methods = ['svmm' + eval_name] + new_methods - methods = gao_seb_methods + added_methods + experimental_methods - nold_methods = len(gao_seb_methods) - nnew_methods = len(added_methods) - nexp_methods = len(experimental_methods) - - # fill data table - table = Table(benchmarks=datasets, methods=methods) - for dataset in datasets: - for method in methods: - if method in experimental_methods: - path = args.newresults - else: - path = args.results - table.add(dataset, method, experiment_errors(path, dataset, method, eval_name)) - - # write the latex table - tabular = """ - \\begin{tabularx}{\\textwidth}{|c||""" + ('Y|'*nold_methods) + '|' + ('Y|'*nnew_methods) + '|' + ('Y|'*nexp_methods) + """} \hline - & \multicolumn{"""+str(nold_methods)+"""}{c||}{Methods tested in~\cite{Gao:2016uq}} & - \multicolumn{"""+str(nnew_methods)+"""}{c|}{} & - \multicolumn{"""+str(nexp_methods)+"""}{c|}{}\\\\ \hline - """ - rowreplace={dataset: nice.get(dataset, dataset.upper()) for dataset in datasets} - colreplace={method:'\side{' + nice.get(method, method.upper()) +'$^{' + nicerm(eval_name) + '}$} ' for method in methods} - - tabular += table.latexTabular(benchmark_replace=rowreplace, method_replace=colreplace) - tabular += "\n\end{tabularx}" - - save_table(f'./tables/tab_results_{eval_name}.new.tex', tabular) - - # Tables ranks for AE and RAE (two tables) - # ---------------------------------------------------- - # fill the data table - ranktable = Table(benchmarks=datasets, methods=methods, missing='--') - for dataset in datasets: - for method in methods: - ranktable.add(dataset, method, values=table.get(dataset, method, 'rank')) - - # write the latex table - tabular = """ - \\begin{tabularx}{\\textwidth}{|c||""" + ('Y|'*nold_methods) + '|' + ('Y|'*nnew_methods) + '|' + ('Y|'*nexp_methods) + """} \hline - & \multicolumn{"""+str(nold_methods)+"""}{c||}{Methods tested in~\cite{Gao:2016uq}} & - \multicolumn{"""+str(nnew_methods)+"""}{c|}{} & - \multicolumn{"""+str(nexp_methods)+"""}{c|}{}\\\\ \hline - """ - for method in methods: - tabular += ' & \side{' + nice.get(method, method.upper()) +'$^{' + nicerm(eval_name) + '}$} ' - tabular += '\\\\\hline\n' - - for dataset in datasets: - tabular += nice.get(dataset, dataset.upper()) + ' ' - for method in methods: - newrank = ranktable.get(dataset, method) - if newrank != '--': - newrank = f'{int(newrank)}' - color = ranktable.get_color(dataset, method) - if color == '--': - color = '' - tabular += ' & ' + f'{newrank}' + color - tabular += '\\\\\hline\n' - tabular += '\hline\n' - - tabular += 'Average ' - for method in methods: - newrank = ranktable.get_average(method) - if newrank != '--': - newrank = f'{newrank:.1f}' - color = ranktable.get_average(method, 'color') - if color == '--': - color = '' - tabular += ' & ' + f'{newrank}' + color - tabular += '\\\\\hline\n' - tabular += "\end{tabularx}" - - save_table(f'./tables/tab_rank_{eval_name}.new.tex', tabular) - - print("[Done]") diff --git a/NewMethods/settings.py b/NewMethods/settings.py deleted file mode 100644 index 2ade31a..0000000 --- a/NewMethods/settings.py +++ /dev/null @@ -1,4 +0,0 @@ -import multiprocessing - -N_JOBS = -2 #multiprocessing.cpu_count() -SAMPLE_SIZE = 100 \ No newline at end of file diff --git a/TweetSentQuant/Gao_Sebastiani_results.txt b/TweetSentQuant/Gao_Sebastiani_results.txt deleted file mode 100644 index de0e6dd..0000000 --- a/TweetSentQuant/Gao_Sebastiani_results.txt +++ /dev/null @@ -1,89 +0,0 @@ - AE RAE -SemEval13 SVM-KLD 0.0722 0.1720 - SVM-NKLD 0.0714 0.2756 - SVM-QBETA2 0.0782 0.2775 - LR-CC 0.0996 0.3095 - LR-EM 0.1191 0.3923 - LR-PCC 0.0344 0.1506 - LR-ACC 0.0806 0.2479 - LR-PACC 0.0812 0.2626 -SemEval14 SVM-KLD 0.0843 0.2268 - SVM-NKLD 0.0836 0.3367 - SVM-QBETA2 0.1018 0.3680 - LR-CC 0.1043 0.3212 - LR-EM 0.0807 0.3517 - LR-PCC 0.1001 0.4277 - LR-ACC 0.0581 0.2360 - LR-PACC 0.0533 0.2573 -SemEval15 SVM-KLD 0.1185 0.3789 - SVM-NKLD 0.1155 0.4720 - SVM-QBETA2 0.1263 0.4762 - LR-CC 0.1101 0.2879 - LR-EM 0.1204 0.2949 - LR-PCC 0.0460 0.1973 - LR-ACC 0.1064 0.2971 - LR-PACC 0.1013 0.2729 -SemEval16 SVM-KLD 0.0385 0.1512 - SVM-NKLD 0.0830 0.3249 - SVM-QBETA2 0.1201 0.5156 - LR-CC 0.0500 0.1771 - LR-EM 0.0646 0.2126 - LR-PCC 0.0379 0.1553 - LR-ACC 0.0542 0.2246 - LR-PACC 0.0864 0.3504 -Sanders SVM-KLD 0.0134 0.0630 - SVM-NKLD 0.0950 0.3965 - SVM-QBETA2 0.1098 0.4360 - LR-CC 0.0671 0.2682 - LR-EM 0.0715 0.2849 - LR-PCC 0.0150 0.0602 - LR-ACC 0.0338 0.1306 - LR-PACC 0.0301 0.1173 -SST SVM-KLD 0.0413 0.1458 - SVM-NKLD 0.0749 0.2497 - SVM-QBETA2 0.0671 0.2343 - LR-CC 0.0330 0.1239 - LR-EM 0.0369 0.1190 - LR-PCC 0.0282 0.1068 - LR-ACC 0.0492 0.1689 - LR-PACC 0.0841 0.2302 -OMD SVM-KLD 0.0305 0.0999 - SVM-NKLD 0.0437 0.1279 - SVM-QBETA2 0.0624 0.1826 - LR-CC 0.0524 0.1527 - LR-EM 0.0648 0.1886 - LR-PCC 0.0046 0.0095 - LR-ACC 0.0239 0.0753 - LR-PACC 0.0100 0.0293 -HCR SVM-KLD 0.0414 0.2191 - SVM-NKLD 0.0604 0.2324 - SVM-QBETA2 0.1272 0.4600 - LR-CC 0.0525 0.1817 - LR-EM 0.0895 0.3093 - LR-PCC 0.0055 0.0202 - LR-ACC 0.0240 0.1026 - LR-PACC 0.0329 0.1436 -GASP SVM-KLD 0.0171 0.0529 - SVM-NKLD 0.0503 0.3416 - SVM-QBETA2 0.0640 0.4402 - LR-CC 0.0189 0.1297 - LR-EM 0.0231 0.1589 - LR-PCC 0.0097 0.0682 - LR-ACC 0.0150 0.1038 - LR-PACC 0.0087 0.0597 -WA SVM-KLD 0.0647 0.1957 - SVM-NKLD 0.0393 0.1357 - SVM-QBETA2 0.0798 0.2332 - LR-CC 0.0434 0.1270 - LR-EM 0.0391 0.1145 - LR-PCC 0.0338 0.0990 - LR-ACC 0.0407 0.1197 - LR-PACC 0.0277 0.0815 -WB SVM-KLD 0.0613 0.1791 - SVM-NKLD 0.0534 0.1756 - SVM-QBETA2 0.0249 0.0774 - LR-CC 0.0132 0.0399 - LR-EM 0.0244 0.0773 - LR-PCC 0.0123 0.0390 - LR-ACC 0.0230 0.0719 - LR-PACC 0.0165 0.0515 \ No newline at end of file diff --git a/TweetSentQuant/evaluate_results.py b/TweetSentQuant/evaluate_results.py deleted file mode 100644 index 2b8a4d0..0000000 --- a/TweetSentQuant/evaluate_results.py +++ /dev/null @@ -1,35 +0,0 @@ -import numpy as np -import quapy as qp -import settings -import os -import pickle -from glob import glob -import itertools -import pathlib - -qp.environ['SAMPLE_SIZE'] = settings.SAMPLE_SIZE - -resultdir = './results' -methods = ['*'] - - -def evaluate_results(methods, datasets, error_name): - results_str = [] - all = [] - error = qp.error.from_name(error_name) - for method, dataset in itertools.product(methods, datasets): - for experiment in glob(f'{resultdir}/{dataset}-{method}-{error_name}.pkl'): - true_prevalences, estim_prevalences, tr_prev, te_prev, te_prev_estim, best_params = \ - pickle.load(open(experiment, 'rb')) - result = error(true_prevalences, estim_prevalences) - string = f'{pathlib.Path(experiment).name}: {result:.3f}' - results_str.append(string) - all.append(result) - results_str = sorted(results_str) - for r in results_str: - print(r) - print() - print(f'Ave: {np.mean(all):.3f}') - - -evaluate_results(methods=['epacc*mae1k'], datasets=['*'], error_name='mae') diff --git a/TweetSentQuant/experiments.py b/TweetSentQuant/experiments.py deleted file mode 100644 index 3f3c2d7..0000000 --- a/TweetSentQuant/experiments.py +++ /dev/null @@ -1,214 +0,0 @@ -from sklearn.linear_model import LogisticRegression -import quapy as qp -from classification.methods import PCALR -from method.meta import QuaNet -from method.non_aggregative import MaximumLikelihoodPrevalenceEstimation -from quapy.method.aggregative import CC, ACC, PCC, PACC, EMQ, OneVsAll, SVMQ, SVMKLD, SVMNKLD, SVMAE, SVMRAE, HDy -from quapy.method.meta import EPACC, EEMQ -import quapy.functional as F -import numpy as np -import os -import pickle -import itertools -from joblib import Parallel, delayed -import settings -import argparse -import torch -import shutil - - -qp.environ['SAMPLE_SIZE'] = settings.SAMPLE_SIZE - -def newLR(): - return LogisticRegression(max_iter=1000, solver='lbfgs', n_jobs=-1) - -__C_range = np.logspace(-4, 5, 10) -lr_params = {'C': __C_range, 'class_weight': [None, 'balanced']} -svmperf_params = {'C': __C_range} - -def quantification_models(): - # methods tested in Gao & Sebastiani 2016 - yield 'cc', CC(newLR()), lr_params - yield 'acc', ACC(newLR()), lr_params - yield 'pcc', PCC(newLR()), lr_params - yield 'pacc', PACC(newLR()), lr_params - yield 'sld', EMQ(newLR()), lr_params - yield 'svmq', OneVsAll(SVMQ(args.svmperfpath)), svmperf_params - yield 'svmkld', OneVsAll(SVMKLD(args.svmperfpath)), svmperf_params - yield 'svmnkld', OneVsAll(SVMNKLD(args.svmperfpath)), svmperf_params - - # methods added - yield 'svmmae', OneVsAll(SVMAE(args.svmperfpath)), svmperf_params - yield 'svmmrae', OneVsAll(SVMRAE(args.svmperfpath)), svmperf_params - yield 'hdy', OneVsAll(HDy(newLR())), lr_params - - -def quantification_cuda_models(): - device = 'cuda' if torch.cuda.is_available() else 'cpu' - print(f'Running QuaNet in {device}') - learner = PCALR(**newLR().get_params()) - yield 'quanet', QuaNet(learner, settings.SAMPLE_SIZE, checkpointdir=args.checkpointdir, device=device), lr_params - - -def quantification_ensembles(): - param_mod_sel = { - 'sample_size': settings.SAMPLE_SIZE, - 'n_prevpoints': 21, - 'n_repetitions': 5, - 'verbose': False - } - common={ - 'max_sample_size': 1000, - 'n_jobs': settings.ENSEMBLE_N_JOBS, - 'param_grid': lr_params, - 'param_mod_sel': param_mod_sel, - 'val_split': 0.4, - 'min_pos': 10 - } - - # hyperparameters will be evaluated within each quantifier of the ensemble, and so the typical model selection - # will be skipped (by setting hyperparameters to None) - hyper_none = None - #yield 'epaccmaeptr', EPACC(newLR(), optim='mae', policy='ptr', **common), hyper_none - yield 'epaccmaemae1k', EPACC(newLR(), optim='mae', policy='mae', **common), hyper_none - # yield 'esldmaeptr', EEMQ(newLR(), optim='mae', policy='ptr', **common), hyper_none - # yield 'esldmaemae', EEMQ(newLR(), optim='mae', policy='mae', **common), hyper_none - - #yield 'epaccmraeptr', EPACC(newLR(), optim='mrae', policy='ptr', **common), hyper_none - #yield 'epaccmraemrae', EPACC(newLR(), optim='mrae', policy='mrae', **common), hyper_none - #yield 'esldmraeptr', EEMQ(newLR(), optim='mrae', policy='ptr', **common), hyper_none - #yield 'esldmraemrae', EEMQ(newLR(), optim='mrae', policy='mrae', **common), hyper_none - - -def evaluate_experiment(true_prevalences, estim_prevalences): - print('\nEvaluation Metrics:\n'+'='*22) - for eval_measure in [qp.error.mae, qp.error.mrae]: - err = eval_measure(true_prevalences, estim_prevalences) - print(f'\t{eval_measure.__name__}={err:.4f}') - print() - - -def evaluate_method_point_test(true_prev, estim_prev): - print('\nPoint-Test evaluation:\n' + '=' * 22) - print(f'true-prev={F.strprev(true_prev)}, estim-prev={F.strprev(estim_prev)}') - for eval_measure in [qp.error.mae, qp.error.mrae]: - err = eval_measure(true_prev, estim_prev) - print(f'\t{eval_measure.__name__}={err:.4f}') - - -def result_path(path, dataset_name, model_name, optim_loss): - return os.path.join(path, f'{dataset_name}-{model_name}-{optim_loss}.pkl') - - -def is_already_computed(dataset_name, model_name, optim_loss): - if dataset_name=='semeval': - check_datasets = ['semeval13', 'semeval14', 'semeval15'] - else: - check_datasets = [dataset_name] - return all(os.path.exists(result_path(args.results, name, model_name, optim_loss)) for name in check_datasets) - - -def save_results(dataset_name, model_name, optim_loss, *results): - rpath = result_path(args.results, dataset_name, model_name, optim_loss) - qp.util.create_parent_dir(rpath) - with open(rpath, 'wb') as foo: - pickle.dump(tuple(results), foo, pickle.HIGHEST_PROTOCOL) - - -def run(experiment): - - optim_loss, dataset_name, (model_name, model, hyperparams) = experiment - - if is_already_computed(dataset_name, model_name, optim_loss=optim_loss): - print(f'result for dataset={dataset_name} model={model_name} loss={optim_loss} already computed.') - return - elif (optim_loss == 'mae' and 'mrae' in model_name) or (optim_loss=='mrae' and 'mae' in model_name): - print(f'skipping model={model_name} for optim_loss={optim_loss}') - return - else: - print(f'running dataset={dataset_name} model={model_name} loss={optim_loss}') - - benchmark_devel = qp.datasets.fetch_twitter(dataset_name, for_model_selection=True, min_df=5, pickle=True) - benchmark_devel.stats() - - # model selection (hyperparameter optimization for a quantification-oriented loss) - if hyperparams is not None: - model_selection = qp.model_selection.GridSearchQ( - model, - param_grid=hyperparams, - sample_size=settings.SAMPLE_SIZE, - n_prevpoints=21, - n_repetitions=5, - error=optim_loss, - refit=False, - timeout=60*60, - verbose=True - ) - model_selection.fit(benchmark_devel.training, benchmark_devel.test) - model = model_selection.best_model() - best_params = model_selection.best_params_ - else: - best_params = {} - - # model evaluation - test_names = [dataset_name] if dataset_name != 'semeval' else ['semeval13', 'semeval14', 'semeval15'] - for test_no, test_name in enumerate(test_names): - benchmark_eval = qp.datasets.fetch_twitter(test_name, for_model_selection=False, min_df=5, pickle=True) - if test_no == 0: - print('fitting the selected model') - # fits the model only the first time - model.fit(benchmark_eval.training) - - true_prevalences, estim_prevalences = qp.evaluation.artificial_sampling_prediction( - model, - test=benchmark_eval.test, - sample_size=settings.SAMPLE_SIZE, - n_prevpoints=21, - n_repetitions=25, - n_jobs=-1 if isinstance(model, qp.method.meta.Ensemble) else 1 - ) - test_estim_prevalence = model.quantify(benchmark_eval.test.instances) - test_true_prevalence = benchmark_eval.test.prevalence() - - evaluate_experiment(true_prevalences, estim_prevalences) - evaluate_method_point_test(test_true_prevalence, test_estim_prevalence) - save_results(test_name, model_name, optim_loss, - true_prevalences, estim_prevalences, - benchmark_eval.training.prevalence(), test_true_prevalence, test_estim_prevalence, - best_params) - - #if isinstance(model, QuaNet): - #model.clean_checkpoint_dir() - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Run experiments for Tweeter Sentiment Quantification') - parser.add_argument('results', metavar='RESULT_PATH', type=str, - help='path to the directory where to store the results') - parser.add_argument('--svmperfpath', metavar='SVMPERF_PATH', type=str, default='./svm_perf_quantification', - help='path to the directory with svmperf') - parser.add_argument('--checkpointdir', metavar='PATH', type=str, default='./checkpoint', - help='path to the directory where to dump QuaNet checkpoints') - args = parser.parse_args() - - print(f'Result folder: {args.results}') - np.random.seed(0) - - optim_losses = ['mae', 'mrae'] - datasets = qp.datasets.TWITTER_SENTIMENT_DATASETS_TRAIN - - models = quantification_models() - qp.util.parallel(run, itertools.product(optim_losses, datasets, models), n_jobs=settings.N_JOBS) - - models = quantification_cuda_models() - qp.util.parallel(run, itertools.product(optim_losses, datasets, models), n_jobs=settings.CUDA_N_JOBS) - - models = quantification_ensembles() - qp.util.parallel(run, itertools.product(optim_losses, datasets, models), n_jobs=1) - # Parallel(n_jobs=1)( - # delayed(run)(experiment) for experiment in itertools.product(optim_losses, datasets, models) - # ) - - #shutil.rmtree(args.checkpointdir, ignore_errors=True) - - diff --git a/TweetSentQuant/gen_plots.py b/TweetSentQuant/gen_plots.py deleted file mode 100644 index 4952999..0000000 --- a/TweetSentQuant/gen_plots.py +++ /dev/null @@ -1,95 +0,0 @@ -import quapy as qp -import settings -import os -import pathlib -import pickle -from glob import glob -import sys -from TweetSentQuant.util import nicename -from os.path import join - - -qp.environ['SAMPLE_SIZE'] = settings.SAMPLE_SIZE -plotext='png' - -resultdir = './results' -plotdir = './plots' -os.makedirs(plotdir, exist_ok=True) - -def gather_results(methods, error_name): - method_names, true_prevs, estim_prevs, tr_prevs = [], [], [], [] - for method in methods: - for experiment in glob(f'{resultdir}/*-{method}-m{error_name}.pkl'): - true_prevalences, estim_prevalences, tr_prev, te_prev, te_prev_estim, best_params = pickle.load(open(experiment, 'rb')) - method_names.append(nicename(method)) - true_prevs.append(true_prevalences) - estim_prevs.append(estim_prevalences) - tr_prevs.append(tr_prev) - return method_names, true_prevs, estim_prevs, tr_prevs - - -def plot_error_by_drift(methods, error_name, logscale=False, path=None): - print('plotting error by drift') - if path is not None: - path = join(path, f'error_by_drift_{error_name}.{plotext}') - method_names, true_prevs, estim_prevs, tr_prevs = gather_results(methods, error_name) - qp.plot.error_by_drift( - method_names, - true_prevs, - estim_prevs, - tr_prevs, - n_bins=20, - error_name=error_name, - show_std=False, - logscale=logscale, - title=f'Quantification error as a function of distribution shift', - savepath=path - ) - - -def diagonal_plot(methods, error_name, path=None): - print('plotting diagonal plots') - if path is not None: - path = join(path, f'diag_{error_name}') - method_names, true_prevs, estim_prevs, tr_prevs = gather_results(methods, error_name) - qp.plot.binary_diagonal(method_names, true_prevs, estim_prevs, pos_class=0, title='Negative', legend=False, show_std=False, savepath=f'{path}_neg.{plotext}') - qp.plot.binary_diagonal(method_names, true_prevs, estim_prevs, pos_class=1, title='Neutral', legend=False, show_std=False, savepath=f'{path}_neu.{plotext}') - qp.plot.binary_diagonal(method_names, true_prevs, estim_prevs, pos_class=2, title='Positive', legend=True, show_std=False, savepath=f'{path}_pos.{plotext}') - - -def binary_bias_global(methods, error_name, path=None): - print('plotting bias global') - if path is not None: - path = join(path, f'globalbias_{error_name}') - method_names, true_prevs, estim_prevs, tr_prevs = gather_results(methods, error_name) - qp.plot.binary_bias_global(method_names, true_prevs, estim_prevs, pos_class=0, title='Negative', savepath=f'{path}_neg.{plotext}') - qp.plot.binary_bias_global(method_names, true_prevs, estim_prevs, pos_class=1, title='Neutral', savepath=f'{path}_neu.{plotext}') - qp.plot.binary_bias_global(method_names, true_prevs, estim_prevs, pos_class=2, title='Positive', savepath=f'{path}_pos.{plotext}') - - -def binary_bias_bins(methods, error_name, path=None): - print('plotting bias local') - if path is not None: - path = join(path, f'localbias_{error_name}') - method_names, true_prevs, estim_prevs, tr_prevs = gather_results(methods, error_name) - qp.plot.binary_bias_bins(method_names, true_prevs, estim_prevs, pos_class=0, title='Negative', legend=False, savepath=f'{path}_neg.{plotext}') - qp.plot.binary_bias_bins(method_names, true_prevs, estim_prevs, pos_class=1, title='Neutral', legend=False, savepath=f'{path}_neu.{plotext}') - qp.plot.binary_bias_bins(method_names, true_prevs, estim_prevs, pos_class=2, title='Positive', legend=True, savepath=f'{path}_pos.{plotext}') - - -gao_seb_methods = ['cc', 'acc', 'pcc', 'pacc', 'sld', 'svmq', 'svmkld', 'svmnkld'] -new_methods_ae = ['svmmae' , 'epaccmaeptr', 'epaccmaemae', 'hdy', 'quanet'] -new_methods_rae = ['svmmrae' , 'epaccmraeptr', 'epaccmraemrae', 'hdy', 'quanet'] - -plot_error_by_drift(gao_seb_methods+new_methods_ae, error_name='ae', path=plotdir) -plot_error_by_drift(gao_seb_methods+new_methods_rae, error_name='rae', logscale=True, path=plotdir) - -diagonal_plot(gao_seb_methods+new_methods_ae, error_name='ae', path=plotdir) -diagonal_plot(gao_seb_methods+new_methods_rae, error_name='rae', path=plotdir) - -binary_bias_global(gao_seb_methods+new_methods_ae, error_name='ae', path=plotdir) -binary_bias_global(gao_seb_methods+new_methods_rae, error_name='rae', path=plotdir) - -#binary_bias_bins(gao_seb_methods+new_methods_ae, error_name='ae', path=plotdir) -#binary_bias_bins(gao_seb_methods+new_methods_rae, error_name='rae', path=plotdir) - diff --git a/TweetSentQuant/gen_tables.py b/TweetSentQuant/gen_tables.py deleted file mode 100644 index 585c453..0000000 --- a/TweetSentQuant/gen_tables.py +++ /dev/null @@ -1,145 +0,0 @@ -import quapy as qp -import numpy as np -from os import makedirs -import sys, os -import pickle -import argparse -from TweetSentQuant.util import nicename, get_ranks_from_Gao_Sebastiani -import settings -from experiments import result_path -from tabular import Table - -tables_path = './tables' -MAXTONE = 50 # sets the intensity of the maximum color reached by the worst (red) and best (green) results - -makedirs(tables_path, exist_ok=True) - -qp.environ['SAMPLE_SIZE'] = settings.SAMPLE_SIZE - - -def save_table(path, table): - print(f'saving results in {path}') - with open(path, 'wt') as foo: - foo.write(table) - - -def experiment_errors(path, dataset, method, loss): - path = result_path(path, dataset, method, 'm'+loss if not loss.startswith('m') else loss) - if os.path.exists(path): - true_prevs, estim_prevs, _, _, _, _ = pickle.load(open(path, 'rb')) - err_fn = getattr(qp.error, loss) - errors = err_fn(true_prevs, estim_prevs) - return errors - return None - - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Generate tables for Tweeter Sentiment Quantification') - parser.add_argument('results', metavar='RESULT_PATH', type=str, - help='path to the directory where to store the results') - args = parser.parse_args() - - datasets = qp.datasets.TWITTER_SENTIMENT_DATASETS_TEST - evaluation_measures = [qp.error.ae, qp.error.rae] - gao_seb_methods = ['cc', 'acc', 'pcc', 'pacc', 'sld', 'svmq', 'svmkld', 'svmnkld'] - new_methods = ['hdy', 'quanet'] - - gao_seb_ranks, gao_seb_results = get_ranks_from_Gao_Sebastiani() - - for i, eval_func in enumerate(evaluation_measures): - - # Tables evaluation scores for AE and RAE (two tables) - # ---------------------------------------------------- - - eval_name = eval_func.__name__ - added_methods = ['svmm' + eval_name, f'epaccm{eval_name}ptr', f'epaccm{eval_name}m{eval_name}'] + new_methods - methods = gao_seb_methods + added_methods - nold_methods = len(gao_seb_methods) - nnew_methods = len(added_methods) - - # fill data table - table = Table(benchmarks=datasets, methods=methods) - for dataset in datasets: - for method in methods: - table.add(dataset, method, experiment_errors(args.results, dataset, method, eval_name)) - - # write the latex table - # tabular = """ - # \\begin{tabularx}{\\textwidth}{|c||""" + ('Y|'*nold_methods)+ '|' + ('Y|'*nnew_methods) + """} \hline - # & \multicolumn{"""+str(nold_methods)+"""}{c||}{Methods tested in~\cite{Gao:2016uq}} & - # \multicolumn{"""+str(nnew_methods)+"""}{c|}{} \\\\ \hline - # """ - tabular = """ - \\resizebox{\\textwidth}{!}{% - \\begin{tabular}{|c||""" + ('c|' * nold_methods) + '|' + ('c|' * nnew_methods) + """} \hline - & \multicolumn{""" + str(nold_methods) + """}{c||}{Methods tested in~\cite{Gao:2016uq}} & - \multicolumn{""" + str(nnew_methods) + """}{c|}{} \\\\ \hline - """ - rowreplace={dataset: nicename(dataset) for dataset in datasets} - colreplace={method: nicename(method, eval_name, side=True) for method in methods} - - tabular += table.latexTabular(benchmark_replace=rowreplace, method_replace=colreplace) - tabular += """ - \end{tabular}% - } - """ - - save_table(f'./tables/tab_results_{eval_name}.new.tex', tabular) - - # Tables ranks for AE and RAE (two tables) - # ---------------------------------------------------- - methods = gao_seb_methods - - table.dropMethods(added_methods) - - # fill the data table - ranktable = Table(benchmarks=datasets, methods=methods, missing='--') - for dataset in datasets: - for method in methods: - ranktable.add(dataset, method, values=table.get(dataset, method, 'rank')) - - # write the latex table - tabular = """ - \\resizebox{\\textwidth}{!}{% - \\begin{tabular}{|c||""" + ('c|' * len(gao_seb_methods)) + """} \hline - & \multicolumn{""" + str(nold_methods) + """}{c|}{Methods tested in~\cite{Gao:2016uq}} \\\\ \hline - """ - for method in methods: - tabular += ' & ' + nicename(method, eval_name, side=True) - tabular += "\\\\\hline\n" - - for dataset in datasets: - tabular += nicename(dataset) + ' ' - for method in methods: - newrank = ranktable.get(dataset, method) - oldrank = gao_seb_ranks[f'{dataset}-{method}-{eval_name}'] - if newrank != '--': - newrank = f'{int(newrank)}' - color = ranktable.get_color(dataset, method) - if color == '--': - color = '' - tabular += ' & ' + f'{newrank}' + f' ({oldrank}) ' + color - tabular += '\\\\\hline\n' - tabular += '\hline\n' - - tabular += 'Average ' - for method in methods: - newrank = ranktable.get_average(method) - oldrank = gao_seb_ranks[f'Average-{method}-{eval_name}'] - if newrank != '--': - newrank = f'{newrank:.1f}' - oldrank = f'{oldrank:.1f}' - color = ranktable.get_average(method, 'color') - if color == '--': - color = '' - tabular += ' & ' + f'{newrank}' + f' ({oldrank}) ' + color - tabular += '\\\\\hline\n' - tabular += """ - \end{tabular}% - } - """ - - save_table(f'./tables/tab_rank_{eval_name}.new.tex', tabular) - - print("[Done]") diff --git a/TweetSentQuant/settings.py b/TweetSentQuant/settings.py deleted file mode 100644 index 8064fa8..0000000 --- a/TweetSentQuant/settings.py +++ /dev/null @@ -1,8 +0,0 @@ -import multiprocessing - -N_JOBS = -2 #multiprocessing.cpu_count() -CUDA_N_JOBS = 2 -ENSEMBLE_N_JOBS = -2 - -SAMPLE_SIZE = 100 - diff --git a/TweetSentQuant/tabular.py b/TweetSentQuant/tabular.py deleted file mode 100644 index cb90f3f..0000000 --- a/TweetSentQuant/tabular.py +++ /dev/null @@ -1,318 +0,0 @@ -import numpy as np -import itertools -from scipy.stats import ttest_ind_from_stats, wilcoxon - - -class Table: - VALID_TESTS = [None, "wilcoxon", "ttest"] - - def __init__(self, benchmarks, methods, lower_is_better=True, ttest='ttest', prec_mean=3, - clean_zero=False, show_std=False, prec_std=3, average=True, missing=None, missing_str='--', color=True): - assert ttest in self.VALID_TESTS, f'unknown test, valid are {self.VALID_TESTS}' - - self.benchmarks = np.asarray(benchmarks) - self.benchmark_index = {row:i for i, row in enumerate(benchmarks)} - - self.methods = np.asarray(methods) - self.method_index = {col:j for j, col in enumerate(methods)} - - self.map = {} - # keyed (#rows,#cols)-ndarrays holding computations from self.map['values'] - self._addmap('values', dtype=object) - self.lower_is_better = lower_is_better - self.ttest = ttest - self.prec_mean = prec_mean - self.clean_zero = clean_zero - self.show_std = show_std - self.prec_std = prec_std - self.add_average = average - self.missing = missing - self.missing_str = missing_str - self.color = color - - self.touch() - - @property - def nbenchmarks(self): - return len(self.benchmarks) - - @property - def nmethods(self): - return len(self.methods) - - def touch(self): - self._modif = True - - def update(self): - if self._modif: - self.compute() - - def _getfilled(self): - return np.argwhere(self.map['fill']) - - @property - def values(self): - return self.map['values'] - - def _indexes(self): - return itertools.product(range(self.nbenchmarks), range(self.nmethods)) - - def _addmap(self, map, dtype, func=None): - self.map[map] = np.empty((self.nbenchmarks, self.nmethods), dtype=dtype) - if func is None: - return - m = self.map[map] - f = func - indexes = self._indexes() if map == 'fill' else self._getfilled() - for i, j in indexes: - m[i, j] = f(self.values[i, j]) - - def _addrank(self): - for i in range(self.nbenchmarks): - filled_cols_idx = np.argwhere(self.map['fill'][i]).flatten() - col_means = [self.map['mean'][i,j] for j in filled_cols_idx] - ranked_cols_idx = filled_cols_idx[np.argsort(col_means)] - if not self.lower_is_better: - ranked_cols_idx = ranked_cols_idx[::-1] - self.map['rank'][i, ranked_cols_idx] = np.arange(1, len(filled_cols_idx)+1) - - def _addcolor(self): - for i in range(self.nbenchmarks): - filled_cols_idx = np.argwhere(self.map['fill'][i]).flatten() - if filled_cols_idx.size==0: - continue - col_means = [self.map['mean'][i,j] for j in filled_cols_idx] - minval = min(col_means) - maxval = max(col_means) - for col_idx in filled_cols_idx: - val = self.map['mean'][i,col_idx] - norm = (maxval - minval) - if norm > 0: - normval = (val - minval) / norm - else: - normval = 0.5 - if self.lower_is_better: - normval = 1 - normval - self.map['color'][i, col_idx] = color_red2green_01(normval) - - def _run_ttest(self, row, col1, col2): - mean1 = self.map['mean'][row, col1] - std1 = self.map['std'][row, col1] - nobs1 = self.map['nobs'][row, col1] - mean2 = self.map['mean'][row, col2] - std2 = self.map['std'][row, col2] - nobs2 = self.map['nobs'][row, col2] - _, p_val = ttest_ind_from_stats(mean1, std1, nobs1, mean2, std2, nobs2) - return p_val - - def _run_wilcoxon(self, row, col1, col2): - values1 = self.map['values'][row, col1] - values2 = self.map['values'][row, col2] - _, p_val = wilcoxon(values1, values2) - return p_val - - def _add_statistical_test(self): - if self.ttest is None: - return - self.some_similar = [False]*self.nmethods - for i in range(self.nbenchmarks): - filled_cols_idx = np.argwhere(self.map['fill'][i]).flatten() - if len(filled_cols_idx) <= 1: - continue - col_means = [self.map['mean'][i,j] for j in filled_cols_idx] - best_pos = filled_cols_idx[np.argmin(col_means)] - - for j in filled_cols_idx: - if j==best_pos: - continue - if self.ttest == 'ttest': - p_val = self._run_ttest(i, best_pos, j) - else: - p_val = self._run_wilcoxon(i, best_pos, j) - - pval_outcome = pval_interpretation(p_val) - self.map['ttest'][i, j] = pval_outcome - if pval_outcome != 'Diff': - self.some_similar[j] = True - - def compute(self): - self._addmap('fill', dtype=bool, func=lambda x: x is not None) - self._addmap('mean', dtype=float, func=np.mean) - self._addmap('std', dtype=float, func=np.std) - self._addmap('nobs', dtype=float, func=len) - self._addmap('rank', dtype=int, func=None) - self._addmap('color', dtype=object, func=None) - self._addmap('ttest', dtype=object, func=None) - self._addmap('latex', dtype=object, func=None) - self._addrank() - self._addcolor() - self._add_statistical_test() - if self.add_average: - self._addave() - self._modif = False - - def _is_column_full(self, col): - return all(self.map['fill'][:, self.method_index[col]]) - - def _addave(self): - ave = Table(['ave'], self.methods, lower_is_better=self.lower_is_better, ttest=self.ttest, average=False, - missing=self.missing, missing_str=self.missing_str) - for col in self.methods: - values = None - if self._is_column_full(col): - if self.ttest == 'ttest': - values = np.asarray(self.map['mean'][:, self.method_index[col]]) - else: # wilcoxon - values = np.concatenate(self.values[:, self.method_index[col]]) - ave.add('ave', col, values) - self.average = ave - - def add(self, benchmark, method, values): - if values is not None: - values = np.asarray(values) - if values.ndim==0: - values = values.flatten() - rid, cid = self._coordinates(benchmark, method) - self.map['values'][rid, cid] = values - self.touch() - - def get(self, benchmark, method, attr='mean'): - self.update() - assert attr in self.map, f'unknwon attribute {attr}' - rid, cid = self._coordinates(benchmark, method) - if self.map['fill'][rid, cid]: - v = self.map[attr][rid, cid] - if v is None or (isinstance(v,float) and np.isnan(v)): - return self.missing - return v - else: - return self.missing - - def _coordinates(self, benchmark, method): - assert benchmark in self.benchmark_index, f'benchmark {benchmark} out of range' - assert method in self.method_index, f'method {method} out of range' - rid = self.benchmark_index[benchmark] - cid = self.method_index[method] - return rid, cid - - def get_average(self, method, attr='mean'): - self.update() - if self.add_average: - return self.average.get('ave', method, attr=attr) - return None - - def get_color(self, benchmark, method): - color = self.get(benchmark, method, attr='color') - if color is None: - return '' - return color - - def latex(self, benchmark, method): - self.update() - i,j = self._coordinates(benchmark, method) - if self.map['fill'][i,j] == False: - return self.missing_str - - mean = self.map['mean'][i,j] - l = f" {mean:.{self.prec_mean}f}" - if self.clean_zero: - l = l.replace(' 0.', '.') - - isbest = self.map['rank'][i,j] == 1 - if isbest: - l = "\\textbf{"+l.strip()+"}" - - stat = '' - if self.ttest is not None and self.some_similar[j]: - test_label = self.map['ttest'][i,j] - if test_label == 'Sim': - stat = '^{\dag\phantom{\dag}}' - elif test_label == 'Same': - stat = '^{\ddag}' - elif isbest or test_label == 'Diff': - stat = '^{\phantom{\ddag}}' - - std = '' - if self.show_std: - std = self.map['std'][i,j] - std = f" {std:.{self.prec_std}f}" - if self.clean_zero: - std = std.replace(' 0.', '.') - std = f" \pm {std:{self.prec_std}}" - - if stat!='' or std!='': - l = f'{l}${stat}{std}$' - - if self.color: - l += ' ' + self.map['color'][i,j] - - return l - - def latexTabular(self, benchmark_replace={}, method_replace={}, average=True): - tab = ' & ' - tab += ' & '.join([method_replace.get(col, col) for col in self.methods]) - tab += ' \\\\\hline\n' - for row in self.benchmarks: - rowname = benchmark_replace.get(row, row) - tab += rowname + ' & ' - tab += self.latexRow(row) - - if average: - tab += '\hline\n' - tab += 'Average & ' - tab += self.latexAverage() - return tab - - def latexRow(self, benchmark, endl='\\\\\hline\n'): - s = [self.latex(benchmark, col) for col in self.methods] - s = ' & '.join(s) - s += ' ' + endl - return s - - def latexAverage(self, endl='\\\\\hline\n'): - if self.add_average: - return self.average.latexRow('ave', endl=endl) - - def getRankTable(self): - t = Table(benchmarks=self.benchmarks, methods=self.methods, prec_mean=0, average=True) - for rid, cid in self._getfilled(): - row = self.benchmarks[rid] - col = self.methods[cid] - t.add(row, col, self.get(row, col, 'rank')) - t.compute() - return t - - def dropMethods(self, methods): - drop_index = [self.method_index[m] for m in methods] - new_methods = np.delete(self.methods, drop_index) - new_index = {col:j for j, col in enumerate(new_methods)} - - self.map['values'] = self.values[:,np.asarray([self.method_index[m] for m in new_methods], dtype=int)] - self.methods = new_methods - self.method_index = new_index - self.touch() - - -def pval_interpretation(p_val): - if 0.005 >= p_val: - return 'Diff' - elif 0.05 >= p_val > 0.005: - return 'Sim' - elif p_val > 0.05: - return 'Same' - - -def color_red2green_01(val, maxtone=50): - if np.isnan(val): return None - assert 0 <= val <= 1, f'val {val} out of range [0,1]' - - # rescale to [-1,1] - val = val * 2 - 1 - if val < 0: - color = 'red' - tone = maxtone * (-val) - else: - color = 'green' - tone = maxtone * val - return '\cellcolor{' + color + f'!{int(tone)}' + '}' - diff --git a/TweetSentQuant/util.py b/TweetSentQuant/util.py deleted file mode 100644 index fef866e..0000000 --- a/TweetSentQuant/util.py +++ /dev/null @@ -1,89 +0,0 @@ -import numpy as np - - -nice = { - 'mae':'AE', - 'mrae':'RAE', - 'ae':'AE', - 'rae':'RAE', - 'svmkld': 'SVM(KLD)', - 'svmnkld': 'SVM(NKLD)', - 'svmq': 'SVM(Q)', - 'svmae': 'SVM(AE)', - 'svmnae': 'SVM(NAE)', - 'svmmae': 'SVM(AE)', - 'svmmrae': 'SVM(RAE)', - 'quanet': 'QuaNet', - 'hdy': 'HDy', - 'dys': 'DyS', - 'epaccmaeptr': 'E(PACC)$_\mathrm{Ptr}$', - 'epaccmaemae': 'E(PACC)$_\mathrm{AE}$', - 'epaccmraeptr': 'E(PACC)$_\mathrm{Ptr}$', - 'epaccmraemrae': 'E(PACC)$_\mathrm{RAE}$', - 'svmperf':'', - 'sanders': 'Sanders', - 'semeval13': 'SemEval13', - 'semeval14': 'SemEval14', - 'semeval15': 'SemEval15', - 'semeval16': 'SemEval16', - 'Average': 'Average' -} - - -def nicerm(key): - return '\mathrm{'+nice[key]+'}' - - -def nicename(method, eval_name=None, side=False): - m = nice.get(method, method.upper()) - if eval_name is not None: - o = '$^{' + nicerm(eval_name) + '}$' - m = (m+o).replace('$$','') - if side: - m = '\side{'+m+'}' - return m - - -def load_Gao_Sebastiani_previous_results(): - def rename(method): - old2new = { - 'kld': 'svmkld', - 'nkld': 'svmnkld', - 'qbeta2': 'svmq', - 'em': 'sld' - } - return old2new.get(method, method) - - gao_seb_results = {} - with open('./Gao_Sebastiani_results.txt', 'rt') as fin: - lines = fin.readlines() - for line in lines[1:]: - line = line.strip() - parts = line.lower().split() - if len(parts) == 4: - dataset, method, ae, rae = parts - else: - method, ae, rae = parts - learner, method = method.split('-') - method = rename(method) - gao_seb_results[f'{dataset}-{method}-ae'] = float(ae) - gao_seb_results[f'{dataset}-{method}-rae'] = float(rae) - return gao_seb_results - - -def get_ranks_from_Gao_Sebastiani(): - gao_seb_results = load_Gao_Sebastiani_previous_results() - datasets = set([key.split('-')[0] for key in gao_seb_results.keys()]) - methods = np.sort(np.unique([key.split('-')[1] for key in gao_seb_results.keys()])) - ranks = {} - for metric in ['ae', 'rae']: - for dataset in datasets: - scores = [gao_seb_results[f'{dataset}-{method}-{metric}'] for method in methods] - order = np.argsort(scores) - sorted_methods = methods[order] - for i, method in enumerate(sorted_methods): - ranks[f'{dataset}-{method}-{metric}'] = i+1 - for method in methods: - rankave = np.mean([ranks[f'{dataset}-{method}-{metric}'] for dataset in datasets]) - ranks[f'Average-{method}-{metric}'] = rankave - return ranks, gao_seb_results From 9c926cc8a5a6b1e3bdc286b9077191301a237e0e Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Wed, 10 Mar 2021 11:42:00 +0100 Subject: [PATCH 03/10] cleaning master --- plot_example.py | 48 ----------- test.py | 222 ------------------------------------------------ 2 files changed, 270 deletions(-) delete mode 100644 plot_example.py delete mode 100644 test.py diff --git a/plot_example.py b/plot_example.py deleted file mode 100644 index 346455e..0000000 --- a/plot_example.py +++ /dev/null @@ -1,48 +0,0 @@ -from sklearn.model_selection import GridSearchCV -import numpy as np -import quapy as qp -from sklearn.linear_model import LogisticRegression - -sample_size = 500 -qp.environ['SAMPLE_SIZE'] = sample_size - - - -def gen_data(): - - data = qp.datasets.fetch_reviews('kindle', tfidf=True, min_df=5) - - models = [ - qp.method.aggregative.CC, - qp.method.aggregative.ACC, - qp.method.aggregative.PCC, - qp.method.aggregative.PACC, - qp.method.aggregative.HDy, - qp.method.aggregative.EMQ, - qp.method.meta.ECC, - qp.method.meta.EACC, - qp.method.meta.EHDy, - ] - - method_names, true_prevs, estim_prevs, tr_prevs = [], [], [], [] - for Quantifier in models: - print(f'training {Quantifier.__name__}') - lr = LogisticRegression(max_iter=1000, class_weight='balanced') - # lr = GridSearchCV(lr, param_grid={'C':np.logspace(-3,3,7)}, n_jobs=-1) - model = Quantifier(lr).fit(data.training) - true_prev, estim_prev = qp.evaluation.artificial_sampling_prediction( - model, data.test, sample_size, n_repetitions=20, n_prevpoints=11) - - method_names.append(Quantifier.__name__) - true_prevs.append(true_prev) - estim_prevs.append(estim_prev) - tr_prevs.append(data.training.prevalence()) - - return method_names, true_prevs, estim_prevs, tr_prevs - -method_names, true_prevs, estim_prevs, tr_prevs = qp.util.pickled_resource('./plots/plot_data.pkl', gen_data) - -qp.plot.error_by_drift(method_names, true_prevs, estim_prevs, tr_prevs, n_bins=11, savepath='./plots/err_drift.png') -qp.plot.binary_diagonal(method_names, true_prevs, estim_prevs, savepath='./plots/bin_diag.png') -qp.plot.binary_bias_global(method_names, true_prevs, estim_prevs, savepath='./plots/bin_bias.png') -qp.plot.binary_bias_bins(method_names, true_prevs, estim_prevs, nbins=11, savepath='./plots/bin_bias_bin.png') diff --git a/test.py b/test.py deleted file mode 100644 index 3d664b3..0000000 --- a/test.py +++ /dev/null @@ -1,222 +0,0 @@ -from sklearn.linear_model import LogisticRegression -from sklearn.model_selection import GridSearchCV -from sklearn.svm import LinearSVC, LinearSVR -import quapy as qp -import quapy.functional as F -import sys -import numpy as np - -from NewMethods.methods import AveragePoolQuantification -from classification.methods import PCALR -from data import Dataset -from method.meta import EPACC -from quapy.model_selection import GridSearchQ -from tqdm import tqdm -import pandas as pd - -sample_size=100 -qp.environ['SAMPLE_SIZE'] = sample_size - -np.random.seed(0) - -nfolds=5 -nrepeats=1 - -df = pd.DataFrame(columns=['dataset', 'method', 'mse']) -for datasetname in qp.datasets.UCI_DATASETS: - collection = qp.datasets.fetch_UCILabelledCollection(datasetname, verbose=False) - scores = [] - pbar = tqdm(Dataset.kFCV(collection, nfolds=nfolds, nrepeats=nrepeats), total=nfolds*nrepeats) - for data in pbar: - pbar.set_description(f'{data.name}') - # learner = GridSearchCV(LogisticRegression(class_weight='balanced'), param_grid={'C': np.logspace(-3,3,7)}, n_jobs=-1) - learner = LogisticRegression(class_weight='balanced') - # model = qp.method.aggregative.CC(learner) - model = qp.method.meta.EHDy(learner, size=30, red_size=15, verbose=False) - model.fit(data.training) - err = qp.evaluation.artificial_sampling_eval(model, data.test, sample_size, n_prevpoints=101, n_jobs=-1, - error_metric='mse', verbose=False) - scores.append(err) - - score = np.mean(scores) - df = df.append({ - 'dataset': datasetname, - 'method': model.__class__.__name__, - 'mse': score - }, ignore_index=True) - print(df) - -sys.exit(0) - - - -#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 = 500 - -sample_size = qp.environ['SAMPLE_SIZE'] -binary = False -svmperf_home = './svm_perf_quantification' - -if binary: - #dataset = qp.datasets.fetch_reviews('kindle', tfidf=True, min_df=5) - dataset = qp.datasets.fetch_UCIDataset('german', verbose=True) - #qp.data.preprocessing.index(dataset, inplace=True) - -else: - dataset = qp.datasets.fetch_twitter('gasp', for_model_selection=True, min_df=5, pickle=True) - #dataset.training = dataset.training.sampling(sample_size, 0.2, 0.5, 0.3) - -print(f'dataset loaded: #training={len(dataset.training)} #test={len(dataset.test)}') - - -# training a quantifier -# learner = LogisticRegression(max_iter=1000) -#model = qp.method.aggregative.ClassifyAndCount(learner) -# model = qp.method.aggregative.AdjustedClassifyAndCount(learner) -# model = qp.method.aggregative.ProbabilisticClassifyAndCount(learner) -# model = qp.method.aggregative.ProbabilisticAdjustedClassifyAndCount(learner) -# model = qp.method.aggregative.HellingerDistanceY(learner) -# model = qp.method.aggregative.ExpectationMaximizationQuantifier(learner) -# model = qp.method.aggregative.ExplicitLossMinimisationBinary(svmperf_home, loss='q', C=100) -# model = qp.method.aggregative.SVMQ(svmperf_home, C=1) - -#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) -# model = qp.method.aggregative.ClassifyAndCount(learner) - -param_mod_sel = { - 'sample_size': 100, - 'n_prevpoints': 21, - 'n_repetitions': 5, - 'verbose': False -} -common = { - 'max_sample_size': 50, - 'n_jobs': -1, - 'param_grid': {'C': np.logspace(0,2,2), 'class_weight': ['balanced']}, - 'param_mod_sel': param_mod_sel, - 'val_split': 0.4, - 'min_pos': 10, - 'size':6, - 'red_size':3 -} - -# hyperparameters will be evaluated within each quantifier of the ensemble, and so the typical model selection -# will be skipped (by setting hyperparameters to None) -model = EPACC(LogisticRegression(max_iter=100), optim='mrae', policy='mrae', **common) - -""" -Problemas: -- La interfaz es muy fea, hay que conocer practicamente todos los detalles así que no ahorra nada con respecto a crear - un objeto con otros anidados dentro -- El fit genera las prevalences random, y esto hace que despues de la model selection, un nuevo fit tire todo el trabajo - hecho. -- El fit de un GridSearcQ tiene dentro un best_estimator, pero después de la model selection, hacer fit otra vez sobre - este objeto no se limita a re-entrenar el modelo con los mejores parámetros, sino que inicia una nueva búsqueda - en modo grid search. -- Posible solución (no vale): sería hacer directamente model selection con el benchmark final, aunque esto haría que los hyper- - parámetros se buscasen en un conjunto diferente del resto de models.... -- Posible solución: - - Elegir las prevalences en init - - -- Problema: el parámetro val_split es muy ambiguo en todo el framework. Por ejemplo, en EPACC podría ser un float que, - en el caso de un GridSearchQ podría referir al split de validación para los hyperparámetros o al split que usa PACC - para encontrar los parámetros... -""" - -# regressor = LinearSVR(max_iter=10000) -# param_grid = {'C': np.logspace(-1,3,5)} -# model = AveragePoolQuantification(regressor, sample_size, trials=5000, n_components=500, zscore=False) - -# 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) - -# model = qp.method.meta.QuaNet(PCALR(n_components=100, max_iter=1000), -# sample_size=100, -# patience=10, -# tr_iter_per_poch=500, va_iter_per_poch=100, #lstm_nlayers=2, lstm_hidden_size=64, -# ff_layers=[500, 250, 50], - # checkpointdir='./checkpoint', device='cuda') - -if qp.isbinary(model) and not qp.isbinary(dataset): - model = qp.method.aggregative.OneVsAll(model) - - -# Model fit and Evaluation on the test data -# ---------------------------------------------------------------------------- - -print(f'fitting model {model.__class__.__name__}') -#train, val = dataset.training.split_stratified(0.6) -#model.fit(train, val_split=val) -qp.SAMPLE=1 -qp.environ['SAMPLE_SIZE']=2 -model.fit(dataset.training) - - - - - -# estimating class prevalences -# print('quantifying') -# 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}') - - -# Model fit and Evaluation according to the artificial sampling protocol -# ---------------------------------------------------------------------------- - -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) -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' - f'For the {dataset.n_classes} classes this dataset has, this will yield a total of {n_evaluations} evaluations.') - -true_prev, estim_prev = qp.evaluation.artificial_sampling_prediction(model, dataset.test, sample_size, n_prevpoints) - -#qp.error.SAMPLE_SIZE = sample_size -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}') - -sys.exit(0) -# Model selection and Evaluation according to the artificial sampling protocol -# ---------------------------------------------------------------------------- - -model_selection = GridSearchQ(model, - param_grid=param_grid, - sample_size=sample_size, - eval_budget=max_evaluations//10, - error='mae', - refit=True, - verbose=True, - timeout=60*60) - -model = model_selection.fit(dataset.training, val_split=0.3) -#model = model_selection.fit(train, validation=val) -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}') - -true_prev, estim_prev = qp.evaluation.artificial_sampling_prediction(model, dataset.test, sample_size, n_prevpoints) - -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}') \ No newline at end of file From a70a10429d21c58b0f11d9de22c99608287506fb Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Wed, 10 Mar 2021 11:59:08 +0100 Subject: [PATCH 04/10] testing ssh --- experiments.sh | 1 + 1 file changed, 1 insertion(+) create mode 100644 experiments.sh diff --git a/experiments.sh b/experiments.sh new file mode 100644 index 0000000..f22851a --- /dev/null +++ b/experiments.sh @@ -0,0 +1 @@ +PYTHONPATH=. python3 TweetSentQuant/experiments.py From 330b8a59f8ce4ee072c3882d1871e7cce78b6923 Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Wed, 10 Mar 2021 12:02:08 +0100 Subject: [PATCH 05/10] testing ssh --- experiments.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/experiments.sh b/experiments.sh index f22851a..303f198 100644 --- a/experiments.sh +++ b/experiments.sh @@ -1 +1,3 @@ PYTHONPATH=. python3 TweetSentQuant/experiments.py + + From ebf040f352437a1f7c6f5ef057bbf17ec0d234e3 Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Wed, 10 Mar 2021 13:17:47 +0100 Subject: [PATCH 06/10] cleaning --- experiments.sh | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 experiments.sh diff --git a/experiments.sh b/experiments.sh deleted file mode 100644 index 303f198..0000000 --- a/experiments.sh +++ /dev/null @@ -1,3 +0,0 @@ -PYTHONPATH=. python3 TweetSentQuant/experiments.py - - From 1aafd10e2558d19558531261ecd6bed2a965565e Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Wed, 10 Mar 2021 13:21:17 +0100 Subject: [PATCH 07/10] cleaning --- NewMethods/fgsld/__init__.py | 0 NewMethods/fgsld/em.py | 0 NewMethods/fgsld/fglsd_test.py | 0 NewMethods/fgsld/fine_grained_sld.py | 0 NewMethods/fgsld/metrics.py | 0 NewMethods/fgsld/plot_fglsd.png | 0 NewMethods/methods.py | 174 --------------------------- NewMethods/new_experiments.py | 48 -------- NewMethods/new_gen_tables.py | 148 ----------------------- NewMethods/settings.py | 4 - 10 files changed, 374 deletions(-) delete mode 100644 NewMethods/fgsld/__init__.py delete mode 100644 NewMethods/fgsld/em.py delete mode 100644 NewMethods/fgsld/fglsd_test.py delete mode 100644 NewMethods/fgsld/fine_grained_sld.py delete mode 100644 NewMethods/fgsld/metrics.py delete mode 100644 NewMethods/fgsld/plot_fglsd.png delete mode 100644 NewMethods/methods.py delete mode 100644 NewMethods/new_experiments.py delete mode 100644 NewMethods/new_gen_tables.py delete mode 100644 NewMethods/settings.py diff --git a/NewMethods/fgsld/__init__.py b/NewMethods/fgsld/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/NewMethods/fgsld/em.py b/NewMethods/fgsld/em.py deleted file mode 100644 index e69de29..0000000 diff --git a/NewMethods/fgsld/fglsd_test.py b/NewMethods/fgsld/fglsd_test.py deleted file mode 100644 index e69de29..0000000 diff --git a/NewMethods/fgsld/fine_grained_sld.py b/NewMethods/fgsld/fine_grained_sld.py deleted file mode 100644 index e69de29..0000000 diff --git a/NewMethods/fgsld/metrics.py b/NewMethods/fgsld/metrics.py deleted file mode 100644 index e69de29..0000000 diff --git a/NewMethods/fgsld/plot_fglsd.png b/NewMethods/fgsld/plot_fglsd.png deleted file mode 100644 index e69de29..0000000 diff --git a/NewMethods/methods.py b/NewMethods/methods.py deleted file mode 100644 index b47927d..0000000 --- a/NewMethods/methods.py +++ /dev/null @@ -1,174 +0,0 @@ -import numpy as np -from sklearn.base import BaseEstimator -from sklearn.decomposition import PCA -from sklearn.preprocessing import StandardScaler - -import quapy as qp -from typing import Union - -from quapy.data import LabelledCollection -from quapy.method.base import BaseQuantifier, BinaryQuantifier -from quapy.method.aggregative import PACC, EMQ, HDy -import quapy.functional as F -from tqdm import tqdm -from scipy.sparse import issparse, csr_matrix -import scipy - - -class PACCSLD(PACC): - """ - This method combines the EMQ improved posterior probabilities with PACC. - Note: the posterior probabilities are re-calibrated with EMQ only during prediction, and not also during fit since, - for PACC, the validation split is known to have the same prevalence as the training set (this is because the split - is stratified) and thus the posterior probabilities should not be re-calibrated for a different prior (it actually - happens to degrades performance). - """ - - def fit(self, data: qp.data.LabelledCollection, fit_learner=True, val_split:Union[float, int, qp.data.LabelledCollection]=0.4): - self.train_prevalence = F.prevalence_from_labels(data.labels, data.n_classes) - return super(PACCSLD, self).fit(data, fit_learner, val_split) - - def aggregate(self, classif_posteriors): - priors, posteriors = EMQ.EM(self.train_prevalence, classif_posteriors, epsilon=1e-4) - return super(PACCSLD, self).aggregate(posteriors) - - -class HDySLD(HDy): - """ - This method combines the EMQ improved posterior probabilities with HDy. - Note: [same as PACCSLD] - """ - def fit(self, data: qp.data.LabelledCollection, fit_learner=True, - val_split: Union[float, int, qp.data.LabelledCollection] = 0.4): - self.train_prevalence = F.prevalence_from_labels(data.labels, data.n_classes) - return super(HDySLD, self).fit(data, fit_learner, val_split) - - def aggregate(self, classif_posteriors): - priors, posteriors = EMQ.EM(self.train_prevalence, classif_posteriors, epsilon=1e-4) - return super(HDySLD, self).aggregate(posteriors) - - - -class AveragePoolQuantification(BinaryQuantifier): - def __init__(self, learner, sample_size, trials, n_components=-1, zscore=False): - self.learner = learner - self.sample_size = sample_size - self.trials = trials - - self.do_zscore = zscore - self.zscore = StandardScaler() if self.do_zscore else None - - self.do_pca = n_components>0 - self.pca = PCA(n_components) if self.do_pca else None - - def fit(self, data: LabelledCollection): - training, validation = data.split_stratified(train_prop=0.7) - - X, y = [], [] - - nprevpoints = F.get_nprevpoints_approximation(self.trials, data.n_classes) - for sample in tqdm( - training.artificial_sampling_generator(self.sample_size, n_prevalences=nprevpoints, repeats=1), - desc='generating averages' - ): - X.append(sample.instances.mean(axis=0)) - y.append(sample.prevalence()[1]) - while len(X) < self.trials: - sample = training.sampling(self.sample_size, F.uniform_simplex_sampling(data.n_classes)) - X.append(sample.instances.mean(axis=0)) - y.append(sample.prevalence()) - X = np.asarray(np.vstack(X)) - y = np.asarray(y) - - if self.do_pca: - X = self.pca.fit_transform(X) - print(X.shape) - - if self.do_zscore: - X = self.zscore.fit_transform(X) - - print('training regressor...') - self.regressor = self.learner.fit(X, y) - - # correction at 0: - print('getting corrections...') - X0 = np.asarray(np.vstack([validation.sampling(self.sample_size, 0., shuffle=False).instances.mean(axis=0) for _ in range(100)])) - X1 = np.asarray(np.vstack([validation.sampling(self.sample_size, 1., shuffle=False).instances.mean(axis=0) for _ in range(100)])) - - if self.do_pca: - X0 = self.pca.transform(X0) - X1 = self.pca.transform(X1) - - if self.do_zscore: - X0 = self.zscore.transform(X0) - X1 = self.zscore.transform(X1) - - self.correction_0 = self.regressor.predict(X0).mean() - self.correction_1 = self.regressor.predict(X1).mean() - - print('correction-0', self.correction_0) - print('correction-1', self.correction_1) - print('done') - - def quantify(self, instances): - ave = np.asarray(instances.mean(axis=0)) - - if self.do_pca: - ave = self.pca.transform(ave) - if self.do_zscore: - ave = self.zscore.transform(ave) - phat = self.regressor.predict(ave).item() - phat = np.clip((phat-self.correction_0)/(self.correction_1-self.correction_0), 0, 1) - return np.asarray([1-phat, phat]) - - def set_params(self, **parameters): - self.learner.set_params(**parameters) - - def get_params(self, deep=True): - return self.learner.get_params(deep=deep) - - -class WinnowOrthogonal(BaseEstimator): - - def __init__(self): - pass - - def fit(self, X, y): - self.classes_ = np.asarray(sorted(np.unique(y))) - w1 = np.asarray(X[y == 0].mean(axis=0)).flatten() - w2 = np.asarray(X[y == 1].mean(axis=0)).flatten() - diff = w2 - w1 - orth = np.ones_like(diff) - orth[0] = -diff[1:].sum() / diff[0] - orth /= np.linalg.norm(orth) - self.w = orth - self.b = w1.dot(orth) - return self - - def decision_function(self, X): - if issparse(X): - Z = X.dot(csr_matrix(self.w).T).toarray().flatten() - return Z - self.b - else: - return np.matmul(X, self.w) - self.b - - def predict(self, X): - return 1 * (self.decision_function(X) > 0) - - def split(self, X, y): - s = self.predict(X) - X0a = X[np.logical_and(y == 0, s == 0)] - X0b = X[np.logical_and(y == 0, s == 1)] - X1a = X[np.logical_and(y == 1, s == 0)] - X1b = X[np.logical_and(y == 1, s == 1)] - y0a = np.zeros(X0a.shape[0], dtype=np.int) - y0b = np.zeros(X0b.shape[0], dtype=np.int) - y1a = np.ones(X1a.shape[0], dtype=np.int) - y1b = np.ones(X1b.shape[0], dtype=np.int) - return X0a, X0b, X1a, X1b, y0a, y0b, y1a, y1b - - def get_params(self): - return {} - - def set_params(self, **params): - pass diff --git a/NewMethods/new_experiments.py b/NewMethods/new_experiments.py deleted file mode 100644 index d60b158..0000000 --- a/NewMethods/new_experiments.py +++ /dev/null @@ -1,48 +0,0 @@ -from sklearn.linear_model import LogisticRegression -import quapy as qp -from classification.methods import PCALR -from method.meta import QuaNet -from quapy.method.aggregative import * -from NewMethods.methods import * -from experiments import run, SAMPLE_SIZE -import numpy as np -import itertools -from joblib import Parallel, delayed -import settings -import argparse -import torch - -parser = argparse.ArgumentParser(description='Run experiments for Tweeter Sentiment Quantification') -parser.add_argument('results', metavar='RESULT_PATH', type=str, help='path to the directory where to store the results') -#parser.add_argument('svmperfpath', metavar='SVMPERF_PATH', type=str, help='path to the directory with svmperf') -args = parser.parse_args() - - -def quantification_models(): - def newLR(): - return LogisticRegression(max_iter=1000, solver='lbfgs', n_jobs=-1) - __C_range = np.logspace(-4, 5, 10) - lr_params = {'C': __C_range, 'class_weight': [None, 'balanced']} - svmperf_params = {'C': __C_range} - #yield 'paccsld', PACCSLD(newLR()), lr_params - yield 'hdysld', OneVsAll(HDySLD(newLR())), lr_params # <-- promising! - - #device = 'cuda' if torch.cuda.is_available() else 'cpu' - #print(f'Running QuaNet in {device}') - #yield 'quanet', QuaNet(PCALR(**newLR().get_params()), SAMPLE_SIZE, device=device), lr_params - - -if __name__ == '__main__': - - print(f'Result folder: {args.results}') - np.random.seed(0) - - optim_losses = ['mae'] - datasets = qp.datasets.TWITTER_SENTIMENT_DATASETS_TRAIN - models = quantification_models() - - results = Parallel(n_jobs=settings.N_JOBS)( - delayed(run)(experiment) for experiment in itertools.product(optim_losses, datasets, models) - ) - - diff --git a/NewMethods/new_gen_tables.py b/NewMethods/new_gen_tables.py deleted file mode 100644 index c6aeb7e..0000000 --- a/NewMethods/new_gen_tables.py +++ /dev/null @@ -1,148 +0,0 @@ -import quapy as qp -import numpy as np -from os import makedirs -import sys, os -import pickle -from experiments import result_path -from gen_tables import save_table, experiment_errors -from tabular import Table -import argparse - -tables_path = './tables' -MAXTONE = 50 # sets the intensity of the maximum color reached by the worst (red) and best (green) results - -makedirs(tables_path, exist_ok=True) - -sample_size = 100 -qp.environ['SAMPLE_SIZE'] = sample_size - - -nice = { - 'mae':'AE', - 'mrae':'RAE', - 'ae':'AE', - 'rae':'RAE', - 'svmkld': 'SVM(KLD)', - 'svmnkld': 'SVM(NKLD)', - 'svmq': 'SVM(Q)', - 'svmae': 'SVM(AE)', - 'svmnae': 'SVM(NAE)', - 'svmmae': 'SVM(AE)', - 'svmmrae': 'SVM(RAE)', - 'quanet': 'QuaNet', - 'hdy': 'HDy', - 'hdysld': 'HDy-SLD', - 'dys': 'DyS', - 'svmperf':'', - 'sanders': 'Sanders', - 'semeval13': 'SemEval13', - 'semeval14': 'SemEval14', - 'semeval15': 'SemEval15', - 'semeval16': 'SemEval16', - 'Average': 'Average' -} - - -def nicerm(key): - return '\mathrm{'+nice[key]+'}' - - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Generate tables for Tweeter Sentiment Quantification') - parser.add_argument('results', metavar='RESULT_PATH', type=str, - help='path to the directory containing the results of the methods tested in Gao & Sebastiani') - parser.add_argument('newresults', metavar='RESULT_PATH', type=str, - help='path to the directory containing the results for the experimental methods') - args = parser.parse_args() - - datasets = qp.datasets.TWITTER_SENTIMENT_DATASETS_TEST - evaluation_measures = [qp.error.ae, qp.error.rae] - gao_seb_methods = ['cc', 'acc', 'pcc', 'pacc', 'sld', 'svmq', 'svmkld', 'svmnkld'] - new_methods = ['hdy'] # methods added to the Gao & Sebastiani methods - experimental_methods = ['hdysld'] # experimental - - for i, eval_func in enumerate(evaluation_measures): - - # Tables evaluation scores for AE and RAE (two tables) - # ---------------------------------------------------- - - eval_name = eval_func.__name__ - - added_methods = ['svmm' + eval_name] + new_methods - methods = gao_seb_methods + added_methods + experimental_methods - nold_methods = len(gao_seb_methods) - nnew_methods = len(added_methods) - nexp_methods = len(experimental_methods) - - # fill data table - table = Table(benchmarks=datasets, methods=methods) - for dataset in datasets: - for method in methods: - if method in experimental_methods: - path = args.newresults - else: - path = args.results - table.add(dataset, method, experiment_errors(path, dataset, method, eval_name)) - - # write the latex table - tabular = """ - \\begin{tabularx}{\\textwidth}{|c||""" + ('Y|'*nold_methods) + '|' + ('Y|'*nnew_methods) + '|' + ('Y|'*nexp_methods) + """} \hline - & \multicolumn{"""+str(nold_methods)+"""}{c||}{Methods tested in~\cite{Gao:2016uq}} & - \multicolumn{"""+str(nnew_methods)+"""}{c|}{} & - \multicolumn{"""+str(nexp_methods)+"""}{c|}{}\\\\ \hline - """ - rowreplace={dataset: nice.get(dataset, dataset.upper()) for dataset in datasets} - colreplace={method:'\side{' + nice.get(method, method.upper()) +'$^{' + nicerm(eval_name) + '}$} ' for method in methods} - - tabular += table.latexTabular(benchmark_replace=rowreplace, method_replace=colreplace) - tabular += "\n\end{tabularx}" - - save_table(f'./tables/tab_results_{eval_name}.new.tex', tabular) - - # Tables ranks for AE and RAE (two tables) - # ---------------------------------------------------- - # fill the data table - ranktable = Table(benchmarks=datasets, methods=methods, missing='--') - for dataset in datasets: - for method in methods: - ranktable.add(dataset, method, values=table.get(dataset, method, 'rank')) - - # write the latex table - tabular = """ - \\begin{tabularx}{\\textwidth}{|c||""" + ('Y|'*nold_methods) + '|' + ('Y|'*nnew_methods) + '|' + ('Y|'*nexp_methods) + """} \hline - & \multicolumn{"""+str(nold_methods)+"""}{c||}{Methods tested in~\cite{Gao:2016uq}} & - \multicolumn{"""+str(nnew_methods)+"""}{c|}{} & - \multicolumn{"""+str(nexp_methods)+"""}{c|}{}\\\\ \hline - """ - for method in methods: - tabular += ' & \side{' + nice.get(method, method.upper()) +'$^{' + nicerm(eval_name) + '}$} ' - tabular += '\\\\\hline\n' - - for dataset in datasets: - tabular += nice.get(dataset, dataset.upper()) + ' ' - for method in methods: - newrank = ranktable.get(dataset, method) - if newrank != '--': - newrank = f'{int(newrank)}' - color = ranktable.get_color(dataset, method) - if color == '--': - color = '' - tabular += ' & ' + f'{newrank}' + color - tabular += '\\\\\hline\n' - tabular += '\hline\n' - - tabular += 'Average ' - for method in methods: - newrank = ranktable.get_average(method) - if newrank != '--': - newrank = f'{newrank:.1f}' - color = ranktable.get_average(method, 'color') - if color == '--': - color = '' - tabular += ' & ' + f'{newrank}' + color - tabular += '\\\\\hline\n' - tabular += "\end{tabularx}" - - save_table(f'./tables/tab_rank_{eval_name}.new.tex', tabular) - - print("[Done]") diff --git a/NewMethods/settings.py b/NewMethods/settings.py deleted file mode 100644 index 2ade31a..0000000 --- a/NewMethods/settings.py +++ /dev/null @@ -1,4 +0,0 @@ -import multiprocessing - -N_JOBS = -2 #multiprocessing.cpu_count() -SAMPLE_SIZE = 100 \ No newline at end of file From 3491ed7d72c4b6e88ddb8d461fb843ee78cc9d74 Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Thu, 11 Mar 2021 09:27:14 +0100 Subject: [PATCH 08/10] plot fix --- quapy/plot.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/quapy/plot.py b/quapy/plot.py index 0f5a0aa..ff93237 100644 --- a/quapy/plot.py +++ b/quapy/plot.py @@ -83,21 +83,21 @@ def binary_bias_bins(method_names, true_prevs, estim_prevs, pos_class=1, title=N binwidth = 1/nbins data = {} for method, true_prev, estim_prev in zip(method_names, true_prevs, estim_prevs): - true_prev = true_prev[:,pos_class] - estim_prev = estim_prev[:,pos_class] + true_prev = true_prev[:, pos_class] + estim_prev = estim_prev[:, pos_class] data[method] = [] - inds = np.digitize(true_prev, bins, right=True) + inds = np.digitize(true_prev, bins[1:], right=True) for ind in range(len(bins)): selected = inds==ind data[method].append(estim_prev[selected] - true_prev[selected]) nmethods = len(method_names) boxwidth = binwidth/(nmethods+4) - for i,bin in enumerate(bins[:-1]): + for i,bin in enumerate(bins): boxdata = [data[method][i] for method in method_names] positions = [bin+(i*boxwidth)+2*boxwidth for i,_ in enumerate(method_names)] - box = boxplot(boxdata, showmeans=False, positions=positions, widths = boxwidth, sym='+', patch_artist=True) + box = boxplot(boxdata, showmeans=False, positions=positions, widths=boxwidth, sym='+', patch_artist=True) for boxid in range(len(method_names)): c = colormap.colors[boxid%len(colormap.colors)] setp(box['fliers'][boxid], color=c, marker='+', markersize=3., markeredgecolor=c) @@ -110,7 +110,7 @@ def binary_bias_bins(method_names, true_prevs, estim_prevs, pos_class=1, title=N major_xticks_positions.append(b) minor_xticks_positions.append(b + binwidth / 2) major_xticks_labels.append('') - minor_xticks_labels.append(f'[{bins[i]:.2f}-{bins[i + 1]:.2f})') + minor_xticks_labels.append(f'[{bins[i]:.2f}-{bins[i + 1]:.2f}' + (')' if i < len(bins)-2 else ']')) ax.set_xticks(major_xticks_positions) ax.set_xticks(minor_xticks_positions, minor=True) ax.set_xticklabels(major_xticks_labels) From ca4c344c55bf9088a0ac39a70da816bebad40ad1 Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Fri, 19 Mar 2021 17:34:09 +0100 Subject: [PATCH 09/10] imports fix --- quapy/data/datasets.py | 2 +- quapy/model_selection.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/quapy/data/datasets.py b/quapy/data/datasets.py index 15a3921..79d0bbf 100644 --- a/quapy/data/datasets.py +++ b/quapy/data/datasets.py @@ -10,7 +10,7 @@ from sklearn.model_selection import StratifiedKFold import pandas as pd -from data.base import Dataset, LabelledCollection +from quapy.data.base import Dataset, LabelledCollection from quapy.data.preprocessing import text2tfidf, reduce_columns from quapy.data.reader import * from quapy.util import download_file_if_not_exists, download_file, get_quapy_home, pickled_resource diff --git a/quapy/model_selection.py b/quapy/model_selection.py index f3e9b18..feeb14d 100644 --- a/quapy/model_selection.py +++ b/quapy/model_selection.py @@ -5,7 +5,7 @@ from typing import Union, Callable import quapy as qp import quapy.functional as F -from data.base import LabelledCollection +from quapy.data.base import LabelledCollection from quapy.evaluation import artificial_sampling_prediction from quapy.method.aggregative import BaseQuantifier From 423fccb0964f07b326822582a07107e724e1ba2f Mon Sep 17 00:00:00 2001 From: Alex Moreo Date: Tue, 27 Apr 2021 18:47:25 +0200 Subject: [PATCH 10/10] todo update --- TODO.txt | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/TODO.txt b/TODO.txt index 5baa937..6ff9e9c 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,16 +1,55 @@ +Packaging: +========================================== Documentation with sphinx +Document methods with paper references +allow for "pip install" +unit-tests + +New features: +========================================== Add NAE, NRAE Add "measures for evaluating ordinal"? -Document methods with paper references +Add datasets for topic. +Do we want to cover cross-lingual quantification natively in QuaPy, or does it make more sense as an application on top? + +Current issues: +========================================== In binary quantification (hp, kindle, imdb) we used F1 in the minority class (which in kindle and hp happens to be the negative class). This is not covered in this new implementation, in which the binary case is not treated as such, but as an instance of single-label with 2 labels. Check -Add classnames to LabelledCollection ? +Add classnames to LabelledCollection? This should improve visualization of reports Add automatic reindex of class labels in LabelledCollection (currently, class indexes should be ordered and with no gaps) -Add datasets for topic. +OVR I believe is currently tied to aggregative methods. We should provide a general interface also for general quantifiers +Currently, being "binary" only adds one checker; we should figure out how to impose the check to be automatically performed + +Improvements: +========================================== Clarify whether QuaNet is an aggregative method or not. Explore the hyperparameter "number of bins" in HDy Rename EMQ to SLD ? +Parallelize the kFCV in ACC and PACC? +Parallelize model selection trainings +We might want to think of (improving and) adding the class Tabular (it is defined and used on branch tweetsent). A more + recent version is in the project ql4facct. This class is meant to generate latex tables from results (highligting + best results, computing statistical tests, colouring cells, producing rankings, producing averages, etc.). Trying + to generate tables is typically a bad idea, but in this specific case we do have pretty good control of what an + experiment looks like. (Do we want to abstract experimental results? this could be useful not only for tables but + also for plots). + +Checks: +========================================== How many times is the system of equations for ACC and PACC not solved? How many times is it clipped? Do they sum up to one always? -Parallelize the kFCV in ACC and PACC +Re-check how hyperparameters from the quantifier and hyperparameters from the classifier (in aggregative quantifiers) + is handled. In scikit-learn the hyperparameters from a wrapper method are indicated directly whereas the hyperparams + from the internal learner are prefixed with "estimator__". In QuaPy, combinations having to do with the classifier + can be computed at the begining, and then in an internal loop the hyperparams of the quantifier can be explored, + passing fit_learner=False. +Re-check Ensembles. As for now, they are strongly tied to aggregative quantifiers. +Re-think the environment variables. Maybe add new ones (like, for example, parameters for the plots) +Do we want to wrap prevalences (currently simple np.ndarray) as a class? This might be convenient for some interfaces + (e.g., for specifying artificial prevalences in samplings, for printing them -- currently supported through + F.strprev(), etc.). This might however add some overload, and prevent/difficult post processing with numpy. +Would be nice to get a better integration with sklearn. + +