From 365a9e626c8dc6fbd0a8b4e0e00a6583be7110b2 Mon Sep 17 00:00:00 2001 From: Alejandro Moreo Date: Tue, 10 Sep 2024 10:38:17 +0200 Subject: [PATCH 01/11] gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 418b54f..64c94fa 100644 --- a/.gitignore +++ b/.gitignore @@ -167,3 +167,4 @@ TweetSentQuant *.png +.idea From a6ff00f96b601e003191d124ed219d7989ec2401 Mon Sep 17 00:00:00 2001 From: Alejandro Moreo Date: Mon, 16 Sep 2024 12:54:56 +0200 Subject: [PATCH 02/11] simplfiying the minimal working exaple in the README --- CHANGE_LOG.txt | 4 ---- README.md | 13 ++++++------- TODO.txt | 6 ++++++ examples/4b.lequa2024_experiments.py | 6 +++--- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/CHANGE_LOG.txt b/CHANGE_LOG.txt index 3590cf7..b12ca4c 100644 --- a/CHANGE_LOG.txt +++ b/CHANGE_LOG.txt @@ -1,9 +1,5 @@ Change Log 0.1.9 ---------------- -- [TODO] add LeQua2024 and normalized match distance to qp.error -- [TODO] add CDE-iteration and Bayes-CDE methods -- [TODO] add Friedman's method and DeBias -- [TODO] check ignore warning stuff (check https://docs.python.org/3/library/warnings.html#temporarily-suppressing-warnings) - Added LeQua 2024 datasets and normalized match distance to qp.error diff --git a/README.md b/README.md index 5e1dffa..839060d 100644 --- a/README.md +++ b/README.md @@ -45,19 +45,18 @@ of the test set. ```python import quapy as qp -from sklearn.linear_model import LogisticRegression -dataset = qp.datasets.fetch_twitter('semeval16') +dataset = qp.datasets.fetch_UCIBinaryDataset("yeast") +training, test = dataset.train_test # create an "Adjusted Classify & Count" quantifier -model = qp.method.aggregative.ACC(LogisticRegression()) -model.fit(dataset.training) +model = qp.method.aggregative.ACC() +model.fit(training) -estim_prevalence = model.quantify(dataset.test.instances) -true_prevalence = dataset.test.prevalence() +estim_prevalence = model.quantify(test.X) +true_prevalence = test.prevalence() error = qp.error.mae(true_prevalence, estim_prevalence) - print(f'Mean Absolute Error (MAE)={error:.3f}') ``` diff --git a/TODO.txt b/TODO.txt index e69de29..b7d69fa 100644 --- a/TODO.txt +++ b/TODO.txt @@ -0,0 +1,6 @@ +- [TODO] add ensemble methods SC-MQ, MC-SQ, MC-MQ +- [TODO] add HistNetQ +- [TODO] add CDE-iteration and Bayes-CDE methods +- [TODO] add Friedman's method and DeBias +- [TODO] check ignore warning stuff + check https://docs.python.org/3/library/warnings.html#temporarily-suppressing-warnings diff --git a/examples/4b.lequa2024_experiments.py b/examples/4b.lequa2024_experiments.py index 4ce5a43..38394e3 100644 --- a/examples/4b.lequa2024_experiments.py +++ b/examples/4b.lequa2024_experiments.py @@ -33,9 +33,9 @@ quantifier = KDEyML(classifier=LogisticRegression()) # model selection param_grid = { - 'classifier__C': np.logspace(-3, 3, 7), # classifier-dependent: inverse of regularization strength - 'classifier__class_weight': ['balanced', None], # classifier-dependent: weights of each class - 'bandwidth': np.linspace(0.01, 0.2, 20) # quantifier-dependent: bandwidth of the kernel + 'classifier__C': np.logspace(-3, 3, 7), # classifier-dependent: inverse of regularization strength + 'classifier__class_weight': ['balanced', None], # classifier-dependent: weights of each class + 'bandwidth': np.linspace(0.01, 0.2, 20) # quantifier-dependent: bandwidth of the kernel } model_selection = GridSearchQ(quantifier, param_grid, protocol=val_generator, error='mrae', refit=False, verbose=True) quantifier = model_selection.fit(training) From 55c62a9dd279d9c888e78633d44ec65e56679b54 Mon Sep 17 00:00:00 2001 From: Alejandro Moreo Date: Mon, 16 Sep 2024 13:22:36 +0200 Subject: [PATCH 03/11] adding name to datasets un fetch_UCIMulticlassDataset --- quapy/data/datasets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quapy/data/datasets.py b/quapy/data/datasets.py index 6286688..5582a58 100644 --- a/quapy/data/datasets.py +++ b/quapy/data/datasets.py @@ -637,7 +637,7 @@ def fetch_UCIMulticlassDataset( if n_train > max_train_instances: train_prop = (max_train_instances / n) - data = Dataset(*data.split_stratified(train_prop, random_state=0)) + data = Dataset(*data.split_stratified(train_prop, random_state=0), name=dataset_name) if standardize: data = standardizer(data) From 2311bb66491a37e59400c0ba35938ca113ef17ea Mon Sep 17 00:00:00 2001 From: Mirko Bunse Date: Mon, 16 Sep 2024 13:44:35 +0200 Subject: [PATCH 04/11] CI: replace ammaraskar/sphinx-action with custom run commands --- .github/workflows/ci.yml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 030b152..9ba9d0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,9 +20,9 @@ jobs: env: QUAPY_TESTS_OMIT_LARGE_DATASETS: True steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies @@ -38,15 +38,17 @@ jobs: runs-on: ubuntu-latest if: github.ref == 'refs/heads/master' steps: - - uses: actions/checkout@v1 - - name: Build documentation - uses: ammaraskar/sphinx-action@master + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 with: - pre-build-command: | - apt-get --allow-releaseinfo-change update -y && apt-get install -y git && git --version - python -m pip install --upgrade pip setuptools wheel "jax[cpu]" - python -m pip install -e .[composable,neural,docs] - docs-folder: "docs/" + python-version: 3.11 + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools wheel "jax[cpu]" + python -m pip install -e .[composable,neural,docs] + - name: Build documentation + run: sphinx-build -M html docs/source docs/build - name: Publish documentation run: | git clone ${{ github.server_url }}/${{ github.repository }}.git --branch gh-pages --single-branch __gh-pages/ From de3f8fd300d50202f1ec0e926d7b7228ee20fb31 Mon Sep 17 00:00:00 2001 From: Mirko Bunse Date: Mon, 16 Sep 2024 13:48:11 +0200 Subject: [PATCH 05/11] TO REVERT: build gh-pages even on pushes to devel --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ba9d0f..7dd0cfe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,6 @@ jobs: docs: name: Documentation runs-on: ubuntu-latest - if: github.ref == 'refs/heads/master' steps: - uses: actions/checkout@v4 - name: Set up Python From 3895cba6104143a7ce624872743b1d6a42e8ac90 Mon Sep 17 00:00:00 2001 From: Mirko Bunse Date: Mon, 16 Sep 2024 13:56:00 +0200 Subject: [PATCH 06/11] Revert "TO REVERT: build gh-pages even on pushes to devel" This reverts commit de3f8fd300d50202f1ec0e926d7b7228ee20fb31. --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7dd0cfe..9ba9d0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ jobs: docs: name: Documentation runs-on: ubuntu-latest + if: github.ref == 'refs/heads/master' steps: - uses: actions/checkout@v4 - name: Set up Python From 584a4d07d4e47a88039b670438aa7f2582b4b583 Mon Sep 17 00:00:00 2001 From: Alejandro Moreo Date: Mon, 16 Sep 2024 15:07:19 +0200 Subject: [PATCH 07/11] removing pylint --- .github/workflows/pylint.yml | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 .github/workflows/pylint.yml diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml deleted file mode 100644 index 383e65c..0000000 --- a/.github/workflows/pylint.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Pylint - -on: [push] - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ["3.8", "3.9", "3.10"] - steps: - - uses: actions/checkout@v3 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v3 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pylint - - name: Analysing the code with pylint - run: | - pylint $(git ls-files '*.py') From cea96e87c6f08f5b5bc7173717f9dd84e142a30e Mon Sep 17 00:00:00 2001 From: Alejandro Moreo Date: Mon, 16 Sep 2024 15:30:34 +0200 Subject: [PATCH 08/11] added path to sys.path in config --- KDEy/experiments.py | 108 ++++++++++++++++++++++++++++++++++++++++++++ docs/source/conf.py | 5 ++ 2 files changed, 113 insertions(+) create mode 100644 KDEy/experiments.py diff --git a/KDEy/experiments.py b/KDEy/experiments.py new file mode 100644 index 0000000..fb279fc --- /dev/null +++ b/KDEy/experiments.py @@ -0,0 +1,108 @@ +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) + + + + + diff --git a/docs/source/conf.py b/docs/source/conf.py index cfed1ac..689cc6e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -11,9 +11,14 @@ import sys from os.path import join quapy_path = join(pathlib.Path(__file__).parents[2].resolve().as_posix(), 'quapy') wiki_path = join(pathlib.Path(__file__).parents[0].resolve().as_posix(), 'wiki') +source_path = pathlib.Path(__file__).parents[2].resolve().as_posix() print(f'quapy path={quapy_path}') +print(f'quapy source path={source_path}') sys.path.insert(0, quapy_path) sys.path.insert(0, wiki_path) +sys.path.insert(0, source_path) + +print(sys.path) project = 'QuaPy: A Python-based open-source framework for quantification' From 9be729386a82071a8c138a896c733a7c66a2ba6c Mon Sep 17 00:00:00 2001 From: Mirko Bunse Date: Tue, 17 Sep 2024 10:19:26 +0200 Subject: [PATCH 09/11] 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 10/11] 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 11/11] 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.