From 9be729386a82071a8c138a896c733a7c66a2ba6c Mon Sep 17 00:00:00 2001 From: Mirko Bunse Date: Tue, 17 Sep 2024 10:19:26 +0200 Subject: [PATCH 1/3] Fix PyPI: replace the direct extra dependency quapy[composable] with documentation on how to install through git --- .github/workflows/ci.yml | 6 ++++-- docs/source/manuals/methods.md | 2 +- examples/14.composable_methods.py | 7 +++++++ setup.py | 1 - 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ba9d0f..17a6c39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,8 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip setuptools wheel - python -m pip install -e .[bayes,composable,tests] + python -m pip install "qunfold @ git+https://github.com/mirkobunse/qunfold@v0.1.4" + python -m pip install -e .[bayes,tests] - name: Test with unittest run: python -m unittest @@ -46,7 +47,8 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip setuptools wheel "jax[cpu]" - python -m pip install -e .[composable,neural,docs] + python -m pip install "qunfold @ git+https://github.com/mirkobunse/qunfold@v0.1.4" + python -m pip install -e .[neural,docs] - name: Build documentation run: sphinx-build -M html docs/source docs/build - name: Publish documentation diff --git a/docs/source/manuals/methods.md b/docs/source/manuals/methods.md index 0644ebc..598c193 100644 --- a/docs/source/manuals/methods.md +++ b/docs/source/manuals/methods.md @@ -447,7 +447,7 @@ The [](quapy.method.composable) module allows the composition of quantification ```sh pip install --upgrade pip setuptools wheel pip install "jax[cpu]" -pip install quapy[composable] +pip install "qunfold @ git+https://github.com/mirkobunse/qunfold@v0.1.4" ``` ### Basics diff --git a/examples/14.composable_methods.py b/examples/14.composable_methods.py index 2a8701d..5ffcb94 100644 --- a/examples/14.composable_methods.py +++ b/examples/14.composable_methods.py @@ -2,6 +2,13 @@ This example illustrates the composition of quantification methods from arbitrary loss functions and feature transformations. It will extend the basic example on the usage of quapy with this composition. + +This example requires the installation of qunfold, the back-end of QuaPy's +composition module: + + pip install --upgrade pip setuptools wheel + pip install "jax[cpu]" + pip install "qunfold @ git+https://github.com/mirkobunse/qunfold@v0.1.4" """ import numpy as np diff --git a/setup.py b/setup.py index c071c07..bb8ad80 100644 --- a/setup.py +++ b/setup.py @@ -125,7 +125,6 @@ setup( # projects. extras_require={ # Optional 'bayes': ['jax', 'jaxlib', 'numpyro'], - 'composable': ['qunfold @ git+https://github.com/mirkobunse/qunfold@v0.1.4'], 'neural': ['torch'], 'tests': ['certifi'], 'docs' : ['sphinx-rtd-theme', 'myst-parser'], From b485205c7cf95efb26e42066ef1b1df611ddc3b2 Mon Sep 17 00:00:00 2001 From: Alejandro Moreo Date: Tue, 17 Sep 2024 10:39:39 +0200 Subject: [PATCH 2/3] cleaning dir KDEy --- KDEy/experiments.py | 108 -------------------------------------------- 1 file changed, 108 deletions(-) delete mode 100644 KDEy/experiments.py diff --git a/KDEy/experiments.py b/KDEy/experiments.py deleted file mode 100644 index fb279fc..0000000 --- a/KDEy/experiments.py +++ /dev/null @@ -1,108 +0,0 @@ -import numpy as np -from sklearn.linear_model import LogisticRegression -from os.path import join -import quapy as qp -from quapy.protocol import UPP -from quapy.method.aggregative import KDEyML - -DEBUG = True - -qp.environ["SAMPLE_SIZE"] = 100 if DEBUG else 500 -val_repeats = 100 if DEBUG else 500 -test_repeats = 100 if DEBUG else 500 -if DEBUG: - qp.environ["DEFAULT_CLS"] = LogisticRegression() - -test_results = {} -val_choice = {} - -bandwidth_range = np.linspace(0.01, 0.20, 20) -if DEBUG: - bandwidth_range = np.linspace(0.01, 0.20, 10) - -def datasets(): - for dataset_name in qp.datasets.UCI_MULTICLASS_DATASETS[:4]: - dataset = qp.datasets.fetch_UCIMulticlassDataset(dataset_name) - if DEBUG: - dataset = dataset.reduce(random_state=0) - yield dataset - - -def experiment_dataset(dataset): - train, test = dataset.train_test - test_gen = UPP(test, repeats=test_repeats) - - # bandwidth chosen during model selection in validation - train_tr, train_va = train.split_stratified(random_state=0) - kdey = KDEyML(random_state=0) - modsel = qp.model_selection.GridSearchQ( - model=kdey, - param_grid={'bandwidth': bandwidth_range}, - protocol=UPP(train_va, repeats=val_repeats), - refit=False, - n_jobs=-1 - ).fit(train_tr) - chosen_bandwidth = modsel.best_params_['bandwidth'] - modsel_choice = float(chosen_bandwidth) - - # results in test - print(f"testing KDEy in {dataset.name}") - dataset_results = [] - for b in bandwidth_range: - kdey = KDEyML(bandwidth=b, random_state=0) - kdey.fit(train) - - mae = qp.evaluation.evaluate(kdey, protocol=test_gen, error_metric='mae', verbose=True) - print(f'bandwidth={b}: {mae:.5f}') - dataset_results.append((float(b), float(mae))) - - return modsel_choice, dataset_results - -def plot_bandwidth(val_choice, test_results): - for dataset_name in val_choice.keys(): - import matplotlib.pyplot as plt - - bandwidths, results = zip(*test_results[dataset_name]) - - # Crear la gráfica - plt.figure(figsize=(8, 6)) - - # Graficar los puntos de datos - plt.plot(bandwidths, results, marker='o') - - # Agregar la línea vertical en bandwidth_chosen - plt.axvline(x=val_choice[dataset_name], color='r', linestyle='--', label=f'Bandwidth elegido: {val_choice[dataset_name]}') - - # Agregar etiquetas y título - plt.xlabel('Bandwidth') - plt.ylabel('Resultado') - plt.title('Gráfica de Bandwidth vs Resultado') - - # Mostrar la leyenda - plt.legend() - - # Mostrar la gráfica - plt.grid(True) - plt.show() - - -for dataset in datasets(): - if DEBUG: - result_path = f'./results/debug/{dataset.name}.pkl' - else: - result_path = f'./results/{dataset.name}.pkl' - - modsel_choice, dataset_results = qp.util.pickled_resource(result_path, experiment_dataset, dataset) - val_choice[dataset.name] = modsel_choice - test_results[dataset.name] = dataset_results - - print(f'Dataset = {dataset.name}') - print(modsel_choice) - print(dataset_results) - -plot_bandwidth(val_choice, test_results) - - - - - From db8a87049599fb8ae3ddd4c437c8568f1313aeb2 Mon Sep 17 00:00:00 2001 From: Mirko Bunse Date: Tue, 17 Sep 2024 10:48:53 +0200 Subject: [PATCH 3/3] Instruct the user how to install qunfold in the case of an unsuccessful import --- quapy/method/composable.py | 90 +++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/quapy/method/composable.py b/quapy/method/composable.py index aa00be4..5d40aad 100644 --- a/quapy/method/composable.py +++ b/quapy/method/composable.py @@ -1,45 +1,57 @@ """This module allows the composition of quantification methods from loss functions and feature transformations. This functionality is realized through an integration of the qunfold package: https://github.com/mirkobunse/qunfold.""" -import qunfold -from qunfold.quapy import QuaPyWrapper -from qunfold.sklearn import CVClassifier -from qunfold import ( - LeastSquaresLoss, # losses - BlobelLoss, - EnergyLoss, - HellingerSurrogateLoss, - CombinedLoss, - TikhonovRegularization, - TikhonovRegularized, - ClassTransformer, # transformers - HistogramTransformer, - DistanceTransformer, - KernelTransformer, - EnergyKernelTransformer, - LaplacianKernelTransformer, - GaussianKernelTransformer, - GaussianRFFKernelTransformer, -) +_import_error_message = """qunfold, the back-end of quapy.method.composable, is not properly installed. -__all__ = [ # control public members, e.g., for auto-documentation in sphinx; omit QuaPyWrapper - "ComposableQuantifier", - "CVClassifier", - "LeastSquaresLoss", - "BlobelLoss", - "EnergyLoss", - "HellingerSurrogateLoss", - "CombinedLoss", - "TikhonovRegularization", - "TikhonovRegularized", - "ClassTransformer", - "HistogramTransformer", - "DistanceTransformer", - "KernelTransformer", - "EnergyKernelTransformer", - "LaplacianKernelTransformer", - "GaussianKernelTransformer", - "GaussianRFFKernelTransformer", -] +To fix this error, call: + + pip install --upgrade pip setuptools wheel + pip install "jax[cpu]" + pip install "qunfold @ git+https://github.com/mirkobunse/qunfold@v0.1.4" +""" + +try: + import qunfold + from qunfold.quapy import QuaPyWrapper + from qunfold.sklearn import CVClassifier + from qunfold import ( + LeastSquaresLoss, # losses + BlobelLoss, + EnergyLoss, + HellingerSurrogateLoss, + CombinedLoss, + TikhonovRegularization, + TikhonovRegularized, + ClassTransformer, # transformers + HistogramTransformer, + DistanceTransformer, + KernelTransformer, + EnergyKernelTransformer, + LaplacianKernelTransformer, + GaussianKernelTransformer, + GaussianRFFKernelTransformer, + ) + + __all__ = [ # control public members, e.g., for auto-documentation in sphinx; omit QuaPyWrapper + "ComposableQuantifier", + "CVClassifier", + "LeastSquaresLoss", + "BlobelLoss", + "EnergyLoss", + "HellingerSurrogateLoss", + "CombinedLoss", + "TikhonovRegularization", + "TikhonovRegularized", + "ClassTransformer", + "HistogramTransformer", + "DistanceTransformer", + "KernelTransformer", + "EnergyKernelTransformer", + "LaplacianKernelTransformer", + "GaussianKernelTransformer", + "GaussianRFFKernelTransformer", + ] +except ImportError as e: + raise ImportError(_import_error_message) from e def ComposableQuantifier(loss, transformer, **kwargs): """A generic quantification / unfolding method that solves a linear system of equations.