QuaPy/Retrieval/kdey_bandwidth_selection_qu...

162 lines
6.0 KiB
Python

import os.path
import pickle
from collections import defaultdict
from pathlib import Path
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV
from sklearn.svm import LinearSVC
import quapy as qp
from Retrieval.commons import RetrievedSamples, load_sample
from method.non_aggregative import MaximumLikelihoodPrevalenceEstimation as Naive
from quapy.method.aggregative import ClassifyAndCount, EMQ, ACC, PCC, PACC, KDEyML
from quapy.data.base import LabelledCollection
from os.path import join
from tqdm import tqdm
from result_table.src.table import Table
def methods(classifier, class_name):
yield ('KDE001', KDEyML(classifier, val_split=5, n_jobs=-1, bandwidth=0.001))
yield ('KDE005', KDEyML(classifier, val_split=5, n_jobs=-1, bandwidth=0.005))
yield ('KDE01', KDEyML(classifier, val_split=5, n_jobs=-1, bandwidth=0.01))
yield ('KDE02', KDEyML(classifier, val_split=5, n_jobs=-1, bandwidth=0.02))
yield ('KDE03', KDEyML(classifier, val_split=5, n_jobs=-1, bandwidth=0.03))
yield ('KDE04', KDEyML(classifier, val_split=5, n_jobs=-1, bandwidth=0.04))
yield ('KDE05', KDEyML(classifier, val_split=5, n_jobs=-1, bandwidth=0.05))
yield ('KDE07', KDEyML(classifier, val_split=5, n_jobs=-1, bandwidth=0.07))
yield ('KDE10', KDEyML(classifier, val_split=5, n_jobs=-1, bandwidth=0.10))
def reduceAtK(data: LabelledCollection, k):
# if k > len(data):
# print(f'[warning] {k=}>{len(data)=}')
X, y = data.Xy
X = X[:k]
y = y[:k]
return LabelledCollection(X, y, classes=data.classes_)
def run_experiment():
results = {
'mae': {k: [] for k in Ks},
'mrae': {k: [] for k in Ks}
}
pbar = tqdm(experiment_prot(), total=experiment_prot.total())
for train, test in pbar:
Xtr, ytr, score_tr = train
Xte, yte, score_te = test
if HALF:
n = len(ytr) // 2
train_col = LabelledCollection(Xtr[:n], ytr[:n], classes=classifier_trained.classes_)
else:
train_col = LabelledCollection(Xtr, ytr, classes=classifier_trained.classes_)
if method_name not in ['Naive', 'NaiveQuery']:
quantifier.fit(train_col, val_split=train_col, fit_classifier=False)
elif method_name == 'Naive':
quantifier.fit(train_col)
test_col = LabelledCollection(Xte, yte, classes=classifier_trained.classes_)
for k in Ks:
test_k = reduceAtK(test_col, k)
if method_name == 'NaiveQuery':
train_k = reduceAtK(train_col, k)
quantifier.fit(train_k)
estim_prev = quantifier.quantify(test_k.instances)
mae = qp.error.mae(test_k.prevalence(), estim_prev)
mrae = qp.error.mrae(test_k.prevalence(), estim_prev, eps=(1. / (2 * k)))
results['mae'][k].append(mae)
results['mrae'][k].append(mrae)
pbar.set_description(f'{method_name}')
return results
def benchmark_name(class_name, k):
scape_class_name = class_name.replace('_', '\_')
return f'{scape_class_name}@{k}'
if __name__ == '__main__':
data_home = 'data-modsel'
HALF=True
exp_posfix = '_half_modsel'
Ks = [5, 10, 25, 50, 75, 100, 250, 500, 750, 1000]
method_names = [m for m, *_ in methods(None, None)]
dir_names={
'gender': '100K_GENDER_TREC21_QUERIES/100K-NEW-QUERIES',
'continent': '100K_CONT_TREC21_QUERIES/100K-NEW-QUERIES',
'years_category': '100K_YEARS_TREC21_QUERIES/100K-NEW-QUERIES'
}
for class_name in ['gender', 'continent', 'years_category']: # 'relative_pageviews_category', 'num_sitelinks_category']:
tables_mae, tables_mrae = [], []
benchmarks = [benchmark_name(class_name, k) for k in Ks]
for data_size in ['100K']:
table_mae = Table(name=f'{class_name}-{data_size}-mae', benchmarks=benchmarks, methods=method_names)
table_mrae = Table(name=f'{class_name}-{data_size}-mrae', benchmarks=benchmarks, methods=method_names)
table_mae.format.mean_prec = 5
table_mae.format.remove_zero = True
table_mae.format.color_mode = 'global'
tables_mae.append(table_mae)
tables_mrae.append(table_mrae)
class_home = join(data_home, dir_names[class_name])
classifier_path = join('classifiers', 'FULL', f'classifier_{class_name}.pkl') # <------------ fixed classifier
test_rankings_path = join(data_home, 'testRanking-TREC21-Queries_Results.json')
results_home = join('results'+exp_posfix, class_name, data_size)
tfidf, classifier_trained = pickle.load(open(classifier_path, 'rb'))
experiment_prot = RetrievedSamples(
class_home,
test_rankings_path,
vectorizer=tfidf,
class_name=class_name,
classes=classifier_trained.classes_
)
for method_name, quantifier in methods(classifier_trained, class_name):
results_path = join(results_home, method_name + '.pkl')
if os.path.exists(results_path):
print(f'Method {method_name=} already computed')
results = pickle.load(open(results_path, 'rb'))
else:
results = run_experiment()
os.makedirs(Path(results_path).parent, exist_ok=True)
pickle.dump(results, open(results_path, 'wb'), pickle.HIGHEST_PROTOCOL)
for k in Ks:
table_mae.add(benchmark=benchmark_name(class_name, k), method=method_name, v=results['mae'][k])
table_mrae.add(benchmark=benchmark_name(class_name, k), method=method_name, v=results['mrae'][k])
# Table.LatexPDF(f'./latex{exp_posfix}/{class_name}{exp_posfix}.pdf', tables=tables_mae+tables_mrae)
Table.LatexPDF(f'./latex{exp_posfix}/{class_name}{exp_posfix}.pdf', tables=tables_mrae)