QuaPy/docs/build/html/_modules/quapy/method/aggregative.html

2500 lines
275 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" data-content_root="../../../" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>quapy.method.aggregative &#8212; QuaPy: A Python-based open-source framework for quantification 0.2.1 documentation</title>
<script data-cfasync="false">
document.documentElement.dataset.mode = localStorage.getItem("mode") || "";
document.documentElement.dataset.theme = localStorage.getItem("theme") || "";
</script>
<!--
this give us a css class that will be invisible only if js is disabled
-->
<noscript>
<style>
.pst-js-only { display: none !important; }
</style>
</noscript>
<!-- Loaded before other Sphinx assets -->
<link href="../../../_static/styles/theme.css?digest=90905a2f556bf617f1a9" rel="stylesheet" />
<link href="../../../_static/styles/pydata-sphinx-theme.css?digest=90905a2f556bf617f1a9" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css?v=8f2a1f02" />
<link rel="stylesheet" type="text/css" href="../../../_static/sphinx-design.min.css?v=95c83b7e" />
<link rel="stylesheet" type="text/css" href="../../../_static/custom.css?v=9f2a2228" />
<!-- So that users can add custom icons -->
<script defer src="../../../_static/scripts/fontawesome.js?digest=90905a2f556bf617f1a9"></script>
<!-- Pre-loaded scripts that we'll load fully later -->
<link rel="preload" as="script" href="../../../_static/scripts/bootstrap.js?digest=90905a2f556bf617f1a9" />
<link rel="preload" as="script" href="../../../_static/scripts/pydata-sphinx-theme.js?digest=90905a2f556bf617f1a9" />
<script src="../../../_static/documentation_options.js?v=37f418d5"></script>
<script src="../../../_static/doctools.js?v=fd6eb6e6"></script>
<script src="../../../_static/sphinx_highlight.js?v=6ffebe34"></script>
<script src="../../../_static/design-tabs.js?v=f930bc37"></script>
<script>DOCUMENTATION_OPTIONS.pagename = '_modules/quapy/method/aggregative';</script>
<script>DOCUMENTATION_OPTIONS.search_as_you_type = false;</script>
<link rel="index" title="Index" href="../../../genindex.html" />
<link rel="search" title="Search" href="../../../search.html" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="docsearch:language" content="en"/>
<meta name="docsearch:version" content="" />
<script src="../../../_static/searchtools.js"></script>
<script src="../../../_static/language_data.js"></script>
<script src="../../../searchindex.js"></script>
</head>
<body data-default-mode="">
<div id="pst-skip-link" class="skip-link d-print-none"><a href="#main-content">Skip to main content</a></div>
<div id="pst-scroll-pixel-helper"></div>
<button type="button" class="btn rounded-pill" id="pst-back-to-top">
<i class="fa-solid fa-arrow-up"></i>Back to top</button>
<dialog id="pst-search-dialog">
<form class="bd-search d-flex align-items-center"
action="../../../search.html"
method="get">
<i class="fa-solid fa-magnifying-glass"></i>
<input type="search"
class="form-control"
name="q"
placeholder="Search the docs ..."
aria-label="Search the docs ..."
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"/>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd>K</kbd></span>
</form>
</dialog>
<div class="pst-async-banner-revealer d-none">
<aside id="bd-header-version-warning" class="d-none d-print-none" aria-label="Version warning"></aside>
</div>
<header id="pst-header" class="bd-header navbar navbar-expand-lg bd-navbar d-print-none">
<div class="bd-header__inner bd-page-width">
<button class="pst-navbar-icon sidebar-toggle primary-toggle" aria-label="Site navigation">
<span class="fa-solid fa-bars"></span>
</button>
<div class="col-lg-3 navbar-header-items__start">
<div class="navbar-item">
<a class="navbar-brand logo" href="../../../index.html">
<img src="../../../_static/quapy_logo.png" class="logo__image only-light" alt="QuaPy: A Python-based open-source framework for quantification 0.2.1 documentation - Home"/>
<img src="../../../_static/quapy_logo_dark.png" class="logo__image only-dark pst-js-only" alt="QuaPy: A Python-based open-source framework for quantification 0.2.1 documentation - Home"/>
</a></div>
</div>
<div class="col-lg-9 navbar-header-items">
<div class="me-auto navbar-header-items__center">
<div class="navbar-item">
<nav>
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../../index.html">
Home
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../../manuals.html">
Manuals
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../../quapy.html">
API
</a>
</li>
</ul>
</nav></div>
</div>
<div class="navbar-header-items__end">
<div class="navbar-item navbar-persistent--container">
<button class="btn search-button-field search-button__button pst-js-only" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
</div>
<div class="navbar-item">
<div class="theme-switch-container dropdown pst-js-only" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Color mode">
<button class="btn btn-sm nav-link pst-navbar-icon theme-switch-button dropdown-toggle" aria-label="Color mode" data-bs-toggle="dropdown">
<i class="theme-switch fa-solid fa-sun fa-lg fa-fw" data-mode="light" title="Light"></i>
<i class="theme-switch fa-solid fa-moon fa-lg fa-fw" data-mode="dark" title="Dark"></i>
<i class="theme-switch fa-solid fa-circle-half-stroke fa-lg fa-fw" data-mode="auto" title="System Settings"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><button class="dropdown-item d-flex align-items-center theme-change-button" data-mode="auto"><i class="fa-solid fa-circle-half-stroke fa-lg fa-fw me-1"></i>System Settings</button></li>
<li><button class="dropdown-item d-flex align-items-center theme-change-button" data-mode="light"><i class="fa-solid fa-sun fa-lg fa-fw me-1"></i>Light</button></li>
<li><button class="dropdown-item d-flex align-items-center theme-change-button" data-mode="dark"><i class="fa-solid fa-moon fa-lg fa-fw me-1"></i>Dark</button></li>
</ul>
</div></div>
<div class="navbar-item"><ul class="navbar-icon-links"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/HLT-ISTI/QuaPy" title="GitHub" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-github fa-lg" aria-hidden="true"></i><span class="visually-hidden">GitHub</span></a>
</li>
</ul></div>
</div>
</div>
<div class="navbar-persistent--mobile">
<button class="btn search-button-field search-button__button pst-js-only" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
</div>
</div>
</header>
<div class="bd-container">
<div class="bd-container__inner bd-page-width">
<dialog id="pst-primary-sidebar-modal"></dialog>
<div id="pst-primary-sidebar" class="bd-sidebar-primary bd-sidebar hide-on-wide">
<div class="sidebar-header-items sidebar-primary__section">
<div class="sidebar-header-items__center">
<div class="navbar-item">
<nav>
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../../index.html">
Home
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../../manuals.html">
Manuals
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../../quapy.html">
API
</a>
</li>
</ul>
</nav></div>
</div>
<div class="sidebar-header-items__end">
<div class="navbar-item">
<div class="theme-switch-container dropdown pst-js-only" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Color mode">
<button class="btn btn-sm nav-link pst-navbar-icon theme-switch-button dropdown-toggle" aria-label="Color mode" data-bs-toggle="dropdown">
<i class="theme-switch fa-solid fa-sun fa-lg fa-fw" data-mode="light" title="Light"></i>
<i class="theme-switch fa-solid fa-moon fa-lg fa-fw" data-mode="dark" title="Dark"></i>
<i class="theme-switch fa-solid fa-circle-half-stroke fa-lg fa-fw" data-mode="auto" title="System Settings"></i>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><button class="dropdown-item d-flex align-items-center theme-change-button" data-mode="auto"><i class="fa-solid fa-circle-half-stroke fa-lg fa-fw me-1"></i>System Settings</button></li>
<li><button class="dropdown-item d-flex align-items-center theme-change-button" data-mode="light"><i class="fa-solid fa-sun fa-lg fa-fw me-1"></i>Light</button></li>
<li><button class="dropdown-item d-flex align-items-center theme-change-button" data-mode="dark"><i class="fa-solid fa-moon fa-lg fa-fw me-1"></i>Dark</button></li>
</ul>
</div></div>
<div class="navbar-item"><ul class="navbar-icon-links"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/HLT-ISTI/QuaPy" title="GitHub" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-github fa-lg" aria-hidden="true"></i><span class="visually-hidden">GitHub</span></a>
</li>
</ul></div>
</div>
</div>
<div class="sidebar-primary-items__end sidebar-primary__section">
<div class="sidebar-primary-item">
<div id="ethical-ad-placement"
class="flat"
data-ea-publisher="readthedocs"
data-ea-type="readthedocs-sidebar"
data-ea-manual="true">
</div></div>
</div>
</div>
<main id="main-content" class="bd-main" role="main">
<div class="bd-content">
<div class="bd-article-container">
<div class="bd-header-article d-print-none">
<div class="header-article-items header-article__inner">
<div class="header-article-items__start">
<div class="header-article-item">
<nav aria-label="Breadcrumb" class="d-print-none">
<ul class="bd-breadcrumbs">
<li class="breadcrumb-item breadcrumb-home">
<a href="../../../index.html" class="nav-link" aria-label="Home">
<i class="fa-solid fa-home"></i>
</a>
</li>
<li class="breadcrumb-item"><a href="../../index.html" class="nav-link">Module code</a></li>
<li class="breadcrumb-item active" aria-current="page"><span class="ellipsis">quapy.method.aggregative</span></li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div id="searchbox"></div>
<article class="bd-article">
<h1>Source code for quapy.method.aggregative</h1><div class="highlight"><pre>
<span></span><span class="kn">import</span><span class="w"> </span><span class="nn">warnings</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">abc</span><span class="w"> </span><span class="kn">import</span> <span class="n">ABC</span><span class="p">,</span> <span class="n">abstractmethod</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">copy</span><span class="w"> </span><span class="kn">import</span> <span class="n">deepcopy</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">Literal</span><span class="p">,</span> <span class="n">Union</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">numpy</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">np</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sklearn.base</span><span class="w"> </span><span class="kn">import</span> <span class="n">BaseEstimator</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sklearn.calibration</span><span class="w"> </span><span class="kn">import</span> <span class="n">CalibratedClassifierCV</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sklearn.exceptions</span><span class="w"> </span><span class="kn">import</span> <span class="n">NotFittedError</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sklearn.metrics</span><span class="w"> </span><span class="kn">import</span> <span class="n">confusion_matrix</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sklearn.model_selection</span><span class="w"> </span><span class="kn">import</span> <span class="n">cross_val_predict</span><span class="p">,</span> <span class="n">train_test_split</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sklearn.utils.validation</span><span class="w"> </span><span class="kn">import</span> <span class="n">check_is_fitted</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">quapy</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">qp</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">quapy.functional</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">F</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">quapy.functional</span><span class="w"> </span><span class="kn">import</span> <span class="n">get_divergence</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">quapy.classification.svmperf</span><span class="w"> </span><span class="kn">import</span> <span class="n">SVMperf</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">quapy.data</span><span class="w"> </span><span class="kn">import</span> <span class="n">LabelledCollection</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">quapy.method.base</span><span class="w"> </span><span class="kn">import</span> <span class="n">BaseQuantifier</span><span class="p">,</span> <span class="n">BinaryQuantifier</span><span class="p">,</span> <span class="n">OneVsAllGeneric</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">quapy.method._energy</span><span class="w"> </span><span class="kn">import</span> <span class="n">_EnergyDistanceCore</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">quapy.method._helper</span><span class="w"> </span><span class="kn">import</span> <span class="p">(</span>
<span class="n">_get_abstention_calibrators</span><span class="p">,</span>
<span class="n">_get_cvxpy</span><span class="p">,</span>
<span class="n">_rlls_check_mode</span><span class="p">,</span>
<span class="n">_rlls_joint_distribution</span><span class="p">,</span>
<span class="n">_rlls_predicted_marginal</span><span class="p">,</span>
<span class="n">_rlls_compute_3deltaC</span><span class="p">,</span>
<span class="n">_rlls_compute_weights</span><span class="p">,</span>
<span class="n">_labels_to_indices</span><span class="p">,</span>
<span class="p">)</span>
<span class="c1"># Abstract classes</span>
<span class="c1"># ------------------------------------</span>
<div class="viewcode-block" id="AggregativeQuantifier">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeQuantifier">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">AggregativeQuantifier</span><span class="p">(</span><span class="n">BaseQuantifier</span><span class="p">,</span> <span class="n">ABC</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Abstract class for quantification methods that base their estimations on the aggregation of classification</span>
<span class="sd"> results. Aggregative quantifiers implement a pipeline that consists of generating classification predictions</span>
<span class="sd"> and aggregating them. For this reason, the training phase is implemented by :meth:`classification_fit` followed</span>
<span class="sd"> by :meth:`aggregation_fit`, while the testing phase is implemented by :meth:`classify` followed by</span>
<span class="sd"> :meth:`aggregate`. Subclasses of this abstract class must provide implementations for these methods.</span>
<span class="sd"> Aggregative quantifiers also maintain a :attr:`classifier` attribute.</span>
<span class="sd"> The method :meth:`fit` comes with a default implementation based on :meth:`classification_fit`</span>
<span class="sd"> and :meth:`aggregation_fit`.</span>
<span class="sd"> The method :meth:`quantify` comes with a default implementation based on :meth:`classify`</span>
<span class="sd"> and :meth:`aggregate`.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set to False if the</span>
<span class="sd"> learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier predictions. This specification</span>
<span class="sd"> can be made as float in (0, 1) indicating the proportion of stratified held-out validation set to</span>
<span class="sd"> be extracted from the training set; or as an integer (default 5), indicating that the predictions</span>
<span class="sd"> are to be generated in a `k`-fold cross-validation manner (with this integer indicating the value</span>
<span class="sd"> for `k`); or as a tuple `(X,y)` defining the specific set of data to use for validation. Set to</span>
<span class="sd"> None when the method does not require any validation data, in order to avoid that some portion of</span>
<span class="sd"> the training data be wasted.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span>
<span class="n">classifier</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="kc">None</span><span class="p">,</span><span class="n">BaseEstimator</span><span class="p">],</span>
<span class="n">fit_classifier</span><span class="p">:</span><span class="nb">bool</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">val_split</span><span class="p">:</span><span class="n">Union</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span><span class="nb">float</span><span class="p">,</span><span class="nb">tuple</span><span class="p">,</span><span class="kc">None</span><span class="p">]</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classifier</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_classifier</span><span class="p">(</span><span class="n">classifier</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span> <span class="o">=</span> <span class="n">fit_classifier</span>
<span class="bp">self</span><span class="o">.</span><span class="n">val_split</span> <span class="o">=</span> <span class="n">val_split</span>
<span class="c1"># basic type checks</span>
<span class="k">assert</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="p">,</span> <span class="s1">&#39;fit&#39;</span><span class="p">),</span> \
<span class="sa">f</span><span class="s1">&#39;the classifier does not implement &quot;fit&quot;&#39;</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">fit_classifier</span><span class="p">,</span> <span class="nb">bool</span><span class="p">),</span> \
<span class="sa">f</span><span class="s1">&#39;unexpected type for </span><span class="si">{</span><span class="n">fit_classifier</span><span class="si">=}</span><span class="s1">; must be True or False&#39;</span>
<span class="c1"># val_split is indicated as a number of folds for cross-validation</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">val_split</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
<span class="k">assert</span> <span class="n">val_split</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">,</span> \
<span class="p">(</span><span class="sa">f</span><span class="s1">&#39;when </span><span class="si">{</span><span class="n">val_split</span><span class="si">=}</span><span class="s1"> is indicated as an integer, it represents the number of folds in a kFCV &#39;</span>
<span class="sa">f</span><span class="s1">&#39;and must thus be &gt;1&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">val_split</span><span class="o">==</span><span class="mi">5</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">fit_classifier</span><span class="p">:</span>
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">val_split</span><span class="si">=}</span><span class="s1"> will be ignored when the classifier is already trained &#39;</span>
<span class="sa">f</span><span class="s1">&#39;(</span><span class="si">{</span><span class="n">fit_classifier</span><span class="si">=}</span><span class="s1">). Parameter </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">val_split</span><span class="si">=}</span><span class="s1"> will be set to None. Set </span><span class="si">{</span><span class="n">val_split</span><span class="si">=}</span><span class="s1"> &#39;</span>
<span class="sa">f</span><span class="s1">&#39;to None to avoid this warning.&#39;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">val_split</span><span class="o">=</span><span class="kc">None</span>
<span class="k">if</span> <span class="n">val_split</span><span class="o">!=</span><span class="mi">5</span><span class="p">:</span>
<span class="k">assert</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Parameter </span><span class="si">{</span><span class="n">val_split</span><span class="si">=}</span><span class="s1"> has been modified, but </span><span class="si">{</span><span class="n">fit_classifier</span><span class="si">=}</span><span class="s1"> &#39;</span>
<span class="sa">f</span><span class="s1">&#39;indicates the classifier should not be retrained.&#39;</span><span class="p">)</span>
<span class="c1"># val_split is indicated as a fraction of validation instances</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">val_split</span><span class="p">,</span> <span class="nb">float</span><span class="p">):</span>
<span class="k">assert</span> <span class="mi">0</span> <span class="o">&lt;</span> <span class="n">val_split</span> <span class="o">&lt;</span> <span class="mi">1</span><span class="p">,</span> \
<span class="p">(</span><span class="sa">f</span><span class="s1">&#39;when </span><span class="si">{</span><span class="n">val_split</span><span class="si">=}</span><span class="s1"> is indicated as a float, it represents the fraction of training instances &#39;</span>
<span class="sa">f</span><span class="s1">&#39;to be used for validation, and must thus be in the range (0,1)&#39;</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="p">(</span><span class="sa">f</span><span class="s1">&#39;when </span><span class="si">{</span><span class="n">val_split</span><span class="si">=}</span><span class="s1"> is indicated as a float (the fraction of training instances &#39;</span>
<span class="sa">f</span><span class="s1">&#39;to be used for validation), the parameter </span><span class="si">{</span><span class="n">fit_classifier</span><span class="si">=}</span><span class="s1"> must be True&#39;</span><span class="p">)</span>
<span class="c1"># val_split is indicated as a validation collection (X,y)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">val_split</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
<span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">val_split</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">,</span> \
<span class="p">(</span><span class="sa">f</span><span class="s1">&#39;when </span><span class="si">{</span><span class="n">val_split</span><span class="si">=}</span><span class="s1"> is indicated as a tuple, it represents the collection (X,y) on which the &#39;</span>
<span class="sa">f</span><span class="s1">&#39;validation must be performed, but this seems to have different cardinality&#39;</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">val_split</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;unexpected type for </span><span class="si">{</span><span class="n">val_split</span><span class="si">=}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="c1"># classifier is fitted?</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">check_is_fitted</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="p">)</span>
<span class="n">fitted</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">except</span> <span class="n">NotFittedError</span><span class="p">:</span>
<span class="n">fitted</span> <span class="o">=</span> <span class="kc">False</span>
<span class="c1"># consistency checks: fit_classifier?</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span><span class="p">:</span>
<span class="k">if</span> <span class="n">fitted</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">RuntimeWarning</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;the classifier is already fitted, but </span><span class="si">{</span><span class="n">fit_classifier</span><span class="si">=}</span><span class="s1"> was requested&#39;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">assert</span> <span class="n">fitted</span><span class="p">,</span> <span class="p">(</span><span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">fit_classifier</span><span class="si">=}</span><span class="s1"> requires the classifier to be already trained, &#39;</span>
<span class="sa">f</span><span class="s1">&#39;but this does not seem to be&#39;</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_check_init_parameters</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Implements any check to be performed in the parameters of the init method before undertaking</span>
<span class="sd"> the training of the quantifier. This is made as to allow for a quick execution stop when the</span>
<span class="sd"> parameters are not valid.</span>
<span class="sd"> :return: Nothing. May raise an exception.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_check_non_empty_classes</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Asserts all classes have positive instances.</span>
<span class="sd"> :param labels: array-like of shape `(n_instances,)` with the label for each instance</span>
<span class="sd"> :param classes: the class labels. This is needed in order to correctly compute the prevalence vector even when</span>
<span class="sd"> some classes have no examples.</span>
<span class="sd"> :return: Nothing. May raise an exception.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">sample_prevs</span> <span class="o">=</span> <span class="n">F</span><span class="o">.</span><span class="n">prevalence_from_labels</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">)</span>
<span class="n">empty_classes</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">argwhere</span><span class="p">(</span><span class="n">sample_prevs</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">flatten</span><span class="p">()</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">empty_classes</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">empty_class_names</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">[</span><span class="n">empty_classes</span><span class="p">]</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;classes </span><span class="si">{</span><span class="n">empty_class_names</span><span class="si">}</span><span class="s1"> have no training examples&#39;</span><span class="p">)</span>
<div class="viewcode-block" id="AggregativeQuantifier.fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeQuantifier.fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Trains the aggregative quantifier. This comes down to training a classifier (if requested) and an</span>
<span class="sd"> aggregation function.</span>
<span class="sd"> :param X: array-like of shape `(n_samples, n_features)`, the training instances</span>
<span class="sd"> :param y: array-like of shape `(n_samples,)`, the labels</span>
<span class="sd"> :return: self</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_check_init_parameters</span><span class="p">()</span>
<span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">classifier_fit_predict</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">aggregation_fit</span><span class="p">(</span><span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span></div>
<div class="viewcode-block" id="AggregativeQuantifier.classifier_fit_predict">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeQuantifier.classifier_fit_predict">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">classifier_fit_predict</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Trains the classifier if requested (`fit_classifier=True`) and generate the necessary predictions to</span>
<span class="sd"> train the aggregation function.</span>
<span class="sd"> :param X: array-like of shape `(n_samples, n_features)`, the training instances</span>
<span class="sd"> :param y: array-like of shape `(n_samples,)`, the labels</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_check_classifier</span><span class="p">(</span><span class="n">adapt_if_necessary</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span><span class="p">)</span>
<span class="c1"># self._check_non_empty_classes(y)</span>
<span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">val_split</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span><span class="p">,</span> <span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="si">}</span><span class="s1">: unexpected value for </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span><span class="si">=}</span><span class="s1">&#39;</span>
<span class="n">num_folds</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">val_split</span>
<span class="n">n_jobs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">&#39;n_jobs&#39;</span><span class="p">)</span> <span class="k">else</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_njobs</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
<span class="n">predictions</span> <span class="o">=</span> <span class="n">cross_val_predict</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">cv</span><span class="o">=</span><span class="n">num_folds</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="n">n_jobs</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_classifier_method</span><span class="p">()</span>
<span class="p">)</span>
<span class="n">labels</span> <span class="o">=</span> <span class="n">y</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">val_split</span><span class="p">,</span> <span class="nb">float</span><span class="p">):</span>
<span class="k">assert</span> <span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span><span class="p">,</span> <span class="sa">f</span><span class="s1">&#39;unexpected value for </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span><span class="si">=}</span><span class="s1">&#39;</span>
<span class="n">train_prop</span> <span class="o">=</span> <span class="mf">1.</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">val_split</span>
<span class="n">Xtr</span><span class="p">,</span> <span class="n">Xval</span><span class="p">,</span> <span class="n">ytr</span><span class="p">,</span> <span class="n">yval</span> <span class="o">=</span> <span class="n">train_test_split</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">train_size</span><span class="o">=</span><span class="n">train_prop</span><span class="p">,</span> <span class="n">stratify</span><span class="o">=</span><span class="n">y</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">Xtr</span><span class="p">,</span> <span class="n">ytr</span><span class="p">)</span>
<span class="n">predictions</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">classify</span><span class="p">(</span><span class="n">Xval</span><span class="p">)</span>
<span class="n">labels</span> <span class="o">=</span> <span class="n">yval</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">val_split</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
<span class="n">Xval</span><span class="p">,</span> <span class="n">yval</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">val_split</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="n">predictions</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">classify</span><span class="p">(</span><span class="n">Xval</span><span class="p">)</span>
<span class="n">labels</span> <span class="o">=</span> <span class="n">yval</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">val_split</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">classify</span><span class="p">(</span><span class="n">X</span><span class="p">),</span> <span class="n">y</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;unexpected type for </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">val_split</span><span class="si">=}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span></div>
<div class="viewcode-block" id="AggregativeQuantifier.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeQuantifier.aggregation_fit">[docs]</a>
<span class="nd">@abstractmethod</span>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Trains the aggregation function.</span>
<span class="sd"> :param classif_predictions: array-like with the classification predictions</span>
<span class="sd"> (whatever the method :meth:`classify` returns)</span>
<span class="sd"> :param labels: array-like with the true labels associated to each classifier prediction</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="o">...</span></div>
<span class="nd">@property</span>
<span class="k">def</span><span class="w"> </span><span class="nf">classifier</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Gives access to the classifier</span>
<span class="sd"> :return: the classifier (typically an sklearn&#39;s Estimator)</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">classifier_</span>
<span class="nd">@classifier</span><span class="o">.</span><span class="n">setter</span>
<span class="k">def</span><span class="w"> </span><span class="nf">classifier</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Setter for the classifier</span>
<span class="sd"> :param classifier: the classifier</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classifier_</span> <span class="o">=</span> <span class="n">classifier</span>
<div class="viewcode-block" id="AggregativeQuantifier.classify">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeQuantifier.classify">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">classify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Provides the label predictions for the given instances. The predictions should respect the format expected by</span>
<span class="sd"> :meth:`aggregate`, e.g., posterior probabilities for probabilistic quantifiers, or crisp predictions for</span>
<span class="sd"> non-probabilistic quantifiers. The default one is &quot;decision_function&quot;.</span>
<span class="sd"> :param X: array-like of shape `(n_samples, n_features)`, the data instances</span>
<span class="sd"> :return: np.ndarray of shape `(n_instances,)` with classifier predictions</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_classifier_method</span><span class="p">())(</span><span class="n">X</span><span class="p">)</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_classifier_method</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Name of the method that must be used for issuing label predictions. The default one is &quot;decision_function&quot;.</span>
<span class="sd"> :return: string</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="s1">&#39;decision_function&#39;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_check_classifier</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">adapt_if_necessary</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Guarantees that the underlying classifier implements the method required for issuing predictions, i.e.,</span>
<span class="sd"> the method indicated by the :meth:`_classifier_method`</span>
<span class="sd"> :param adapt_if_necessary: unused unless overridden</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">assert</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_classifier_method</span><span class="p">()),</span> \
<span class="sa">f</span><span class="s2">&quot;the method does not implement the required </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">_classifier_method</span><span class="p">()</span><span class="si">}</span><span class="s2"> method&quot;</span>
<div class="viewcode-block" id="AggregativeQuantifier.predict">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeQuantifier.predict">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">predict</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Generate class prevalence estimates for the sample&#39;s instances by aggregating the label predictions generated</span>
<span class="sd"> by the classifier.</span>
<span class="sd"> :param X: array-like of shape `(n_samples, n_features)`, the data instances</span>
<span class="sd"> :return: `np.ndarray` of shape `(n_classes)` with class prevalence estimates.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">classif_predictions</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">classify</span><span class="p">(</span><span class="n">X</span><span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">aggregate</span><span class="p">(</span><span class="n">classif_predictions</span><span class="p">)</span></div>
<div class="viewcode-block" id="AggregativeQuantifier.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeQuantifier.aggregate">[docs]</a>
<span class="nd">@abstractmethod</span>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">:</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Implements the aggregation of the classifier predictions.</span>
<span class="sd"> :param classif_predictions: `np.ndarray` of classifier predictions</span>
<span class="sd"> :return: `np.ndarray` of shape `(n_classes,)` with class prevalence estimates.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="o">...</span></div>
<span class="nd">@property</span>
<span class="k">def</span><span class="w"> </span><span class="nf">classes_</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Class labels, in the same order in which class prevalence values are to be computed.</span>
<span class="sd"> This default implementation actually returns the class labels of the learner.</span>
<span class="sd"> :return: array-like, the class labels</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">classes_</span></div>
<div class="viewcode-block" id="AggregativeCrispQuantifier">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeCrispQuantifier">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">AggregativeCrispQuantifier</span><span class="p">(</span><span class="n">AggregativeQuantifier</span><span class="p">,</span> <span class="n">ABC</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Abstract class for quantification methods that base their estimations on the aggregation of crisp decisions</span>
<span class="sd"> as returned by a hard classifier. Aggregative crisp quantifiers thus extend Aggregative</span>
<span class="sd"> Quantifiers by implementing specifications about crisp predictions.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_classifier_method</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Name of the method that must be used for issuing label predictions. For crisp quantifiers, the method</span>
<span class="sd"> is &#39;predict&#39;, that returns an array of shape `(n_instances,)` of label predictions.</span>
<span class="sd"> :return: the string &quot;predict&quot;, i.e., the standard method name for scikit-learn hard predictions</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="s1">&#39;predict&#39;</span></div>
<div class="viewcode-block" id="AggregativeSoftQuantifier">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeSoftQuantifier">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">AggregativeSoftQuantifier</span><span class="p">(</span><span class="n">AggregativeQuantifier</span><span class="p">,</span> <span class="n">ABC</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Abstract class for quantification methods that base their estimations on the aggregation of posterior</span>
<span class="sd"> probabilities as returned by a probabilistic classifier.</span>
<span class="sd"> Aggregative soft quantifiers thus extend Aggregative Quantifiers by implementing specifications</span>
<span class="sd"> about soft predictions.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_classifier_method</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Name of the method that must be used for issuing label predictions. For probabilistic quantifiers, the method</span>
<span class="sd"> is &#39;predict_proba&#39;, that returns an array of shape `(n_instances, n_dimensions,)` with posterior</span>
<span class="sd"> probabilities.</span>
<span class="sd"> :return: the string &quot;predict_proba&quot;, i.e., the standard method name for scikit-learn soft predictions</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="s1">&#39;predict_proba&#39;</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_check_classifier</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">adapt_if_necessary</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Guarantees that the underlying classifier implements the method indicated by the :meth:`_classifier_method`.</span>
<span class="sd"> In case it does not, the classifier is calibrated (by means of the Platt&#39;s calibration method implemented by</span>
<span class="sd"> scikit-learn in CalibratedClassifierCV, with cv=5). This calibration is only allowed if `adapt_if_necessary`</span>
<span class="sd"> is set to True. If otherwise (i.e., the classifier is not probabilistic, and `adapt_if_necessary` is set</span>
<span class="sd"> to False), an exception will be raised.</span>
<span class="sd"> :param adapt_if_necessary: a hard classifier is turned into a soft classifier if `adapt_if_necessary==True`</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_classifier_method</span><span class="p">()):</span>
<span class="k">if</span> <span class="n">adapt_if_necessary</span><span class="p">:</span>
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;The learner </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s1"> does not seem to be &#39;</span>
<span class="sa">f</span><span class="s1">&#39;probabilistic. The learner will be calibrated (using CalibratedClassifierCV).&#39;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classifier</span> <span class="o">=</span> <span class="n">CalibratedClassifierCV</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="p">,</span> <span class="n">cv</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">AssertionError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;error: The learner </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s1"> does not &#39;</span>
<span class="sa">f</span><span class="s1">&#39;seem to be probabilistic. The learner cannot be calibrated since &#39;</span>
<span class="sa">f</span><span class="s1">&#39;fit_classifier is set to False&#39;</span><span class="p">)</span></div>
<div class="viewcode-block" id="BinaryAggregativeQuantifier">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.BinaryAggregativeQuantifier">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">BinaryAggregativeQuantifier</span><span class="p">(</span><span class="n">AggregativeQuantifier</span><span class="p">,</span> <span class="n">BinaryQuantifier</span><span class="p">):</span>
<span class="nd">@property</span>
<span class="k">def</span><span class="w"> </span><span class="nf">pos_label</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">classes_</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="nd">@property</span>
<span class="k">def</span><span class="w"> </span><span class="nf">neg_label</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">classes_</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<div class="viewcode-block" id="BinaryAggregativeQuantifier.fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.BinaryAggregativeQuantifier.fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_check_binary</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span></div>
</div>
<span class="c1"># Methods</span>
<span class="c1"># ------------------------------------</span>
<div class="viewcode-block" id="CC">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.CC">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">CC</span><span class="p">(</span><span class="n">AggregativeCrispQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `Classify &amp; Count` (CC), the most basic quantification method, one that</span>
<span class="sd"> simply classifies all instances and counts how many have been attributed to</span>
<span class="sd"> each class in order to compute class prevalence estimates. This baseline is</span>
<span class="sd"> the unadjusted estimator discussed, among others, in</span>
<span class="sd"> `Forman, G. (2008). Quantifying counts and costs via classification.</span>
<span class="sd"> Data Mining and Knowledge Discovery, 17, 164-206</span>
<span class="sd"> &lt;https://link.springer.com/article/10.1007/s10618-008-0097-y&gt;`_.</span>
<span class="sd"> :param classifier: a sklearn&#39;s Estimator that generates a classifier</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
<div class="viewcode-block" id="CC.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.CC.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Nothing to do here!</span>
<span class="sd"> :param classif_predictions: unused</span>
<span class="sd"> :param labels: unused</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="CC.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.CC.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">:</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Computes class prevalence estimates by counting the prevalence of each of the predicted labels.</span>
<span class="sd"> :param classif_predictions: array-like with classifier predictions</span>
<span class="sd"> :return: `np.ndarray` of shape `(n_classes,)` with class prevalence estimates.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">prevalence_from_labels</span><span class="p">(</span><span class="n">classif_predictions</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">)</span></div>
</div>
<div class="viewcode-block" id="PCC">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.PCC">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">PCC</span><span class="p">(</span><span class="n">AggregativeSoftQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `Probabilistic Classify &amp; Count` (PCC), the probabilistic variant of CC</span>
<span class="sd"> that relies on the posterior probabilities returned by a probabilistic</span>
<span class="sd"> classifier, introduced in</span>
<span class="sd"> `Bella, A., Ferri, C., Hernández-Orallo, J., and Ramírez-Quintana, M.J.</span>
<span class="sd"> (2010). Quantification via probability estimators. In Proceedings of the</span>
<span class="sd"> 2010 IEEE International Conference on Data Mining (ICDM 2010)</span>
<span class="sd"> &lt;https://ieeexplore.ieee.org/abstract/document/5694031&gt;`_.</span>
<span class="sd"> :param classifier: a sklearn&#39;s Estimator that generates a classifier</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="n">val_split</span><span class="p">)</span>
<div class="viewcode-block" id="PCC.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.PCC.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Nothing to do here!</span>
<span class="sd"> :param classif_predictions: unused</span>
<span class="sd"> :param labels: unused</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="PCC.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.PCC.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_posteriors</span><span class="p">):</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">prevalence_from_probabilities</span><span class="p">(</span><span class="n">classif_posteriors</span><span class="p">,</span> <span class="n">binarize</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span></div>
</div>
<div class="viewcode-block" id="ACC">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.ACC">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">ACC</span><span class="p">(</span><span class="n">AggregativeCrispQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `Adjusted Classify &amp; Count` (ACC), the &quot;adjusted&quot; variant of :class:`CC`</span>
<span class="sd"> that corrects the predictions of CC according to the</span>
<span class="sd"> misclassification rates, originally proposed in</span>
<span class="sd"> `Forman, G. (2008). Quantifying counts and costs via classification.</span>
<span class="sd"> Data Mining and Knowledge Discovery, 17, 164-206</span>
<span class="sd"> &lt;https://link.springer.com/article/10.1007/s10618-008-0097-y&gt;`_.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set to False if the</span>
<span class="sd"> learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier predictions. This specification</span>
<span class="sd"> can be made as float in (0, 1) indicating the proportion of stratified held-out validation set to</span>
<span class="sd"> be extracted from the training set; or as an integer (default 5), indicating that the predictions</span>
<span class="sd"> are to be generated in a `k`-fold cross-validation manner (with this integer indicating the value</span>
<span class="sd"> for `k`); or as a tuple (X,y) defining the specific set of data to use for validation.</span>
<span class="sd"> :param str method: adjustment method to be used:</span>
<span class="sd"> * &#39;inversion&#39;: matrix inversion method based on the matrix equality :math:`P(C)=P(C|Y)P(Y)`,</span>
<span class="sd"> which tries to invert :math:`P(C|Y)` matrix.</span>
<span class="sd"> * &#39;invariant-ratio&#39;: invariant ratio estimator of `Vaz et al. 2018 &lt;https://jmlr.org/papers/v20/18-456.html&gt;`_,</span>
<span class="sd"> which replaces the last equation with the normalization condition.</span>
<span class="sd"> :param str solver: indicates the method to use for solving the system of linear equations. Valid options are:</span>
<span class="sd"> * &#39;exact-raise&#39;: tries to solve the system using matrix inversion. Raises an error if the matrix has rank</span>
<span class="sd"> strictly less than `n_classes`.</span>
<span class="sd"> * &#39;exact-cc&#39;: if the matrix is not of full rank, returns `p_c` as the estimates, which corresponds to</span>
<span class="sd"> no adjustment (i.e., the classify and count method. See :class:`quapy.method.aggregative.CC`)</span>
<span class="sd"> * &#39;exact&#39;: deprecated, defaults to &#39;exact-cc&#39;</span>
<span class="sd"> * &#39;minimize&#39;: minimizes the L2 norm of :math:`|Ax-B|`. This one generally works better, and is the</span>
<span class="sd"> default parameter. More details about this can be consulted in `Bunse, M. &quot;On Multi-Class Extensions of</span>
<span class="sd"> Adjusted Classify and Count&quot;, on proceedings of the 2nd International Workshop on Learning to Quantify:</span>
<span class="sd"> Methods and Applications (LQ 2022), ECML/PKDD 2022, Grenoble (France)</span>
<span class="sd"> &lt;https://lq-2022.github.io/proceedings/CompleteVolume.pdf&gt;`_.</span>
<span class="sd"> :param str norm: the method to use for normalization.</span>
<span class="sd"> * `clip`, the values are clipped to the range [0,1] and then L1-normalized.</span>
<span class="sd"> * `mapsimplex` projects vectors onto the probability simplex. This implementation relies on</span>
<span class="sd"> `Mathieu Blondel&#39;s projection_simplex_sort &lt;https://gist.github.com/mblondel/6f3b7aaad90606b98f71&gt;`_</span>
<span class="sd"> * `condsoftmax`, applies a softmax normalization only to prevalence vectors that lie outside the simplex</span>
<span class="sd"> :param n_jobs: number of parallel workers</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="n">fit_classifier</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
<span class="n">val_split</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span>
<span class="n">solver</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s1">&#39;minimize&#39;</span><span class="p">,</span> <span class="s1">&#39;exact&#39;</span><span class="p">,</span> <span class="s1">&#39;exact-raise&#39;</span><span class="p">,</span> <span class="s1">&#39;exact-cc&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;minimize&#39;</span><span class="p">,</span>
<span class="n">method</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s1">&#39;inversion&#39;</span><span class="p">,</span> <span class="s1">&#39;invariant-ratio&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;inversion&#39;</span><span class="p">,</span>
<span class="n">norm</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s1">&#39;clip&#39;</span><span class="p">,</span> <span class="s1">&#39;mapsimplex&#39;</span><span class="p">,</span> <span class="s1">&#39;condsoftmax&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;clip&#39;</span><span class="p">,</span>
<span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_njobs</span><span class="p">(</span><span class="n">n_jobs</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">solver</span> <span class="o">=</span> <span class="n">solver</span>
<span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="o">=</span> <span class="n">method</span>
<span class="bp">self</span><span class="o">.</span><span class="n">norm</span> <span class="o">=</span> <span class="n">norm</span>
<span class="n">SOLVERS</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;exact&#39;</span><span class="p">,</span> <span class="s1">&#39;minimize&#39;</span><span class="p">,</span> <span class="s1">&#39;exact-raise&#39;</span><span class="p">,</span> <span class="s1">&#39;exact-cc&#39;</span><span class="p">]</span>
<span class="n">METHODS</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;inversion&#39;</span><span class="p">,</span> <span class="s1">&#39;invariant-ratio&#39;</span><span class="p">]</span>
<span class="n">NORMALIZATIONS</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;clip&#39;</span><span class="p">,</span> <span class="s1">&#39;mapsimplex&#39;</span><span class="p">,</span> <span class="s1">&#39;condsoftmax&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">]</span>
<div class="viewcode-block" id="ACC.newInvariantRatioEstimation">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.ACC.newInvariantRatioEstimation">[docs]</a>
<span class="nd">@classmethod</span>
<span class="k">def</span><span class="w"> </span><span class="nf">newInvariantRatioEstimation</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Constructs a quantifier that implements the Invariant Ratio Estimator of</span>
<span class="sd"> `Vaz et al. 2018 &lt;https://jmlr.org/papers/v20/18-456.html&gt;`_. This amounts</span>
<span class="sd"> to setting method to &#39;invariant-ratio&#39; and clipping to &#39;project&#39;.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set to False if the</span>
<span class="sd"> learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier predictions. This specification</span>
<span class="sd"> can be made as float in (0, 1) indicating the proportion of stratified held-out validation set to</span>
<span class="sd"> be extracted from the training set; or as an integer (default 5), indicating that the predictions</span>
<span class="sd"> are to be generated in a `k`-fold cross-validation manner (with this integer indicating the value</span>
<span class="sd"> for `k`); or as a tuple (X,y) defining the specific set of data to use for validation.</span>
<span class="sd"> :param n_jobs: number of parallel workers</span>
<span class="sd"> :return: an instance of ACC configured so that it implements the Invariant Ratio Estimator</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">ACC</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="n">val_split</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s1">&#39;invariant-ratio&#39;</span><span class="p">,</span> <span class="n">norm</span><span class="o">=</span><span class="s1">&#39;mapsimplex&#39;</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="n">n_jobs</span><span class="p">)</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_check_init_parameters</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">solver</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">ACC</span><span class="o">.</span><span class="n">SOLVERS</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;unknown solver; valid ones are </span><span class="si">{</span><span class="n">ACC</span><span class="o">.</span><span class="n">SOLVERS</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">ACC</span><span class="o">.</span><span class="n">METHODS</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;unknown method; valid ones are </span><span class="si">{</span><span class="n">ACC</span><span class="o">.</span><span class="n">METHODS</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">norm</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">ACC</span><span class="o">.</span><span class="n">NORMALIZATIONS</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;unknown normalization; valid ones are </span><span class="si">{</span><span class="n">ACC</span><span class="o">.</span><span class="n">NORMALIZATIONS</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<div class="viewcode-block" id="ACC.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.ACC.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Estimates the misclassification rates.</span>
<span class="sd"> :param classif_predictions: array-like with the predicted labels</span>
<span class="sd"> :param labels: array-like with the true labels associated to each predicted label</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">true_labels</span> <span class="o">=</span> <span class="n">labels</span>
<span class="n">pred_labels</span> <span class="o">=</span> <span class="n">classif_predictions</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cc</span> <span class="o">=</span> <span class="n">CC</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pte_cond_estim_</span> <span class="o">=</span> <span class="n">ACC</span><span class="o">.</span><span class="n">getPteCondEstim</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">classes_</span><span class="p">,</span> <span class="n">true_labels</span><span class="p">,</span> <span class="n">pred_labels</span><span class="p">)</span></div>
<div class="viewcode-block" id="ACC.getPteCondEstim">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.ACC.getPteCondEstim">[docs]</a>
<span class="nd">@classmethod</span>
<span class="k">def</span><span class="w"> </span><span class="nf">getPteCondEstim</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">classes</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">y_</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Estimate the matrix with entry (i,j) being the estimate of P(hat_yi|yj), that is, the probability that a</span>
<span class="sd"> document that belongs to yj ends up being classified as belonging to yi</span>
<span class="sd"> :param classes: array-like with the class names</span>
<span class="sd"> :param y: array-like with the true labels</span>
<span class="sd"> :param y_: array-like with the estimated labels</span>
<span class="sd"> :return: np.ndarray</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">conf</span> <span class="o">=</span> <span class="n">confusion_matrix</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">y_</span><span class="p">,</span> <span class="n">labels</span><span class="o">=</span><span class="n">classes</span><span class="p">)</span><span class="o">.</span><span class="n">T</span>
<span class="n">conf</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">astype</span><span class="p">(</span><span class="nb">float</span><span class="p">)</span>
<span class="n">class_counts</span> <span class="o">=</span> <span class="n">conf</span><span class="o">.</span><span class="n">sum</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">classes</span><span class="p">):</span>
<span class="k">if</span> <span class="n">class_counts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">conf</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">conf</span><span class="p">[:,</span> <span class="n">i</span><span class="p">]</span> <span class="o">/=</span> <span class="n">class_counts</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="k">return</span> <span class="n">conf</span></div>
<div class="viewcode-block" id="ACC.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.ACC.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">):</span>
<span class="n">prevs_estim</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cc</span><span class="o">.</span><span class="n">aggregate</span><span class="p">(</span><span class="n">classif_predictions</span><span class="p">)</span>
<span class="n">estimate</span> <span class="o">=</span> <span class="n">F</span><span class="o">.</span><span class="n">solve_adjustment</span><span class="p">(</span>
<span class="n">class_conditional_rates</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">Pte_cond_estim_</span><span class="p">,</span>
<span class="n">unadjusted_counts</span><span class="o">=</span><span class="n">prevs_estim</span><span class="p">,</span>
<span class="n">solver</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">solver</span><span class="p">,</span>
<span class="n">method</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">method</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">normalize_prevalence</span><span class="p">(</span><span class="n">estimate</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">norm</span><span class="p">)</span></div>
</div>
<div class="viewcode-block" id="PACC">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.PACC">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">PACC</span><span class="p">(</span><span class="n">AggregativeSoftQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `Probabilistic Adjusted Classify &amp; Count` (PACC), the probabilistic</span>
<span class="sd"> variant of ACC that relies on the posterior probabilities returned by a</span>
<span class="sd"> probabilistic classifier, introduced in</span>
<span class="sd"> `Bella, A., Ferri, C., Hernández-Orallo, J., and Ramírez-Quintana, M.J.</span>
<span class="sd"> (2010). Quantification via probability estimators. In Proceedings of the</span>
<span class="sd"> 2010 IEEE International Conference on Data Mining (ICDM 2010)</span>
<span class="sd"> &lt;https://ieeexplore.ieee.org/abstract/document/5694031&gt;`_.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set to False if the</span>
<span class="sd"> learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier predictions. This specification</span>
<span class="sd"> can be made as float in (0, 1) indicating the proportion of stratified held-out validation set to</span>
<span class="sd"> be extracted from the training set; or as an integer (default 5), indicating that the predictions</span>
<span class="sd"> are to be generated in a `k`-fold cross-validation manner (with this integer indicating the value</span>
<span class="sd"> for `k`); or as a tuple (X,y) defining the specific set of data to use for validation.</span>
<span class="sd"> :param str method: adjustment method to be used:</span>
<span class="sd"> * &#39;inversion&#39;: matrix inversion method based on the matrix equality :math:`P(C)=P(C|Y)P(Y)`,</span>
<span class="sd"> which tries to invert `P(C|Y)` matrix.</span>
<span class="sd"> * &#39;invariant-ratio&#39;: invariant ratio estimator of `Vaz et al. &lt;https://jmlr.org/papers/v20/18-456.html&gt;`_,</span>
<span class="sd"> which replaces the last equation with the normalization condition.</span>
<span class="sd"> :param str solver: the method to use for solving the system of linear equations. Valid options are:</span>
<span class="sd"> * &#39;exact-raise&#39;: tries to solve the system using matrix inversion.</span>
<span class="sd"> Raises an error if the matrix has rank strictly less than `n_classes`.</span>
<span class="sd"> * &#39;exact-cc&#39;: if the matrix is not of full rank, returns `p_c` as the estimates, which</span>
<span class="sd"> corresponds to no adjustment (i.e., the classify and count method. See :class:`quapy.method.aggregative.CC`)</span>
<span class="sd"> * &#39;exact&#39;: deprecated, defaults to &#39;exact-cc&#39;</span>
<span class="sd"> * &#39;minimize&#39;: minimizes the L2 norm of :math:`|Ax-B|`. This one generally works better, and is the</span>
<span class="sd"> default parameter. More details about this can be consulted in `Bunse, M. &quot;On Multi-Class Extensions</span>
<span class="sd"> of Adjusted Classify and Count&quot;, on proceedings of the 2nd International Workshop on Learning to</span>
<span class="sd"> Quantify: Methods and Applications (LQ 2022), ECML/PKDD 2022, Grenoble (France)</span>
<span class="sd"> &lt;https://lq-2022.github.io/proceedings/CompleteVolume.pdf&gt;`_.</span>
<span class="sd"> :param str norm: the method to use for normalization.</span>
<span class="sd"> * `clip`, the values are clipped to the range [0,1] and then L1-normalized.</span>
<span class="sd"> * `mapsimplex` projects vectors onto the probability simplex. This implementation relies on</span>
<span class="sd"> `Mathieu Blondel&#39;s projection_simplex_sort &lt;https://gist.github.com/mblondel/6f3b7aaad90606b98f71&gt;`_</span>
<span class="sd"> * `condsoftmax`, applies a softmax normalization only to prevalence vectors that lie outside the simplex</span>
<span class="sd"> :param n_jobs: number of parallel workers</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span>
<span class="n">solver</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s1">&#39;minimize&#39;</span><span class="p">,</span> <span class="s1">&#39;exact&#39;</span><span class="p">,</span> <span class="s1">&#39;exact-raise&#39;</span><span class="p">,</span> <span class="s1">&#39;exact-cc&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;minimize&#39;</span><span class="p">,</span>
<span class="n">method</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s1">&#39;inversion&#39;</span><span class="p">,</span> <span class="s1">&#39;invariant-ratio&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;inversion&#39;</span><span class="p">,</span>
<span class="n">norm</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s1">&#39;clip&#39;</span><span class="p">,</span> <span class="s1">&#39;mapsimplex&#39;</span><span class="p">,</span> <span class="s1">&#39;condsoftmax&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;clip&#39;</span><span class="p">,</span>
<span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span>
<span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_njobs</span><span class="p">(</span><span class="n">n_jobs</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">solver</span> <span class="o">=</span> <span class="n">solver</span>
<span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="o">=</span> <span class="n">method</span>
<span class="bp">self</span><span class="o">.</span><span class="n">norm</span> <span class="o">=</span> <span class="n">norm</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_check_init_parameters</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">solver</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">ACC</span><span class="o">.</span><span class="n">SOLVERS</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;unknown solver; valid ones are </span><span class="si">{</span><span class="n">ACC</span><span class="o">.</span><span class="n">SOLVERS</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">method</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">ACC</span><span class="o">.</span><span class="n">METHODS</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;unknown method; valid ones are </span><span class="si">{</span><span class="n">ACC</span><span class="o">.</span><span class="n">METHODS</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">norm</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">ACC</span><span class="o">.</span><span class="n">NORMALIZATIONS</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;unknown normalization; valid ones are </span><span class="si">{</span><span class="n">ACC</span><span class="o">.</span><span class="n">NORMALIZATIONS</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<div class="viewcode-block" id="PACC.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.PACC.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Estimates the misclassification rates</span>
<span class="sd"> :param classif_predictions: array-like with posterior probabilities</span>
<span class="sd"> :param labels: array-like with the true labels associated to each vector of posterior probabilities</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">posteriors</span> <span class="o">=</span> <span class="n">classif_predictions</span>
<span class="n">true_labels</span> <span class="o">=</span> <span class="n">labels</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pcc</span> <span class="o">=</span> <span class="n">PCC</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pte_cond_estim_</span> <span class="o">=</span> <span class="n">PACC</span><span class="o">.</span><span class="n">getPteCondEstim</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">classes_</span><span class="p">,</span> <span class="n">true_labels</span><span class="p">,</span> <span class="n">posteriors</span><span class="p">)</span></div>
<div class="viewcode-block" id="PACC.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.PACC.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_posteriors</span><span class="p">):</span>
<span class="n">prevs_estim</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pcc</span><span class="o">.</span><span class="n">aggregate</span><span class="p">(</span><span class="n">classif_posteriors</span><span class="p">)</span>
<span class="n">estimate</span> <span class="o">=</span> <span class="n">F</span><span class="o">.</span><span class="n">solve_adjustment</span><span class="p">(</span>
<span class="n">class_conditional_rates</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">Pte_cond_estim_</span><span class="p">,</span>
<span class="n">unadjusted_counts</span><span class="o">=</span><span class="n">prevs_estim</span><span class="p">,</span>
<span class="n">solver</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">solver</span><span class="p">,</span>
<span class="n">method</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">method</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">normalize_prevalence</span><span class="p">(</span><span class="n">estimate</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">norm</span><span class="p">)</span></div>
<div class="viewcode-block" id="PACC.getPteCondEstim">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.PACC.getPteCondEstim">[docs]</a>
<span class="nd">@classmethod</span>
<span class="k">def</span><span class="w"> </span><span class="nf">getPteCondEstim</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">classes</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">y_</span><span class="p">):</span>
<span class="c1"># estimate the matrix with entry (i,j) being the estimate of P(hat_yi|yj), that is, the probability that a</span>
<span class="c1"># document that belongs to yj ends up being classified as belonging to yi</span>
<span class="n">n_classes</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">classes</span><span class="p">)</span>
<span class="n">confusion</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">eye</span><span class="p">(</span><span class="n">n_classes</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">class_</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">classes</span><span class="p">):</span>
<span class="n">idx</span> <span class="o">=</span> <span class="n">y</span> <span class="o">==</span> <span class="n">class_</span>
<span class="k">if</span> <span class="n">idx</span><span class="o">.</span><span class="n">any</span><span class="p">():</span>
<span class="n">confusion</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">y_</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="k">return</span> <span class="n">confusion</span><span class="o">.</span><span class="n">T</span></div>
</div>
<div class="viewcode-block" id="RLLS">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.RLLS">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">RLLS</span><span class="p">(</span><span class="n">AggregativeSoftQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `Regularized Learning for Domain Adaptation under Label Shifts</span>
<span class="sd"> &lt;https://arxiv.org/abs/1903.09734&gt;`_, used here as an aggregative</span>
<span class="sd"> quantifier.</span>
<span class="sd"> This implementation ports the regularized weight-estimation component of</span>
<span class="sd"> RLLS to QuaPy&#39;s aggregative interface. It estimates label-shift ratios from</span>
<span class="sd"> validation posteriors and source labels, then rescales the source</span>
<span class="sd"> prevalence to obtain target prevalence estimates.</span>
<span class="sd"> This method relies on the optional `cvxpy` dependency.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case</span>
<span class="sd"> the classifier is taken to be the one indicated in</span>
<span class="sd"> `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set</span>
<span class="sd"> to False if the learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier</span>
<span class="sd"> predictions. This specification can be made as float in (0, 1)</span>
<span class="sd"> indicating the proportion of stratified held-out validation set to be</span>
<span class="sd"> extracted from the training set; or as an integer (default 5),</span>
<span class="sd"> indicating that the predictions are to be generated in a `k`-fold</span>
<span class="sd"> cross-validation manner; or as a tuple `(X, y)` defining the specific</span>
<span class="sd"> set of data to use for validation. This method requires source</span>
<span class="sd"> predictions and therefore needs `val_split` whenever</span>
<span class="sd"> `fit_classifier=True`.</span>
<span class="sd"> :param mode: whether source- and target-domain quantities are estimated</span>
<span class="sd"> from posterior probabilities (`soft`, default) or from argmax</span>
<span class="sd"> predictions (`hard`)</span>
<span class="sd"> :param alpha: multiplicative factor for the regularization level (default</span>
<span class="sd"> 0.01)</span>
<span class="sd"> :param delta: confidence parameter used in the finite-sample regularizer</span>
<span class="sd"> (default 0.05)</span>
<span class="sd"> :param clip_weights: if True, clips negative importance weights to zero</span>
<span class="sd"> before converting them into prevalence estimates</span>
<span class="sd"> :param norm: the normalization method passed to</span>
<span class="sd"> :func:`quapy.functional.normalize_prevalence`</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span>
<span class="n">mode</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s1">&#39;soft&#39;</span><span class="p">,</span> <span class="s1">&#39;hard&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;soft&#39;</span><span class="p">,</span>
<span class="n">alpha</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">0.01</span><span class="p">,</span>
<span class="n">delta</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">0.05</span><span class="p">,</span>
<span class="n">clip_weights</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
<span class="n">norm</span><span class="p">:</span> <span class="n">Literal</span><span class="p">[</span><span class="s1">&#39;clip&#39;</span><span class="p">,</span> <span class="s1">&#39;mapsimplex&#39;</span><span class="p">,</span> <span class="s1">&#39;condsoftmax&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;clip&#39;</span><span class="p">,</span>
<span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">mode</span> <span class="o">=</span> <span class="n">mode</span>
<span class="bp">self</span><span class="o">.</span><span class="n">alpha</span> <span class="o">=</span> <span class="n">alpha</span>
<span class="bp">self</span><span class="o">.</span><span class="n">delta</span> <span class="o">=</span> <span class="n">delta</span>
<span class="bp">self</span><span class="o">.</span><span class="n">clip_weights</span> <span class="o">=</span> <span class="n">clip_weights</span>
<span class="bp">self</span><span class="o">.</span><span class="n">norm</span> <span class="o">=</span> <span class="n">norm</span>
<span class="bp">self</span><span class="o">.</span><span class="n">last_w_</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_check_init_parameters</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">_get_cvxpy</span><span class="p">()</span>
<span class="n">_rlls_check_mode</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">mode</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">alpha</span><span class="p">,</span> <span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">))</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">alpha</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;expected a non-negative real value for alpha; found </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">alpha</span><span class="si">!r}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">delta</span><span class="p">,</span> <span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">))</span> <span class="ow">or</span> <span class="ow">not</span> <span class="p">(</span><span class="mi">0</span> <span class="o">&lt;</span> <span class="bp">self</span><span class="o">.</span><span class="n">delta</span> <span class="o">&lt;</span> <span class="mi">1</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;expected delta to be in (0,1); found </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">delta</span><span class="si">!r}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">norm</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">ACC</span><span class="o">.</span><span class="n">NORMALIZATIONS</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;unknown normalization; valid ones are </span><span class="si">{</span><span class="n">ACC</span><span class="o">.</span><span class="n">NORMALIZATIONS</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">fit_classifier</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">val_split</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
<span class="s1">&#39;RLLS requires validation predictions for aggregation_fit; &#39;</span>
<span class="s1">&#39;please set val_split to an integer, float, or validation tuple&#39;</span>
<span class="p">)</span>
<div class="viewcode-block" id="RLLS.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.RLLS.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="k">if</span> <span class="n">classif_predictions</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">labels</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">&#39;RLLS requires source posterior predictions and source labels&#39;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">train_prevalence_</span> <span class="o">=</span> <span class="n">F</span><span class="o">.</span><span class="n">prevalence_from_labels</span><span class="p">(</span><span class="n">labels</span><span class="p">,</span> <span class="n">classes</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">C_zy_</span> <span class="o">=</span> <span class="n">_rlls_joint_distribution</span><span class="p">(</span>
<span class="n">classif_predictions</span><span class="p">,</span>
<span class="n">labels</span><span class="p">,</span>
<span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">,</span>
<span class="n">mode</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">mode</span><span class="p">,</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pz_</span> <span class="o">=</span> <span class="n">_rlls_predicted_marginal</span><span class="p">(</span><span class="n">classif_predictions</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">mode</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">rho_</span> <span class="o">=</span> <span class="n">_rlls_compute_3deltaC</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">labels</span><span class="p">),</span> <span class="bp">self</span><span class="o">.</span><span class="n">delta</span><span class="p">)</span></div>
<div class="viewcode-block" id="RLLS.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.RLLS.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_posteriors</span><span class="p">):</span>
<span class="n">qz</span> <span class="o">=</span> <span class="n">_rlls_predicted_marginal</span><span class="p">(</span><span class="n">classif_posteriors</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">mode</span><span class="p">)</span>
<span class="n">w</span> <span class="o">=</span> <span class="n">_rlls_compute_weights</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">C_zy_</span><span class="p">,</span>
<span class="n">qz</span><span class="p">,</span>
<span class="bp">self</span><span class="o">.</span><span class="n">pz_</span><span class="p">,</span>
<span class="n">rho</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">alpha</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">rho_</span><span class="p">,</span>
<span class="n">clip</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">clip_weights</span><span class="p">,</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">last_w_</span> <span class="o">=</span> <span class="n">w</span>
<span class="n">estimate</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">train_prevalence_</span> <span class="o">*</span> <span class="n">w</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">normalize_prevalence</span><span class="p">(</span><span class="n">estimate</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">norm</span><span class="p">)</span></div>
</div>
<div class="viewcode-block" id="EMQ">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EMQ">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">EMQ</span><span class="p">(</span><span class="n">AggregativeSoftQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `Expectation Maximization for Quantification &lt;https://ieeexplore.ieee.org/abstract/document/6789744&gt;`_ (EMQ),</span>
<span class="sd"> aka `Saerens-Latinne-Decaestecker` (SLD) algorithm.</span>
<span class="sd"> EMQ consists of using the well-known `Expectation Maximization algorithm` to iteratively update the posterior</span>
<span class="sd"> probabilities generated by a probabilistic classifier and the class prevalence estimates obtained via</span>
<span class="sd"> maximum-likelihood estimation, in a mutually recursive way, until convergence.</span>
<span class="sd"> This implementation also gives access to the heuristics proposed by `Alexandari et al. paper</span>
<span class="sd"> &lt;http://proceedings.mlr.press/v119/alexandari20a.html&gt;`_. These heuristics consist of using, as the training</span>
<span class="sd"> prevalence, an estimate of it obtained via k-fold cross validation (instead of the true training prevalence),</span>
<span class="sd"> and to recalibrate the posterior probabilities of the classifier.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the classifier (default is True). Set to False if the</span>
<span class="sd"> given classifier has already been trained.</span>
<span class="sd"> :param val_split: specifies the data used for generating the classifier predictions on which the</span>
<span class="sd"> aggregation function is to be trained. This specification can be made as float in (0, 1) indicating</span>
<span class="sd"> the proportion of stratified held-out validation set to be extracted from the training set; or as</span>
<span class="sd"> an integer (default 5), indicating that the predictions are to be generated in a `k`-fold</span>
<span class="sd"> cross-validation manner (with this integer indicating the value for `k`); or as a tuple (X,y) defining</span>
<span class="sd"> the specific set of data to use for validation. This hyperparameter is only meant to be used when</span>
<span class="sd"> the heuristics are to be applied, i.e., if a calibration is required. The default value is None</span>
<span class="sd"> (meaning the calibration is not required). In case this hyperparameter is set to a value other than</span>
<span class="sd"> None, but the calibration is not required (calib=None), a warning message will be raised.</span>
<span class="sd"> :param exact_train_prev: set to True (default) for using the true training prevalence as the initial</span>
<span class="sd"> observation; set to False for computing the training prevalence as an estimate of it, i.e., as the</span>
<span class="sd"> expected value of the posterior probabilities of the training instances.</span>
<span class="sd"> :param calib: a string indicating the method of calibration.</span>
<span class="sd"> Available choices include &quot;nbvs&quot; (No-Bias Vector Scaling), &quot;bcts&quot; (Bias-Corrected Temperature Scaling),</span>
<span class="sd"> &quot;ts&quot; (Temperature Scaling), and &quot;vs&quot; (Vector Scaling). Default is None (no calibration).</span>
<span class="sd"> :param on_calib_error: a string indicating the policy to follow in case the calibrator fails at runtime.</span>
<span class="sd"> Options include &quot;raise&quot; (default), in which case a RuntimeException is raised; and &quot;backup&quot;, in which</span>
<span class="sd"> case the calibrator is silently skipped.</span>
<span class="sd"> :param n_jobs: number of parallel workers. Only used for recalibrating the classifier if `val_split` is set to</span>
<span class="sd"> an integer `k` --the number of folds.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">MAX_ITER</span> <span class="o">=</span> <span class="mi">1000</span>
<span class="n">EPSILON</span> <span class="o">=</span> <span class="mf">1e-4</span>
<span class="n">ON_CALIB_ERROR_VALUES</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;raise&#39;</span><span class="p">,</span> <span class="s1">&#39;backup&#39;</span><span class="p">]</span>
<span class="n">CALIB_OPTIONS</span> <span class="o">=</span> <span class="p">[</span><span class="kc">None</span><span class="p">,</span> <span class="s1">&#39;nbvs&#39;</span><span class="p">,</span> <span class="s1">&#39;bcts&#39;</span><span class="p">,</span> <span class="s1">&#39;ts&#39;</span><span class="p">,</span> <span class="s1">&#39;vs&#39;</span><span class="p">]</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">exact_train_prev</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="n">calib</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">on_calib_error</span><span class="o">=</span><span class="s1">&#39;raise&#39;</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">assert</span> <span class="n">calib</span> <span class="ow">in</span> <span class="n">EMQ</span><span class="o">.</span><span class="n">CALIB_OPTIONS</span><span class="p">,</span> \
<span class="sa">f</span><span class="s1">&#39;invalid value for </span><span class="si">{</span><span class="n">calib</span><span class="si">=}</span><span class="s1">; valid ones are </span><span class="si">{</span><span class="n">EMQ</span><span class="o">.</span><span class="n">CALIB_OPTIONS</span><span class="si">}</span><span class="s1">&#39;</span>
<span class="k">assert</span> <span class="n">on_calib_error</span> <span class="ow">in</span> <span class="n">EMQ</span><span class="o">.</span><span class="n">ON_CALIB_ERROR_VALUES</span><span class="p">,</span> \
<span class="sa">f</span><span class="s1">&#39;invalid value for </span><span class="si">{</span><span class="n">on_calib_error</span><span class="si">=}</span><span class="s1">; valid ones are </span><span class="si">{</span><span class="n">EMQ</span><span class="o">.</span><span class="n">ON_CALIB_ERROR_VALUES</span><span class="si">}</span><span class="s1">&#39;</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">exact_train_prev</span> <span class="o">=</span> <span class="n">exact_train_prev</span>
<span class="bp">self</span><span class="o">.</span><span class="n">calib</span> <span class="o">=</span> <span class="n">calib</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_calib_error</span> <span class="o">=</span> <span class="n">on_calib_error</span>
<span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_njobs</span><span class="p">(</span><span class="n">n_jobs</span><span class="p">)</span>
<div class="viewcode-block" id="EMQ.EMQ_BCTS">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EMQ.EMQ_BCTS">[docs]</a>
<span class="nd">@classmethod</span>
<span class="k">def</span><span class="w"> </span><span class="nf">EMQ_BCTS</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">on_calib_error</span><span class="o">=</span><span class="s2">&quot;raise&quot;</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Constructs an instance of EMQ using the best configuration found in the `Alexandari et al. paper</span>
<span class="sd"> &lt;http://proceedings.mlr.press/v119/alexandari20a.html&gt;`_, i.e., one that relies on Bias-Corrected Temperature</span>
<span class="sd"> Scaling (BCTS) as a calibration function, and that uses an estimate of the training prevalence instead of</span>
<span class="sd"> the true training prevalence.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set to False if the</span>
<span class="sd"> learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier predictions. This specification</span>
<span class="sd"> can be made as float in (0, 1) indicating the proportion of stratified held-out validation set to</span>
<span class="sd"> be extracted from the training set; or as an integer (default 5), indicating that the predictions</span>
<span class="sd"> are to be generated in a `k`-fold cross-validation manner (with this integer indicating the value</span>
<span class="sd"> for `k`); or as a tuple (X,y) defining the specific set of data to use for validation.</span>
<span class="sd"> :param on_calib_error: a string indicating the policy to follow in case the calibrator fails at runtime.</span>
<span class="sd"> Options include &quot;raise&quot; (default), in which case a RuntimeException is raised; and &quot;backup&quot;, in which</span>
<span class="sd"> case the calibrator is silently skipped.</span>
<span class="sd"> :param n_jobs: number of parallel workers. Only used for recalibrating the classifier if `val_split` is set to</span>
<span class="sd"> an integer `k` --the number of folds.</span>
<span class="sd"> :return: An instance of EMQ with BCTS</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">EMQ</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="n">val_split</span><span class="p">,</span> <span class="n">exact_train_prev</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">calib</span><span class="o">=</span><span class="s1">&#39;bcts&#39;</span><span class="p">,</span> <span class="n">on_calib_error</span><span class="o">=</span><span class="n">on_calib_error</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="n">n_jobs</span><span class="p">)</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_check_init_parameters</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">val_split</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">exact_train_prev</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">calib</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;The parameter </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">val_split</span><span class="si">=}</span><span class="s1"> was specified for EMQ, while the parameters &#39;</span>
<span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">exact_train_prev</span><span class="si">=}</span><span class="s1"> and </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">calib</span><span class="si">=}</span><span class="s1">. This has no effect and causes an &#39;</span>
<span class="sa">f</span><span class="s1">&#39;unnecessary overload.&#39;</span><span class="p">,</span> <span class="ne">RuntimeWarning</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">calib</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;The parameter </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">calib</span><span class="si">=}</span><span class="s1"> requires the val_split be different from None. &#39;</span>
<span class="sa">f</span><span class="s1">&#39;This parameter will be set to 5. To avoid this warning, set this value to a float value &#39;</span>
<span class="sa">f</span><span class="s1">&#39;indicating the proportion of training data to be used as validation, or to an integer &#39;</span>
<span class="sa">f</span><span class="s1">&#39;indicating the number of folds for kFCV.&#39;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">val_split</span> <span class="o">=</span> <span class="mi">5</span>
<div class="viewcode-block" id="EMQ.classify">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EMQ.classify">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">classify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Provides the posterior probabilities for the given instances. The calibration function, if required,</span>
<span class="sd"> has no effect in this step, and is only involved in the aggregate method.</span>
<span class="sd"> :param X: array-like of shape `(n_instances, n_dimensions,)`</span>
<span class="sd"> :return: np.ndarray of shape `(n_instances, n_classes,)` with posterior probabilities</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">predict_proba</span><span class="p">(</span><span class="n">X</span><span class="p">)</span></div>
<div class="viewcode-block" id="EMQ.classifier_fit_predict">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EMQ.classifier_fit_predict">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">classifier_fit_predict</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="n">classif_predictions</span> <span class="o">=</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">classifier_fit_predict</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">train_prevalence</span> <span class="o">=</span> <span class="n">F</span><span class="o">.</span><span class="n">prevalence_from_labels</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">classes</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">)</span>
<span class="k">return</span> <span class="n">classif_predictions</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_fit_calibration</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">calibrator</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="n">n_classes</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">np</span><span class="o">.</span><span class="n">issubdtype</span><span class="p">(</span><span class="n">y</span><span class="o">.</span><span class="n">dtype</span><span class="p">,</span> <span class="n">np</span><span class="o">.</span><span class="n">number</span><span class="p">):</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">searchsorted</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">calibration_function</span> <span class="o">=</span> <span class="n">calibrator</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">np</span><span class="o">.</span><span class="n">eye</span><span class="p">(</span><span class="n">n_classes</span><span class="p">)[</span><span class="n">y</span><span class="p">],</span> <span class="n">posterior_supplied</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_calib_error</span> <span class="o">==</span> <span class="s1">&#39;raise&#39;</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;calibration </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">calib</span><span class="si">}</span><span class="s1"> failed at fit time: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_calib_error</span> <span class="o">==</span> <span class="s1">&#39;backup&#39;</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">calibration_function</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">P</span><span class="p">:</span> <span class="n">P</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_calibrate_if_requested</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">uncalib_posteriors</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">&#39;calibration_function&#39;</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">calibration_function</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">calib_posteriors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">calibration_function</span><span class="p">(</span><span class="n">uncalib_posteriors</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_calib_error</span> <span class="o">==</span> <span class="s1">&#39;raise&#39;</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;calibration </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">calib</span><span class="si">}</span><span class="s1"> failed at predict time: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_calib_error</span> <span class="o">==</span> <span class="s1">&#39;backup&#39;</span><span class="p">:</span>
<span class="n">calib_posteriors</span> <span class="o">=</span> <span class="n">uncalib_posteriors</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;unexpected </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">on_calib_error</span><span class="si">=}</span><span class="s1">; &#39;</span>
<span class="sa">f</span><span class="s1">&#39;valid options are </span><span class="si">{</span><span class="n">EMQ</span><span class="o">.</span><span class="n">ON_CALIB_ERROR_VALUES</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">calib_posteriors</span>
<span class="k">return</span> <span class="n">uncalib_posteriors</span>
<div class="viewcode-block" id="EMQ.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EMQ.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Trains the aggregation function of EMQ. This comes down to recalibrating the posterior probabilities</span>
<span class="sd"> ir requested.</span>
<span class="sd"> :param classif_predictions: array-like with the raw (i.e., uncalibrated) posterior probabilities</span>
<span class="sd"> returned by the classifier</span>
<span class="sd"> :param labels: array-like with the true labels associated to each classifier prediction</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">P</span> <span class="o">=</span> <span class="n">classif_predictions</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">labels</span>
<span class="n">requires_predictions</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">calib</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">exact_train_prev</span><span class="p">)</span>
<span class="k">if</span> <span class="n">P</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">requires_predictions</span><span class="p">:</span>
<span class="c1"># classifier predictions were not generated because val_split=None</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span> <span class="o">+</span>
<span class="s2">&quot;: Classifier predictions for the aggregative fit were not generated because &quot;</span>
<span class="s2">&quot;val_split=None. This usually happens when you enable calibrations or heuristics &quot;</span>
<span class="s2">&quot;during model selection but left val_split set to its default value (None). &quot;</span>
<span class="s2">&quot;Please provide one of the following values for val_split: (i) an integer &gt;1 &quot;</span>
<span class="s2">&quot;(e.g. val_split=5) for k-fold cross-validation; (ii) a float in (0,1) (e.g. &quot;</span>
<span class="s2">&quot;val_split=0.3) for a proportion split; or (iii) a tuple (X, y) with explicit &quot;</span>
<span class="s2">&quot;validation data&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">calib</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">calibrator</span> <span class="o">=</span> <span class="n">_get_abstention_calibrators</span><span class="p">()</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">calib</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">if</span> <span class="n">calibrator</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;invalid value for </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">calib</span><span class="si">=}</span><span class="s1">; valid ones are </span><span class="si">{</span><span class="n">EMQ</span><span class="o">.</span><span class="n">CALIB_OPTIONS</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_fit_calibration</span><span class="p">(</span><span class="n">calibrator</span><span class="p">,</span> <span class="n">P</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">exact_train_prev</span><span class="p">:</span>
<span class="n">P</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_calibrate_if_requested</span><span class="p">(</span><span class="n">P</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">train_prevalence</span> <span class="o">=</span> <span class="n">F</span><span class="o">.</span><span class="n">prevalence_from_probabilities</span><span class="p">(</span><span class="n">P</span><span class="p">)</span></div>
<div class="viewcode-block" id="EMQ.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EMQ.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_posteriors</span><span class="p">,</span> <span class="n">epsilon</span><span class="o">=</span><span class="n">EPSILON</span><span class="p">):</span>
<span class="n">classif_posteriors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_calibrate_if_requested</span><span class="p">(</span><span class="n">classif_posteriors</span><span class="p">)</span>
<span class="n">priors</span><span class="p">,</span> <span class="n">posteriors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">EM</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">train_prevalence</span><span class="p">,</span> <span class="n">classif_posteriors</span><span class="p">,</span> <span class="n">epsilon</span><span class="p">)</span>
<span class="k">return</span> <span class="n">priors</span></div>
<div class="viewcode-block" id="EMQ.predict_proba">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EMQ.predict_proba">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">predict_proba</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">instances</span><span class="p">,</span> <span class="n">epsilon</span><span class="o">=</span><span class="n">EPSILON</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Returns the posterior probabilities updated by the EM algorithm.</span>
<span class="sd"> :param instances: np.ndarray of shape `(n_instances, n_dimensions)`</span>
<span class="sd"> :param epsilon: error tolerance</span>
<span class="sd"> :return: np.ndarray of shape `(n_instances, n_classes)`</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">classif_posteriors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">classify</span><span class="p">(</span><span class="n">instances</span><span class="p">)</span>
<span class="n">classif_posteriors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_calibrate_if_requested</span><span class="p">(</span><span class="n">classif_posteriors</span><span class="p">)</span>
<span class="n">priors</span><span class="p">,</span> <span class="n">posteriors</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">EM</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">train_prevalence</span><span class="p">,</span> <span class="n">classif_posteriors</span><span class="p">,</span> <span class="n">epsilon</span><span class="p">)</span>
<span class="k">return</span> <span class="n">posteriors</span></div>
<div class="viewcode-block" id="EMQ.EM">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EMQ.EM">[docs]</a>
<span class="nd">@classmethod</span>
<span class="k">def</span><span class="w"> </span><span class="nf">EM</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">tr_prev</span><span class="p">,</span> <span class="n">posterior_probabilities</span><span class="p">,</span> <span class="n">epsilon</span><span class="o">=</span><span class="n">EPSILON</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Computes the `Expectation Maximization` routine.</span>
<span class="sd"> :param tr_prev: array-like, the training prevalence</span>
<span class="sd"> :param posterior_probabilities: `np.ndarray` of shape `(n_instances, n_classes,)` with the</span>
<span class="sd"> posterior probabilities</span>
<span class="sd"> :param epsilon: float, the threshold different between two consecutive iterations</span>
<span class="sd"> to reach before stopping the loop</span>
<span class="sd"> :return: a tuple with the estimated prevalence values (shape `(n_classes,)`) and</span>
<span class="sd"> the corrected posterior probabilities (shape `(n_instances, n_classes,)`)</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">Px</span> <span class="o">=</span> <span class="n">posterior_probabilities</span>
<span class="n">Ptr</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">tr_prev</span><span class="p">)</span>
<span class="k">if</span> <span class="n">np</span><span class="o">.</span><span class="n">prod</span><span class="p">(</span><span class="n">Ptr</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># some entry is 0; we should smooth the values to avoid 0 division</span>
<span class="n">Ptr</span> <span class="o">+=</span> <span class="n">epsilon</span>
<span class="n">Ptr</span> <span class="o">/=</span> <span class="n">Ptr</span><span class="o">.</span><span class="n">sum</span><span class="p">()</span>
<span class="n">qs</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">Ptr</span><span class="p">)</span> <span class="c1"># qs (the running estimate) is initialized as the training prevalence</span>
<span class="n">s</span><span class="p">,</span> <span class="n">converged</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="kc">False</span>
<span class="n">qs_prev_</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">converged</span> <span class="ow">and</span> <span class="n">s</span> <span class="o">&lt;</span> <span class="n">EMQ</span><span class="o">.</span><span class="n">MAX_ITER</span><span class="p">:</span>
<span class="c1"># E-step: ps is Ps(y|xi)</span>
<span class="n">ps_unnormalized</span> <span class="o">=</span> <span class="p">(</span><span class="n">qs</span> <span class="o">/</span> <span class="n">Ptr</span><span class="p">)</span> <span class="o">*</span> <span class="n">Px</span>
<span class="n">ps</span> <span class="o">=</span> <span class="n">ps_unnormalized</span> <span class="o">/</span> <span class="n">ps_unnormalized</span><span class="o">.</span><span class="n">sum</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">keepdims</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="c1"># M-step:</span>
<span class="n">qs</span> <span class="o">=</span> <span class="n">ps</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="k">if</span> <span class="n">qs_prev_</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">qp</span><span class="o">.</span><span class="n">error</span><span class="o">.</span><span class="n">mae</span><span class="p">(</span><span class="n">qs</span><span class="p">,</span> <span class="n">qs_prev_</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">epsilon</span> <span class="ow">and</span> <span class="n">s</span> <span class="o">&gt;</span> <span class="mi">10</span><span class="p">:</span>
<span class="n">converged</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">qs_prev_</span> <span class="o">=</span> <span class="n">qs</span>
<span class="n">s</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">converged</span><span class="p">:</span>
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s1">&#39;the method has reached the maximum number of iterations; it might have not converged&#39;</span><span class="p">)</span>
<span class="k">return</span> <span class="n">qs</span><span class="p">,</span> <span class="n">ps</span></div>
</div>
<div class="viewcode-block" id="HDy">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.HDy">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">HDy</span><span class="p">(</span><span class="n">AggregativeSoftQuantifier</span><span class="p">,</span> <span class="n">BinaryAggregativeQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `Hellinger Distance y &lt;https://www.sciencedirect.com/science/article/pii/S0020025512004069&gt;`_ (HDy).</span>
<span class="sd"> HDy is a probabilistic method for training binary quantifiers, that models quantification as the problem of</span>
<span class="sd"> minimizing the divergence (in terms of the Hellinger Distance) between two distributions of posterior</span>
<span class="sd"> probabilities returned by the classifier. One of the distributions is generated from the unlabelled examples and</span>
<span class="sd"> the other is generated from a validation set. This latter distribution is defined as a mixture of the</span>
<span class="sd"> class-conditional distributions of the posterior probabilities returned for the positive and negative validation</span>
<span class="sd"> examples, respectively. The parameters of the mixture thus represent the estimates of the class prevalence values.</span>
<span class="sd"> This dedicated class is kept for backward compatibility as the historical</span>
<span class="sd"> HDy implementation. The same historical preset is also available as</span>
<span class="sd"> :meth:`DMy.HDy`.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set to False if the</span>
<span class="sd"> learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier predictions. This specification</span>
<span class="sd"> can be made as float in (0, 1) indicating the proportion of stratified held-out validation set to</span>
<span class="sd"> be extracted from the training set; or as an integer (default 5), indicating that the predictions</span>
<span class="sd"> are to be generated in a `k`-fold cross-validation manner (with this integer indicating the value</span>
<span class="sd"> for `k`); or as a tuple (X,y) defining the specific set of data to use for validation.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="p">)</span>
<div class="viewcode-block" id="HDy.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.HDy.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Trains the aggregation function of HDy.</span>
<span class="sd"> :param classif_predictions: array-like with the posterior probabilities returned by the classifier</span>
<span class="sd"> :param labels: array-like with the true labels associated to each posterior</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">P</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span>
<span class="n">Px</span> <span class="o">=</span> <span class="n">P</span><span class="p">[:,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos_label</span><span class="p">]</span> <span class="c1"># takes only the P(y=+1|x)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy1</span> <span class="o">=</span> <span class="n">Px</span><span class="p">[</span><span class="n">y</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos_label</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy0</span> <span class="o">=</span> <span class="n">Px</span><span class="p">[</span><span class="n">y</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">neg_label</span><span class="p">]</span>
<span class="c1"># pre-compute the histogram for positive and negative examples</span>
<span class="bp">self</span><span class="o">.</span><span class="n">bins</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">110</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">int</span><span class="p">)</span> <span class="c1"># [10, 20, 30, ..., 100, 110]</span>
<span class="k">def</span><span class="w"> </span><span class="nf">hist</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">bins</span><span class="p">):</span>
<span class="n">h</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">histogram</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">bins</span><span class="o">=</span><span class="n">bins</span><span class="p">,</span> <span class="nb">range</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">density</span><span class="o">=</span><span class="kc">True</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">return</span> <span class="n">h</span> <span class="o">/</span> <span class="n">h</span><span class="o">.</span><span class="n">sum</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy1_density</span> <span class="o">=</span> <span class="p">{</span><span class="n">bins</span><span class="p">:</span> <span class="n">hist</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Pxy1</span><span class="p">,</span> <span class="n">bins</span><span class="p">)</span> <span class="k">for</span> <span class="n">bins</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">bins</span><span class="p">}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy0_density</span> <span class="o">=</span> <span class="p">{</span><span class="n">bins</span><span class="p">:</span> <span class="n">hist</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Pxy0</span><span class="p">,</span> <span class="n">bins</span><span class="p">)</span> <span class="k">for</span> <span class="n">bins</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">bins</span><span class="p">}</span></div>
<div class="viewcode-block" id="HDy.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.HDy.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_posteriors</span><span class="p">):</span>
<span class="c1"># &quot;In this work, the number of bins b used in HDx and HDy was chosen from 10 to 110 in steps of 10,</span>
<span class="c1"># and the final estimated a priori probability was taken as the median of these 11 estimates.&quot;</span>
<span class="c1"># (González-Castro, et al., 2013).</span>
<span class="n">Px</span> <span class="o">=</span> <span class="n">classif_posteriors</span><span class="p">[:,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos_label</span><span class="p">]</span> <span class="c1"># takes only the P(y=+1|x)</span>
<span class="n">prev_estimations</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">bins</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">bins</span><span class="p">:</span>
<span class="n">Pxy0_density</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Pxy0_density</span><span class="p">[</span><span class="n">bins</span><span class="p">]</span>
<span class="n">Pxy1_density</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">Pxy1_density</span><span class="p">[</span><span class="n">bins</span><span class="p">]</span>
<span class="n">Px_test</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">histogram</span><span class="p">(</span><span class="n">Px</span><span class="p">,</span> <span class="n">bins</span><span class="o">=</span><span class="n">bins</span><span class="p">,</span> <span class="nb">range</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">density</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="c1"># the authors proposed to search for the prevalence yielding the best matching as a linear search</span>
<span class="c1"># at small steps (modern implementations resort to an optimization procedure,</span>
<span class="c1"># see class DistributionMatching)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">loss</span><span class="p">(</span><span class="n">prev</span><span class="p">):</span>
<span class="n">class1_prev</span> <span class="o">=</span> <span class="n">prev</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">Px_train</span> <span class="o">=</span> <span class="n">class1_prev</span> <span class="o">*</span> <span class="n">Pxy1_density</span> <span class="o">+</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">class1_prev</span><span class="p">)</span> <span class="o">*</span> <span class="n">Pxy0_density</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">HellingerDistance</span><span class="p">(</span><span class="n">Px_train</span><span class="p">,</span> <span class="n">Px_test</span><span class="p">)</span>
<span class="n">prev_estimations</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">F</span><span class="o">.</span><span class="n">linear_search</span><span class="p">(</span><span class="n">loss</span><span class="p">,</span> <span class="n">n_classes</span><span class="o">=</span><span class="mi">2</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">class1_prev</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">median</span><span class="p">(</span><span class="n">prev_estimations</span><span class="p">)</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">as_binary_prevalence</span><span class="p">(</span><span class="n">class1_prev</span><span class="p">)</span></div>
</div>
<div class="viewcode-block" id="DyS">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.DyS">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">DyS</span><span class="p">(</span><span class="n">AggregativeSoftQuantifier</span><span class="p">,</span> <span class="n">BinaryAggregativeQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `DyS framework &lt;https://ojs.aaai.org/index.php/AAAI/article/view/4376&gt;`_ (DyS).</span>
<span class="sd"> DyS is a generalization of HDy method, using a Ternary Search in order to find the prevalence that</span>
<span class="sd"> minimizes the distance between distributions.</span>
<span class="sd"> Details for the ternary search have been got from &lt;https://dl.acm.org/doi/pdf/10.1145/3219819.3220059&gt;</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set to False if the</span>
<span class="sd"> learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier predictions. This specification</span>
<span class="sd"> can be made as float in (0, 1) indicating the proportion of stratified held-out validation set to</span>
<span class="sd"> be extracted from the training set; or as an integer (default 5), indicating that the predictions</span>
<span class="sd"> are to be generated in a `k`-fold cross-validation manner (with this integer indicating the value</span>
<span class="sd"> for `k`); or as a tuple (X,y) defining the specific set of data to use for validation.</span>
<span class="sd"> :param n_bins: an int with the number of bins to use to compute the histograms.</span>
<span class="sd"> :param divergence: a str indicating the name of divergence (currently supported ones are &quot;HD&quot; or &quot;topsoe&quot;), or a</span>
<span class="sd"> callable function computes the divergence between two distributions (two equally sized arrays).</span>
<span class="sd"> :param tol: a float with the tolerance for the ternary search algorithm.</span>
<span class="sd"> :param n_jobs: number of parallel workers.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">n_bins</span><span class="o">=</span><span class="mi">8</span><span class="p">,</span>
<span class="n">divergence</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Callable</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;HD&#39;</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="mf">1e-05</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">tol</span> <span class="o">=</span> <span class="n">tol</span>
<span class="bp">self</span><span class="o">.</span><span class="n">divergence</span> <span class="o">=</span> <span class="n">divergence</span>
<span class="bp">self</span><span class="o">.</span><span class="n">n_bins</span> <span class="o">=</span> <span class="n">n_bins</span>
<span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_njobs</span><span class="p">(</span><span class="n">n_jobs</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_ternary_search</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">f</span><span class="p">,</span> <span class="n">left</span><span class="p">,</span> <span class="n">right</span><span class="p">,</span> <span class="n">tol</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Find maximum of unimodal function f() within [left, right]</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">while</span> <span class="nb">abs</span><span class="p">(</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="n">tol</span><span class="p">:</span>
<span class="n">left_third</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">(</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">3</span>
<span class="n">right_third</span> <span class="o">=</span> <span class="n">right</span> <span class="o">-</span> <span class="p">(</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">/</span> <span class="mi">3</span>
<span class="k">if</span> <span class="n">f</span><span class="p">(</span><span class="n">left_third</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">f</span><span class="p">(</span><span class="n">right_third</span><span class="p">):</span>
<span class="n">left</span> <span class="o">=</span> <span class="n">left_third</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">right</span> <span class="o">=</span> <span class="n">right_third</span>
<span class="c1"># Left and right are the current bounds; the maximum is between them</span>
<span class="k">return</span> <span class="p">(</span><span class="n">left</span> <span class="o">+</span> <span class="n">right</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span>
<div class="viewcode-block" id="DyS.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.DyS.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Trains the aggregation function of DyS.</span>
<span class="sd"> :param classif_predictions: array-like with the posterior probabilities returned by the classifier</span>
<span class="sd"> :param labels: array-like with the true labels associated to each posterior</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">Px</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span>
<span class="n">Px</span> <span class="o">=</span> <span class="n">Px</span><span class="p">[:,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos_label</span><span class="p">]</span> <span class="c1"># takes only the P(y=+1|x)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy1</span> <span class="o">=</span> <span class="n">Px</span><span class="p">[</span><span class="n">y</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos_label</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy0</span> <span class="o">=</span> <span class="n">Px</span><span class="p">[</span><span class="n">y</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">neg_label</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy1_density</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">histogram</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Pxy1</span><span class="p">,</span> <span class="n">bins</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">n_bins</span><span class="p">,</span> <span class="nb">range</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">density</span><span class="o">=</span><span class="kc">True</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy0_density</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">histogram</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Pxy0</span><span class="p">,</span> <span class="n">bins</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">n_bins</span><span class="p">,</span> <span class="nb">range</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">density</span><span class="o">=</span><span class="kc">True</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">return</span> <span class="bp">self</span></div>
<div class="viewcode-block" id="DyS.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.DyS.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_posteriors</span><span class="p">):</span>
<span class="n">Px</span> <span class="o">=</span> <span class="n">classif_posteriors</span><span class="p">[:,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos_label</span><span class="p">]</span> <span class="c1"># takes only the P(y=+1|x)</span>
<span class="n">Px_test</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">histogram</span><span class="p">(</span><span class="n">Px</span><span class="p">,</span> <span class="n">bins</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">n_bins</span><span class="p">,</span> <span class="nb">range</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="n">density</span><span class="o">=</span><span class="kc">True</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">divergence</span> <span class="o">=</span> <span class="n">get_divergence</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">divergence</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">distribution_distance</span><span class="p">(</span><span class="n">prev</span><span class="p">):</span>
<span class="n">Px_train</span> <span class="o">=</span> <span class="n">prev</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">Pxy1_density</span> <span class="o">+</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="n">prev</span><span class="p">)</span> <span class="o">*</span> <span class="bp">self</span><span class="o">.</span><span class="n">Pxy0_density</span>
<span class="k">return</span> <span class="n">divergence</span><span class="p">(</span><span class="n">Px_train</span><span class="p">,</span> <span class="n">Px_test</span><span class="p">)</span>
<span class="n">class1_prev</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_ternary_search</span><span class="p">(</span><span class="n">f</span><span class="o">=</span><span class="n">distribution_distance</span><span class="p">,</span> <span class="n">left</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">right</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">tol</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">tol</span><span class="p">)</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">as_binary_prevalence</span><span class="p">(</span><span class="n">class1_prev</span><span class="p">)</span></div>
</div>
<div class="viewcode-block" id="SMM">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.SMM">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">SMM</span><span class="p">(</span><span class="n">AggregativeSoftQuantifier</span><span class="p">,</span> <span class="n">BinaryAggregativeQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> `SMM method &lt;https://ieeexplore.ieee.org/document/9260028&gt;`_ (SMM).</span>
<span class="sd"> SMM is a simplification of matching distribution methods where the representation of the examples</span>
<span class="sd"> is created using the mean instead of a histogram (conceptually equivalent to PACC).</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set to False if the</span>
<span class="sd"> learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier predictions. This specification</span>
<span class="sd"> can be made as float in (0, 1) indicating the proportion of stratified held-out validation set to</span>
<span class="sd"> be extracted from the training set; or as an integer (default 5), indicating that the predictions</span>
<span class="sd"> are to be generated in a `k`-fold cross-validation manner (with this integer indicating the value</span>
<span class="sd"> for `k`); or as a tuple (X,y) defining the specific set of data to use for validation.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="p">)</span>
<div class="viewcode-block" id="SMM.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.SMM.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Trains the aggregation function of SMM.</span>
<span class="sd"> :param classif_predictions: array-like with the posterior probabilities returned by the classifier</span>
<span class="sd"> :param labels: array-like with the true labels associated to each posterior</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">Px</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span>
<span class="n">Px</span> <span class="o">=</span> <span class="n">Px</span><span class="p">[:,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos_label</span><span class="p">]</span> <span class="c1"># takes only the P(y=+1|x)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy1</span> <span class="o">=</span> <span class="n">Px</span><span class="p">[</span><span class="n">y</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos_label</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy0</span> <span class="o">=</span> <span class="n">Px</span><span class="p">[</span><span class="n">y</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">neg_label</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy1_mean</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Pxy1</span><span class="p">)</span> <span class="c1"># equiv. TPR</span>
<span class="bp">self</span><span class="o">.</span><span class="n">Pxy0_mean</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Pxy0</span><span class="p">)</span> <span class="c1"># equiv. FPR</span>
<span class="k">return</span> <span class="bp">self</span></div>
<div class="viewcode-block" id="SMM.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.SMM.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_posteriors</span><span class="p">):</span>
<span class="n">Px</span> <span class="o">=</span> <span class="n">classif_posteriors</span><span class="p">[:,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pos_label</span><span class="p">]</span> <span class="c1"># takes only the P(y=+1|x)</span>
<span class="n">Px_mean</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">Px</span><span class="p">)</span>
<span class="n">class1_prev</span> <span class="o">=</span> <span class="p">(</span><span class="n">Px_mean</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">Pxy0_mean</span><span class="p">)</span> <span class="o">/</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">Pxy1_mean</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">Pxy0_mean</span><span class="p">)</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">as_binary_prevalence</span><span class="p">(</span><span class="n">class1_prev</span><span class="p">,</span> <span class="n">clip_if_necessary</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></div>
</div>
<div class="viewcode-block" id="DMy">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.DMy">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">DMy</span><span class="p">(</span><span class="n">AggregativeSoftQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Generic Distribution Matching quantifier for binary or multiclass quantification based on the space of posterior</span>
<span class="sd"> probabilities. This implementation takes the number of bins, the divergence, and the possibility to work on CDF</span>
<span class="sd"> as hyperparameters.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None, in which case the classifier is taken to be</span>
<span class="sd"> the one indicated in `qp.environ[&#39;DEFAULT_CLS&#39;]`</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default is True). Set to False if the</span>
<span class="sd"> learner has been trained outside the quantifier.</span>
<span class="sd"> :param val_split: specifies the data used for generating classifier predictions. This specification</span>
<span class="sd"> can be made as float in (0, 1) indicating the proportion of stratified held-out validation set to</span>
<span class="sd"> be extracted from the training set; or as an integer (default 5), indicating that the predictions</span>
<span class="sd"> are to be generated in a `k`-fold cross-validation manner (with this integer indicating the value</span>
<span class="sd"> for `k`); or as a tuple (X,y) defining the specific set of data to use for validation.</span>
<span class="sd"> :param nbins: number of bins used to discretize the distributions (default 8)</span>
<span class="sd"> :param divergence: a string representing a divergence measure (currently, &quot;HD&quot; and &quot;topsoe&quot; are implemented)</span>
<span class="sd"> or a callable function taking two ndarrays of the same dimension as input (default &quot;HD&quot;, meaning Hellinger</span>
<span class="sd"> Distance)</span>
<span class="sd"> :param cdf: whether to use CDF instead of PDF (default False)</span>
<span class="sd"> :param search: string indicating the search strategy used to estimate the prevalence values.</span>
<span class="sd"> Valid options are `optim_minimize` (default, works for binary and multiclass problems),</span>
<span class="sd"> `linear_search` (binary only), and `ternary_search` (binary only)</span>
<span class="sd"> :param n_jobs: number of parallel workers (default None)</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">nbins</span><span class="o">=</span><span class="mi">8</span><span class="p">,</span>
<span class="n">divergence</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Callable</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;HD&#39;</span><span class="p">,</span> <span class="n">cdf</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">search</span><span class="o">=</span><span class="s1">&#39;optim_minimize&#39;</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">nbins</span> <span class="o">=</span> <span class="n">nbins</span>
<span class="bp">self</span><span class="o">.</span><span class="n">divergence</span> <span class="o">=</span> <span class="n">divergence</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cdf</span> <span class="o">=</span> <span class="n">cdf</span>
<span class="bp">self</span><span class="o">.</span><span class="n">search</span> <span class="o">=</span> <span class="n">search</span>
<span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_njobs</span><span class="p">(</span><span class="n">n_jobs</span><span class="p">)</span>
<div class="viewcode-block" id="DMy.HDy">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.DMy.HDy">[docs]</a>
<span class="nd">@classmethod</span>
<span class="k">def</span><span class="w"> </span><span class="nf">HDy</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Historical HDy preset expressed as a configuration of :class:`DMy`.</span>
<span class="sd"> This preset reproduces the original HDy setup by using Hellinger</span>
<span class="sd"> distance, PDF matching, linear search, and a median sweep over</span>
<span class="sd"> `nbins` in `[10, 20, ..., 110]`.</span>
<span class="sd"> :param classifier: a scikit-learn&#39;s BaseEstimator, or None</span>
<span class="sd"> :param fit_classifier: whether to train the learner</span>
<span class="sd"> :param val_split: validation specification for generating posteriors</span>
<span class="sd"> :param n_jobs: number of parallel workers</span>
<span class="sd"> :return: an instance of :class:`AggregativeMedianEstimator` configured</span>
<span class="sd"> to reproduce the historical HDy preset</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">base</span> <span class="o">=</span> <span class="bp">cls</span><span class="p">(</span>
<span class="n">classifier</span><span class="o">=</span><span class="n">classifier</span><span class="p">,</span>
<span class="n">fit_classifier</span><span class="o">=</span><span class="n">fit_classifier</span><span class="p">,</span>
<span class="n">val_split</span><span class="o">=</span><span class="n">val_split</span><span class="p">,</span>
<span class="n">nbins</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span>
<span class="n">divergence</span><span class="o">=</span><span class="s1">&#39;HD&#39;</span><span class="p">,</span>
<span class="n">cdf</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
<span class="n">search</span><span class="o">=</span><span class="s1">&#39;linear_search&#39;</span><span class="p">,</span>
<span class="n">n_jobs</span><span class="o">=</span><span class="n">n_jobs</span><span class="p">,</span>
<span class="p">)</span>
<span class="n">param_grid</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;nbins&#39;</span><span class="p">:</span> <span class="n">np</span><span class="o">.</span><span class="n">linspace</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">110</span><span class="p">,</span> <span class="mi">11</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">int</span><span class="p">)}</span>
<span class="k">return</span> <span class="n">AggregativeMedianEstimator</span><span class="p">(</span><span class="n">base_quantifier</span><span class="o">=</span><span class="n">base</span><span class="p">,</span> <span class="n">param_grid</span><span class="o">=</span><span class="n">param_grid</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="n">n_jobs</span><span class="p">)</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_get_distributions</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">posteriors</span><span class="p">):</span>
<span class="n">histograms</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">post_dims</span> <span class="o">=</span> <span class="n">posteriors</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">if</span> <span class="n">post_dims</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
<span class="c1"># in binary quantification we can use only one class, since the other one is its complement</span>
<span class="n">post_dims</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">dim</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">post_dims</span><span class="p">):</span>
<span class="n">hist</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">histogram</span><span class="p">(</span><span class="n">posteriors</span><span class="p">[:,</span> <span class="n">dim</span><span class="p">],</span> <span class="n">bins</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">nbins</span><span class="p">,</span> <span class="nb">range</span><span class="o">=</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">))[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">histograms</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">hist</span><span class="p">)</span>
<span class="n">counts</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">vstack</span><span class="p">(</span><span class="n">histograms</span><span class="p">)</span>
<span class="n">distributions</span> <span class="o">=</span> <span class="n">counts</span> <span class="o">/</span> <span class="n">counts</span><span class="o">.</span><span class="n">sum</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">)[:,</span> <span class="n">np</span><span class="o">.</span><span class="n">newaxis</span><span class="p">]</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cdf</span><span class="p">:</span>
<span class="n">distributions</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">cumsum</span><span class="p">(</span><span class="n">distributions</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="n">distributions</span>
<div class="viewcode-block" id="DMy.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.DMy.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Trains the aggregation function of a distribution matching method. This comes down to generating the</span>
<span class="sd"> validation distributions out of the training data.</span>
<span class="sd"> The validation distributions have shape `(n, ch, nbins)`, with `n` the number of classes, `ch` the number of</span>
<span class="sd"> channels, and `nbins` the number of bins. In particular, let `V` be the validation distributions; then `di=V[i]`</span>
<span class="sd"> are the distributions obtained from training data labelled with class `i`; while `dij = di[j]` is the discrete</span>
<span class="sd"> distribution of posterior probabilities `P(Y=j|X=x)` for training data labelled with class `i`, and `dij[k]`</span>
<span class="sd"> is the fraction of instances with a value in the `k`-th bin.</span>
<span class="sd"> :param classif_predictions: array-like with the posterior probabilities returned by the classifier</span>
<span class="sd"> :param labels: array-like with the true labels associated to each posterior</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">posteriors</span><span class="p">,</span> <span class="n">true_labels</span> <span class="o">=</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span>
<span class="n">classes</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">classifier</span><span class="o">.</span><span class="n">classes_</span>
<span class="n">n_classes</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">classes</span><span class="p">)</span>
<span class="n">true_labels</span> <span class="o">=</span> <span class="n">_labels_to_indices</span><span class="p">(</span><span class="n">true_labels</span><span class="p">,</span> <span class="n">classes</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">validation_distribution</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">parallel</span><span class="p">(</span>
<span class="n">func</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_distributions</span><span class="p">,</span>
<span class="n">args</span><span class="o">=</span><span class="p">[</span><span class="n">posteriors</span><span class="p">[</span><span class="n">true_labels</span> <span class="o">==</span> <span class="n">cat</span><span class="p">]</span> <span class="k">for</span> <span class="n">cat</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n_classes</span><span class="p">)],</span>
<span class="n">n_jobs</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span><span class="p">,</span>
<span class="n">backend</span><span class="o">=</span><span class="s1">&#39;threading&#39;</span>
<span class="p">)</span></div>
<div class="viewcode-block" id="DMy.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.DMy.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">posteriors</span><span class="p">:</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Searches for the mixture model parameter (the sought prevalence values) that yields a validation distribution</span>
<span class="sd"> (the mixture) that best matches the test distribution, in terms of the divergence measure of choice.</span>
<span class="sd"> In the multiclass case, with `n` the number of classes, the test and mixture distributions contain</span>
<span class="sd"> `n` channels (proper distributions of binned posterior probabilities), on which the divergence is computed</span>
<span class="sd"> independently. The matching is computed as an average of the divergence across all channels.</span>
<span class="sd"> :param posteriors: posterior probabilities of the instances in the sample</span>
<span class="sd"> :return: a vector of class prevalence estimates</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">test_distribution</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_distributions</span><span class="p">(</span><span class="n">posteriors</span><span class="p">)</span>
<span class="n">divergence</span> <span class="o">=</span> <span class="n">get_divergence</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">divergence</span><span class="p">)</span>
<span class="n">n_classes</span><span class="p">,</span> <span class="n">n_channels</span><span class="p">,</span> <span class="n">nbins</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">validation_distribution</span><span class="o">.</span><span class="n">shape</span>
<span class="k">def</span><span class="w"> </span><span class="nf">loss</span><span class="p">(</span><span class="n">prev</span><span class="p">):</span>
<span class="n">prev</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">expand_dims</span><span class="p">(</span><span class="n">prev</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span>
<span class="n">mixture_distribution</span> <span class="o">=</span> <span class="p">(</span><span class="n">prev</span> <span class="o">@</span> <span class="bp">self</span><span class="o">.</span><span class="n">validation_distribution</span><span class="o">.</span><span class="n">reshape</span><span class="p">(</span><span class="n">n_classes</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">))</span><span class="o">.</span><span class="n">reshape</span><span class="p">(</span><span class="n">n_channels</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">divs</span> <span class="o">=</span> <span class="p">[</span><span class="n">divergence</span><span class="p">(</span><span class="n">test_distribution</span><span class="p">[</span><span class="n">ch</span><span class="p">],</span> <span class="n">mixture_distribution</span><span class="p">[</span><span class="n">ch</span><span class="p">])</span> <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n_channels</span><span class="p">)]</span>
<span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">divs</span><span class="p">)</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">argmin_prevalence</span><span class="p">(</span><span class="n">loss</span><span class="p">,</span> <span class="n">n_classes</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">search</span><span class="p">)</span></div>
</div>
<div class="viewcode-block" id="newELM">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.newELM">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">newELM</span><span class="p">(</span><span class="n">svmperf_base</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">loss</span><span class="o">=</span><span class="s1">&#39;01&#39;</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Explicit Loss Minimization (ELM) quantifiers.</span>
<span class="sd"> Quantifiers based on ELM represent a family of methods based on structured output learning;</span>
<span class="sd"> these quantifiers rely on classifiers that have been optimized using a quantification-oriented loss</span>
<span class="sd"> measure. This implementation relies on</span>
<span class="sd"> `Joachims SVM perf &lt;https://www.cs.cornell.edu/people/tj/svm_light/svm_perf.html&gt;`_ structured output</span>
<span class="sd"> learning algorithm, which has to be installed and patched for the purpose (see this</span>
<span class="sd"> `script &lt;https://github.com/HLT-ISTI/QuaPy/blob/master/prepare_svmperf.sh&gt;`_).</span>
<span class="sd"> This function equivalent to:</span>
<span class="sd"> &gt;&gt;&gt; CC(SVMperf(svmperf_base, loss, C))</span>
<span class="sd"> :param svmperf_base: path to the folder containing the binary files of `SVM perf`; if set to None (default)</span>
<span class="sd"> this path will be obtained from qp.environ[&#39;SVMPERF_HOME&#39;]</span>
<span class="sd"> :param loss: the loss to optimize (see :attr:`quapy.classification.svmperf.SVMperf.valid_losses`)</span>
<span class="sd"> :param C: trade-off between training error and margin (default 0.01)</span>
<span class="sd"> :return: returns an instance of CC set to work with SVMperf (with loss and C set properly) as the</span>
<span class="sd"> underlying classifier</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">svmperf_base</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">svmperf_base</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s1">&#39;SVMPERF_HOME&#39;</span><span class="p">]</span>
<span class="k">assert</span> <span class="n">svmperf_base</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">,</span> \
<span class="s1">&#39;param svmperf_base was not specified, and the variable SVMPERF_HOME has not been set in the environment&#39;</span>
<span class="k">return</span> <span class="n">CC</span><span class="p">(</span><span class="n">SVMperf</span><span class="p">(</span><span class="n">svmperf_base</span><span class="p">,</span> <span class="n">loss</span><span class="o">=</span><span class="n">loss</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="n">C</span><span class="p">))</span></div>
<div class="viewcode-block" id="newSVMQ">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.newSVMQ">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">newSVMQ</span><span class="p">(</span><span class="n">svmperf_base</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> SVM(Q) is an Explicit Loss Minimization (ELM) quantifier set to optimize for the `Q` loss combining a</span>
<span class="sd"> classification-oriented loss and a quantification-oriented loss, as proposed by</span>
<span class="sd"> `Barranquero et al. 2015 &lt;https://www.sciencedirect.com/science/article/pii/S003132031400291X&gt;`_.</span>
<span class="sd"> Equivalent to:</span>
<span class="sd"> &gt;&gt;&gt; CC(SVMperf(svmperf_base, loss=&#39;q&#39;, C=C))</span>
<span class="sd"> Quantifiers based on ELM represent a family of methods based on structured output learning;</span>
<span class="sd"> these quantifiers rely on classifiers that have been optimized using a quantification-oriented loss</span>
<span class="sd"> measure. This implementation relies on</span>
<span class="sd"> `Joachims SVM perf &lt;https://www.cs.cornell.edu/people/tj/svm_light/svm_perf.html&gt;`_ structured output</span>
<span class="sd"> learning algorithm, which has to be installed and patched for the purpose (see this</span>
<span class="sd"> `script &lt;https://github.com/HLT-ISTI/QuaPy/blob/master/prepare_svmperf.sh&gt;`_).</span>
<span class="sd"> This function is a wrapper around CC(SVMperf(svmperf_base, loss, C))</span>
<span class="sd"> :param svmperf_base: path to the folder containing the binary files of `SVM perf`; if set to None (default)</span>
<span class="sd"> this path will be obtained from qp.environ[&#39;SVMPERF_HOME&#39;]</span>
<span class="sd"> :param C: trade-off between training error and margin (default 0.01)</span>
<span class="sd"> :return: returns an instance of CC set to work with SVMperf (with loss and C set properly) as the</span>
<span class="sd"> underlying classifier</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">newELM</span><span class="p">(</span><span class="n">svmperf_base</span><span class="p">,</span> <span class="n">loss</span><span class="o">=</span><span class="s1">&#39;q&#39;</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="n">C</span><span class="p">)</span></div>
<div class="viewcode-block" id="newSVMKLD">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.newSVMKLD">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">newSVMKLD</span><span class="p">(</span><span class="n">svmperf_base</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> SVM(KLD) is an Explicit Loss Minimization (ELM) quantifier set to optimize for the Kullback-Leibler Divergence</span>
<span class="sd"> as proposed by `Esuli et al. 2015 &lt;https://dl.acm.org/doi/abs/10.1145/2700406&gt;`_.</span>
<span class="sd"> Equivalent to:</span>
<span class="sd"> &gt;&gt;&gt; CC(SVMperf(svmperf_base, loss=&#39;kld&#39;, C=C))</span>
<span class="sd"> Quantifiers based on ELM represent a family of methods based on structured output learning;</span>
<span class="sd"> these quantifiers rely on classifiers that have been optimized using a quantification-oriented loss</span>
<span class="sd"> measure. This implementation relies on</span>
<span class="sd"> `Joachims SVM perf &lt;https://www.cs.cornell.edu/people/tj/svm_light/svm_perf.html&gt;`_ structured output</span>
<span class="sd"> learning algorithm, which has to be installed and patched for the purpose (see this</span>
<span class="sd"> `script &lt;https://github.com/HLT-ISTI/QuaPy/blob/master/prepare_svmperf.sh&gt;`_).</span>
<span class="sd"> This function is a wrapper around CC(SVMperf(svmperf_base, loss, C))</span>
<span class="sd"> :param svmperf_base: path to the folder containing the binary files of `SVM perf`; if set to None (default)</span>
<span class="sd"> this path will be obtained from qp.environ[&#39;SVMPERF_HOME&#39;]</span>
<span class="sd"> :param C: trade-off between training error and margin (default 0.01)</span>
<span class="sd"> :return: returns an instance of CC set to work with SVMperf (with loss and C set properly) as the</span>
<span class="sd"> underlying classifier</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">newELM</span><span class="p">(</span><span class="n">svmperf_base</span><span class="p">,</span> <span class="n">loss</span><span class="o">=</span><span class="s1">&#39;kld&#39;</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="n">C</span><span class="p">)</span></div>
<div class="viewcode-block" id="newSVMNKLD">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.newSVMNKLD">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">newSVMNKLD</span><span class="p">(</span><span class="n">svmperf_base</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> SVM(NKLD) is an Explicit Loss Minimization (ELM) quantifier set to optimize for the Kullback-Leibler Divergence</span>
<span class="sd"> normalized via the logistic function, as proposed by</span>
<span class="sd"> `Esuli et al. 2015 &lt;https://dl.acm.org/doi/abs/10.1145/2700406&gt;`_.</span>
<span class="sd"> Equivalent to:</span>
<span class="sd"> &gt;&gt;&gt; CC(SVMperf(svmperf_base, loss=&#39;nkld&#39;, C=C))</span>
<span class="sd"> Quantifiers based on ELM represent a family of methods based on structured output learning;</span>
<span class="sd"> these quantifiers rely on classifiers that have been optimized using a quantification-oriented loss</span>
<span class="sd"> measure. This implementation relies on</span>
<span class="sd"> `Joachims SVM perf &lt;https://www.cs.cornell.edu/people/tj/svm_light/svm_perf.html&gt;`_ structured output</span>
<span class="sd"> learning algorithm, which has to be installed and patched for the purpose (see this</span>
<span class="sd"> `script &lt;https://github.com/HLT-ISTI/QuaPy/blob/master/prepare_svmperf.sh&gt;`_).</span>
<span class="sd"> This function is a wrapper around CC(SVMperf(svmperf_base, loss, C))</span>
<span class="sd"> :param svmperf_base: path to the folder containing the binary files of `SVM perf`; if set to None (default)</span>
<span class="sd"> this path will be obtained from qp.environ[&#39;SVMPERF_HOME&#39;]</span>
<span class="sd"> :param C: trade-off between training error and margin (default 0.01)</span>
<span class="sd"> :return: returns an instance of CC set to work with SVMperf (with loss and C set properly) as the</span>
<span class="sd"> underlying classifier</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">newELM</span><span class="p">(</span><span class="n">svmperf_base</span><span class="p">,</span> <span class="n">loss</span><span class="o">=</span><span class="s1">&#39;nkld&#39;</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="n">C</span><span class="p">)</span></div>
<div class="viewcode-block" id="newSVMAE">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.newSVMAE">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">newSVMAE</span><span class="p">(</span><span class="n">svmperf_base</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> SVM(KLD) is an Explicit Loss Minimization (ELM) quantifier set to optimize for the Absolute Error as first used by</span>
<span class="sd"> `Moreo and Sebastiani, 2021 &lt;https://arxiv.org/abs/2011.02552&gt;`_.</span>
<span class="sd"> Equivalent to:</span>
<span class="sd"> &gt;&gt;&gt; CC(SVMperf(svmperf_base, loss=&#39;mae&#39;, C=C))</span>
<span class="sd"> Quantifiers based on ELM represent a family of methods based on structured output learning;</span>
<span class="sd"> these quantifiers rely on classifiers that have been optimized using a quantification-oriented loss</span>
<span class="sd"> measure. This implementation relies on</span>
<span class="sd"> `Joachims SVM perf &lt;https://www.cs.cornell.edu/people/tj/svm_light/svm_perf.html&gt;`_ structured output</span>
<span class="sd"> learning algorithm, which has to be installed and patched for the purpose (see this</span>
<span class="sd"> `script &lt;https://github.com/HLT-ISTI/QuaPy/blob/master/prepare_svmperf.sh&gt;`_).</span>
<span class="sd"> This function is a wrapper around CC(SVMperf(svmperf_base, loss, C))</span>
<span class="sd"> :param svmperf_base: path to the folder containing the binary files of `SVM perf`; if set to None (default)</span>
<span class="sd"> this path will be obtained from qp.environ[&#39;SVMPERF_HOME&#39;]</span>
<span class="sd"> :param C: trade-off between training error and margin (default 0.01)</span>
<span class="sd"> :return: returns an instance of CC set to work with SVMperf (with loss and C set properly) as the</span>
<span class="sd"> underlying classifier</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">newELM</span><span class="p">(</span><span class="n">svmperf_base</span><span class="p">,</span> <span class="n">loss</span><span class="o">=</span><span class="s1">&#39;mae&#39;</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="n">C</span><span class="p">)</span></div>
<div class="viewcode-block" id="newSVMRAE">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.newSVMRAE">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">newSVMRAE</span><span class="p">(</span><span class="n">svmperf_base</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> SVM(KLD) is an Explicit Loss Minimization (ELM) quantifier set to optimize for the Relative Absolute Error as first</span>
<span class="sd"> used by `Moreo and Sebastiani, 2021 &lt;https://arxiv.org/abs/2011.02552&gt;`_.</span>
<span class="sd"> Equivalent to:</span>
<span class="sd"> &gt;&gt;&gt; CC(SVMperf(svmperf_base, loss=&#39;mrae&#39;, C=C))</span>
<span class="sd"> Quantifiers based on ELM represent a family of methods based on structured output learning;</span>
<span class="sd"> these quantifiers rely on classifiers that have been optimized using a quantification-oriented loss</span>
<span class="sd"> measure. This implementation relies on</span>
<span class="sd"> `Joachims SVM perf &lt;https://www.cs.cornell.edu/people/tj/svm_light/svm_perf.html&gt;`_ structured output</span>
<span class="sd"> learning algorithm, which has to be installed and patched for the purpose (see this</span>
<span class="sd"> `script &lt;https://github.com/HLT-ISTI/QuaPy/blob/master/prepare_svmperf.sh&gt;`_).</span>
<span class="sd"> This function is a wrapper around CC(SVMperf(svmperf_base, loss, C))</span>
<span class="sd"> :param svmperf_base: path to the folder containing the binary files of `SVM perf`; if set to None (default)</span>
<span class="sd"> this path will be obtained from qp.environ[&#39;SVMPERF_HOME&#39;]</span>
<span class="sd"> :param C: trade-off between training error and margin (default 0.01)</span>
<span class="sd"> :return: returns an instance of CC set to work with SVMperf (with loss and C set properly) as the</span>
<span class="sd"> underlying classifier</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">newELM</span><span class="p">(</span><span class="n">svmperf_base</span><span class="p">,</span> <span class="n">loss</span><span class="o">=</span><span class="s1">&#39;mrae&#39;</span><span class="p">,</span> <span class="n">C</span><span class="o">=</span><span class="n">C</span><span class="p">)</span></div>
<div class="viewcode-block" id="OneVsAllAggregative">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.OneVsAllAggregative">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">OneVsAllAggregative</span><span class="p">(</span><span class="n">OneVsAllGeneric</span><span class="p">,</span> <span class="n">AggregativeQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Allows any binary quantifier to perform quantification on single-label datasets.</span>
<span class="sd"> The method maintains one binary quantifier for each class, and then l1-normalizes the outputs so that the</span>
<span class="sd"> class prevelences sum up to 1.</span>
<span class="sd"> This variant was used, along with the :class:`EMQ` quantifier, in</span>
<span class="sd"> `Gao and Sebastiani, 2016 &lt;https://link.springer.com/content/pdf/10.1007/s13278-016-0327-z.pdf&gt;`_.</span>
<span class="sd"> :param binary_quantifier: a quantifier (binary) that will be employed to work on multiclass model in a</span>
<span class="sd"> one-vs-all manner (default PACC(LogitsticRegression()))</span>
<span class="sd"> :param n_jobs: number of parallel workers</span>
<span class="sd"> :param parallel_backend: the parallel backend for joblib (default &quot;loky&quot;); this is helpful for some quantifiers</span>
<span class="sd"> (e.g., ELM-based ones) that cannot be run with multiprocessing, since the temp dir they create during fit will</span>
<span class="sd"> is removed and no longer available at predict time.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">binary_quantifier</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">parallel_backend</span><span class="o">=</span><span class="s1">&#39;multiprocessing&#39;</span><span class="p">):</span>
<span class="k">if</span> <span class="n">binary_quantifier</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">binary_quantifier</span> <span class="o">=</span> <span class="n">PACC</span><span class="p">()</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">binary_quantifier</span><span class="p">,</span> <span class="n">BaseQuantifier</span><span class="p">),</span> \
<span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">binary_quantifier</span><span class="si">}</span><span class="s1"> does not seem to be a Quantifier&#39;</span>
<span class="k">assert</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">binary_quantifier</span><span class="p">,</span> <span class="n">AggregativeQuantifier</span><span class="p">),</span> \
<span class="sa">f</span><span class="s1">&#39;</span><span class="si">{</span><span class="n">binary_quantifier</span><span class="si">}</span><span class="s1"> does not seem to be of type Aggregative&#39;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">binary_quantifier</span> <span class="o">=</span> <span class="n">binary_quantifier</span>
<span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_njobs</span><span class="p">(</span><span class="n">n_jobs</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">parallel_backend</span> <span class="o">=</span> <span class="n">parallel_backend</span>
<div class="viewcode-block" id="OneVsAllAggregative.classify">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.OneVsAllAggregative.classify">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">classify</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> If the base quantifier is not probabilistic, returns a matrix of shape `(n,m,)` with `n` the number of</span>
<span class="sd"> instances and `m` the number of classes. The entry `(i,j)` is a binary value indicating whether instance</span>
<span class="sd"> `i` belongs to class `j`. The binary classifications are independent of each other, meaning that an instance</span>
<span class="sd"> can end up be attributed to 0, 1, or more classes.</span>
<span class="sd"> If the base quantifier is probabilistic, returns a matrix of shape `(n,m,2)` with `n` the number of instances</span>
<span class="sd"> and `m` the number of classes. The entry `(i,j,1)` (resp. `(i,j,0)`) is a value in [0,1] indicating the</span>
<span class="sd"> posterior probability that instance `i` belongs (resp. does not belong) to class `j`. The posterior</span>
<span class="sd"> probabilities are independent of each other, meaning that, in general, they do not sum up to one.</span>
<span class="sd"> :param X: array-like</span>
<span class="sd"> :return: `np.ndarray`</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">classif_predictions</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parallel</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_delayed_binary_classification</span><span class="p">,</span> <span class="n">X</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">binary_quantifier</span><span class="p">,</span> <span class="n">AggregativeSoftQuantifier</span><span class="p">):</span>
<span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">swapaxes</span><span class="p">(</span><span class="n">classif_predictions</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">classif_predictions</span><span class="o">.</span><span class="n">T</span></div>
<div class="viewcode-block" id="OneVsAllAggregative.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.OneVsAllAggregative.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">):</span>
<span class="n">prevalences</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parallel</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_delayed_binary_aggregate</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">)</span>
<span class="k">return</span> <span class="n">F</span><span class="o">.</span><span class="n">normalize_prevalence</span><span class="p">(</span><span class="n">prevalences</span><span class="p">)</span></div>
<div class="viewcode-block" id="OneVsAllAggregative.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.OneVsAllAggregative.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_parallel</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_delayed_binary_aggregate_fit</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_delayed_binary_classification</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">X</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict_binary_quantifiers</span><span class="p">[</span><span class="n">c</span><span class="p">]</span><span class="o">.</span><span class="n">classify</span><span class="p">(</span><span class="n">X</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_delayed_binary_aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">):</span>
<span class="c1"># the estimation for the positive class prevalence</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict_binary_quantifiers</span><span class="p">[</span><span class="n">c</span><span class="p">]</span><span class="o">.</span><span class="n">aggregate</span><span class="p">(</span><span class="n">classif_predictions</span><span class="p">[:,</span> <span class="n">c</span><span class="p">])[</span><span class="mi">1</span><span class="p">]</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_delayed_binary_aggregate_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="c1"># trains the aggregation function of the cth quantifier</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">dict_binary_quantifiers</span><span class="p">[</span><span class="n">c</span><span class="p">]</span><span class="o">.</span><span class="n">aggregation_fit</span><span class="p">(</span><span class="n">classif_predictions</span><span class="p">[:,</span> <span class="n">c</span><span class="p">],</span> <span class="n">labels</span> <span class="o">==</span> <span class="n">c</span><span class="p">)</span></div>
<div class="viewcode-block" id="AggregativeMedianEstimator">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeMedianEstimator">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">AggregativeMedianEstimator</span><span class="p">(</span><span class="n">BinaryQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> This method is a meta-quantifier that returns, as the estimated class prevalence values, the median of the</span>
<span class="sd"> estimation returned by differently (hyper)parameterized base quantifiers.</span>
<span class="sd"> The median of unit-vectors is only guaranteed to be a unit-vector for n=2 dimensions,</span>
<span class="sd"> i.e., in cases of binary quantification.</span>
<span class="sd"> :param base_quantifier: the base, binary quantifier</span>
<span class="sd"> :param random_state: a seed to be set before fitting any base quantifier (default None)</span>
<span class="sd"> :param param_grid: the grid or parameters towards which the median will be computed</span>
<span class="sd"> :param n_jobs: number of parallel workers</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">base_quantifier</span><span class="p">:</span> <span class="n">AggregativeQuantifier</span><span class="p">,</span> <span class="n">param_grid</span><span class="p">:</span> <span class="nb">dict</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">base_quantifier</span> <span class="o">=</span> <span class="n">base_quantifier</span>
<span class="bp">self</span><span class="o">.</span><span class="n">param_grid</span> <span class="o">=</span> <span class="n">param_grid</span>
<span class="bp">self</span><span class="o">.</span><span class="n">random_state</span> <span class="o">=</span> <span class="n">random_state</span>
<span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_njobs</span><span class="p">(</span><span class="n">n_jobs</span><span class="p">)</span>
<div class="viewcode-block" id="AggregativeMedianEstimator.get_params">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeMedianEstimator.get_params">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">get_params</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">deep</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">base_quantifier</span><span class="o">.</span><span class="n">get_params</span><span class="p">(</span><span class="n">deep</span><span class="p">)</span></div>
<div class="viewcode-block" id="AggregativeMedianEstimator.set_params">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeMedianEstimator.set_params">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">set_params</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">params</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">base_quantifier</span><span class="o">.</span><span class="n">set_params</span><span class="p">(</span><span class="o">**</span><span class="n">params</span><span class="p">)</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_delayed_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">with</span> <span class="n">qp</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">temp_seed</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">random_state</span><span class="p">):</span>
<span class="n">params</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">args</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">deepcopy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">base_quantifier</span><span class="p">)</span>
<span class="n">model</span><span class="o">.</span><span class="n">set_params</span><span class="p">(</span><span class="o">**</span><span class="n">params</span><span class="p">)</span>
<span class="n">model</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="k">return</span> <span class="n">model</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_delayed_fit_classifier</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">with</span> <span class="n">qp</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">temp_seed</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">random_state</span><span class="p">):</span>
<span class="n">cls_params</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">args</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">deepcopy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">base_quantifier</span><span class="p">)</span>
<span class="n">model</span><span class="o">.</span><span class="n">set_params</span><span class="p">(</span><span class="o">**</span><span class="n">cls_params</span><span class="p">)</span>
<span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">classifier_fit_predict</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="k">return</span> <span class="p">(</span><span class="n">model</span><span class="p">,</span> <span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_delayed_fit_aggregation</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="k">with</span> <span class="n">qp</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">temp_seed</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">random_state</span><span class="p">):</span>
<span class="p">((</span><span class="n">model</span><span class="p">,</span> <span class="n">predictions</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="n">q_params</span><span class="p">)</span> <span class="o">=</span> <span class="n">args</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">deepcopy</span><span class="p">(</span><span class="n">model</span><span class="p">)</span>
<span class="n">model</span><span class="o">.</span><span class="n">set_params</span><span class="p">(</span><span class="o">**</span><span class="n">q_params</span><span class="p">)</span>
<span class="n">model</span><span class="o">.</span><span class="n">aggregation_fit</span><span class="p">(</span><span class="n">predictions</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="k">return</span> <span class="n">model</span>
<div class="viewcode-block" id="AggregativeMedianEstimator.fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeMedianEstimator.fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">itertools</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_check_binary</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">base_quantifier</span><span class="p">,</span> <span class="n">AggregativeQuantifier</span><span class="p">):</span>
<span class="n">cls_configs</span><span class="p">,</span> <span class="n">q_configs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">model_selection</span><span class="o">.</span><span class="n">group_params</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">param_grid</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">cls_configs</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">models_preds</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">parallel</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_delayed_fit_classifier</span><span class="p">,</span>
<span class="p">((</span><span class="n">params</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="k">for</span> <span class="n">params</span> <span class="ow">in</span> <span class="n">cls_configs</span><span class="p">),</span>
<span class="n">seed</span><span class="o">=</span><span class="n">qp</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;_R_SEED&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span>
<span class="n">n_jobs</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span><span class="p">,</span>
<span class="n">asarray</span><span class="o">=</span><span class="kc">False</span>
<span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">base_quantifier</span>
<span class="n">model</span><span class="o">.</span><span class="n">set_params</span><span class="p">(</span><span class="o">**</span><span class="n">cls_configs</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="n">model</span><span class="o">.</span><span class="n">classifier_fit_predict</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
<span class="n">models_preds</span> <span class="o">=</span> <span class="p">[(</span><span class="n">model</span><span class="p">,</span> <span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">)]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">models</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">parallel</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_delayed_fit_aggregation</span><span class="p">,</span>
<span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="n">models_preds</span><span class="p">,</span> <span class="n">q_configs</span><span class="p">),</span>
<span class="n">seed</span><span class="o">=</span><span class="n">qp</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;_R_SEED&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span>
<span class="n">n_jobs</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span>
<span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">configs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">model_selection</span><span class="o">.</span><span class="n">expand_grid</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">param_grid</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">models</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">parallel</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_delayed_fit</span><span class="p">,</span>
<span class="p">((</span><span class="n">params</span><span class="p">,</span> <span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="k">for</span> <span class="n">params</span> <span class="ow">in</span> <span class="n">configs</span><span class="p">),</span>
<span class="n">seed</span><span class="o">=</span><span class="n">qp</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;_R_SEED&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span>
<span class="n">n_jobs</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span>
<span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span></div>
<span class="k">def</span><span class="w"> </span><span class="nf">_delayed_predict</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">):</span>
<span class="n">model</span><span class="p">,</span> <span class="n">instances</span> <span class="o">=</span> <span class="n">args</span>
<span class="k">return</span> <span class="n">model</span><span class="o">.</span><span class="n">predict</span><span class="p">(</span><span class="n">instances</span><span class="p">)</span>
<div class="viewcode-block" id="AggregativeMedianEstimator.predict">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.AggregativeMedianEstimator.predict">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">predict</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">instances</span><span class="p">):</span>
<span class="n">prev_preds</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">parallel</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_delayed_predict</span><span class="p">,</span>
<span class="p">((</span><span class="n">model</span><span class="p">,</span> <span class="n">instances</span><span class="p">)</span> <span class="k">for</span> <span class="n">model</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">models</span><span class="p">),</span>
<span class="n">seed</span><span class="o">=</span><span class="n">qp</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;_R_SEED&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span>
<span class="n">n_jobs</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span>
<span class="p">)</span>
<span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">median</span><span class="p">(</span><span class="n">prev_preds</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span></div>
</div>
<div class="viewcode-block" id="EDy">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EDy">[docs]</a>
<span class="k">class</span><span class="w"> </span><span class="nc">EDy</span><span class="p">(</span><span class="n">_EnergyDistanceCore</span><span class="p">,</span> <span class="n">AggregativeSoftQuantifier</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Energy Distance y (EDy), a posterior-space distribution-matching quantifier</span>
<span class="sd"> based on energy distance.</span>
<span class="sd"> The method represents each class by the posterior-probability vectors</span>
<span class="sd"> produced by a probabilistic classifier on validation data, and estimates the</span>
<span class="sd"> test prevalence vector by matching the test posterior distribution against</span>
<span class="sd"> the class-conditional validation distributions through an energy-distance</span>
<span class="sd"> objective solved as a quadratic program. The method is therefore another</span>
<span class="sd"> instance of the general mixture-matching view of quantification, but it</span>
<span class="sd"> operates directly on posterior vectors rather than on histogram summaries.</span>
<span class="sd"> This implementation works for binary and multiclass single-label</span>
<span class="sd"> quantification and relies on the optional ``quadprog`` dependency. It was</span>
<span class="sd"> adapted to QuaPy&#39;s current aggregative API from the original implementation</span>
<span class="sd"> available in `quantificationlib &lt;https://github.com/AICGijon/quantificationlib&gt;`_,</span>
<span class="sd"> and now shares its numerical core with the classifier-free</span>
<span class="sd"> :class:`quapy.method.non_aggregative.EDx` variant.</span>
<span class="sd"> The current implementation follows the energy-distance formulation discussed</span>
<span class="sd"> in:</span>
<span class="sd"> * Alberto Castaño, Laura Morán-Fernández, Jaime Alonso,</span>
<span class="sd"> Verónica Bolón-Canedo, Amparo Alonso-Betanzos, and Juan José del Coz.</span>
<span class="sd"> *An analysis of quantification methods based on matching distributions*.</span>
<span class="sd"> * Hideko Kawakubo, Marthinus Christoffel du Plessis, and Masashi Sugiyama</span>
<span class="sd"> (2016). *Computationally efficient class-prior estimation under class</span>
<span class="sd"> balance change using energy distance*. IEICE Transactions on Information</span>
<span class="sd"> and Systems, 99(1):176-186.</span>
<span class="sd"> :param classifier: a scikit-learn ``BaseEstimator``, or ``None`` to use</span>
<span class="sd"> ``qp.environ[&#39;DEFAULT_CLS&#39;]``</span>
<span class="sd"> :param fit_classifier: whether to train the learner (default ``True``).</span>
<span class="sd"> Set to ``False`` if the learner has already been trained outside the</span>
<span class="sd"> quantifier</span>
<span class="sd"> :param val_split: specification of the data used for generating validation</span>
<span class="sd"> posterior probabilities. This can be an integer (default ``5``) for</span>
<span class="sd"> k-fold cross-validation, a float in ``(0, 1)`` for a held-out split,</span>
<span class="sd"> or a tuple ``(X, y)`` with explicit validation data</span>
<span class="sd"> :param distance: distance used to compare posterior vectors. Valid string</span>
<span class="sd"> aliases are ``&#39;manhattan&#39;`` (default) and ``&#39;euclidean&#39;``; a custom</span>
<span class="sd"> callable compatible with pairwise-distance signatures can also be used</span>
<span class="sd"> :param n_jobs: number of parallel workers (default ``None``, meaning the</span>
<span class="sd"> value is taken from the environment)</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">classifier</span><span class="p">:</span> <span class="n">BaseEstimator</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="n">fit_classifier</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
<span class="n">val_split</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span>
<span class="n">distance</span><span class="p">:</span> <span class="n">Union</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Callable</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;manhattan&#39;</span><span class="p">,</span>
<span class="n">n_jobs</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">classifier</span><span class="p">,</span> <span class="n">fit_classifier</span><span class="p">,</span> <span class="n">val_split</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">distance</span> <span class="o">=</span> <span class="n">distance</span>
<span class="bp">self</span><span class="o">.</span><span class="n">n_jobs</span> <span class="o">=</span> <span class="n">qp</span><span class="o">.</span><span class="n">_get_njobs</span><span class="p">(</span><span class="n">n_jobs</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">train_n_cls_i_</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">train_distrib_</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">K_</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">G_</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">C_</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">b_</span> <span class="o">=</span> <span class="kc">None</span>
<span class="bp">self</span><span class="o">.</span><span class="n">a_</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">def</span><span class="w"> </span><span class="nf">_check_init_parameters</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_check_ed_init_parameters</span><span class="p">()</span>
<div class="viewcode-block" id="EDy.aggregation_fit">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EDy.aggregation_fit">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregation_fit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">classif_predictions</span><span class="p">,</span> <span class="n">labels</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Estimate the class-conditional posterior distributions on validation</span>
<span class="sd"> data and pre-compute the quadratic-program parameters that depend only</span>
<span class="sd"> on the training side.</span>
<span class="sd"> In EDy, the validation posteriors are not discretized into histograms.</span>
<span class="sd"> Instead, each class is represented by the cloud of posterior vectors</span>
<span class="sd"> observed for that class, and these clouds are then compared through the</span>
<span class="sd"> selected pairwise distance.</span>
<span class="sd"> :param classif_predictions: posterior probabilities returned by the</span>
<span class="sd"> classifier on validation data</span>
<span class="sd"> :param labels: true labels associated to each posterior vector</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">posteriors</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">(</span><span class="n">classif_predictions</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
<span class="n">labels</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">(</span><span class="n">labels</span><span class="p">)</span>
<span class="n">train_distrib</span> <span class="o">=</span> <span class="p">[</span><span class="n">posteriors</span><span class="p">[</span><span class="n">labels</span> <span class="o">==</span> <span class="n">class_</span><span class="p">]</span> <span class="k">for</span> <span class="n">class_</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">classes_</span><span class="p">]</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fit_energy_model</span><span class="p">(</span><span class="n">train_distrib</span><span class="p">)</span></div>
<div class="viewcode-block" id="EDy.aggregate">
<a class="viewcode-back" href="../../../quapy.method.html#quapy.method.aggregative.EDy.aggregate">[docs]</a>
<span class="k">def</span><span class="w"> </span><span class="nf">aggregate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">posteriors</span><span class="p">:</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">):</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;Estimate the prevalence vector for a test sample.</span>
<span class="sd"> :param posteriors: posterior probabilities returned by the classifier</span>
<span class="sd"> for the instances in the test sample</span>
<span class="sd"> :return: a prevalence vector of shape ``(n_classes,)``</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">posteriors</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">(</span><span class="n">posteriors</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="nb">float</span><span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_predict_energy</span><span class="p">(</span><span class="n">posteriors</span><span class="p">)</span></div>
</div>
<span class="c1"># ---------------------------------------------------------------</span>
<span class="c1"># imports</span>
<span class="c1"># ---------------------------------------------------------------</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">.</span><span class="w"> </span><span class="kn">import</span> <span class="n">_threshold_optim</span>
<span class="n">T50</span> <span class="o">=</span> <span class="n">_threshold_optim</span><span class="o">.</span><span class="n">T50</span>
<span class="n">MAX</span> <span class="o">=</span> <span class="n">_threshold_optim</span><span class="o">.</span><span class="n">MAX</span>
<span class="n">X</span> <span class="o">=</span> <span class="n">_threshold_optim</span><span class="o">.</span><span class="n">X</span>
<span class="n">MS</span> <span class="o">=</span> <span class="n">_threshold_optim</span><span class="o">.</span><span class="n">MS</span>
<span class="n">MS2</span> <span class="o">=</span> <span class="n">_threshold_optim</span><span class="o">.</span><span class="n">MS2</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">.</span><span class="w"> </span><span class="kn">import</span> <span class="n">_kdey</span>
<span class="n">KDEyML</span> <span class="o">=</span> <span class="n">_kdey</span><span class="o">.</span><span class="n">KDEyML</span>
<span class="n">KDEyHD</span> <span class="o">=</span> <span class="n">_kdey</span><span class="o">.</span><span class="n">KDEyHD</span>
<span class="n">KDEyCS</span> <span class="o">=</span> <span class="n">_kdey</span><span class="o">.</span><span class="n">KDEyCS</span>
<span class="c1"># ---------------------------------------------------------------</span>
<span class="c1"># aliases</span>
<span class="c1"># ---------------------------------------------------------------</span>
<span class="n">ClassifyAndCount</span> <span class="o">=</span> <span class="n">CC</span>
<span class="n">AdjustedClassifyAndCount</span> <span class="o">=</span> <span class="n">ACC</span>
<span class="n">ProbabilisticClassifyAndCount</span> <span class="o">=</span> <span class="n">PCC</span>
<span class="n">ProbabilisticAdjustedClassifyAndCount</span> <span class="o">=</span> <span class="n">PACC</span>
<span class="n">ExpectationMaximizationQuantifier</span> <span class="o">=</span> <span class="n">EMQ</span>
<span class="n">SLD</span> <span class="o">=</span> <span class="n">EMQ</span>
<span class="n">DistributionMatchingY</span> <span class="o">=</span> <span class="n">DMy</span>
<span class="n">EnergyDistanceY</span> <span class="o">=</span> <span class="n">EDy</span>
<span class="n">HellingerDistanceY</span> <span class="o">=</span> <span class="n">HDy</span>
<span class="n">HistoricalHDy</span> <span class="o">=</span> <span class="n">DMy</span><span class="o">.</span><span class="n">HDy</span>
<span class="n">MedianSweep</span> <span class="o">=</span> <span class="n">MS</span>
<span class="n">MedianSweep2</span> <span class="o">=</span> <span class="n">MS2</span>
</pre></div>
</article>
<footer class="prev-next-footer d-print-none">
<div class="prev-next-area">
</div>
</footer>
</div>
</div>
<footer class="bd-footer-content">
</footer>
</main>
</div>
</div>
<!-- Scripts loaded after <body> so the DOM is not blocked -->
<script defer src="../../../_static/scripts/bootstrap.js?digest=90905a2f556bf617f1a9"></script>
<script defer src="../../../_static/scripts/pydata-sphinx-theme.js?digest=90905a2f556bf617f1a9"></script>
<footer class="bd-footer">
<div class="bd-footer__inner bd-page-width">
<div class="footer-items__start">
<div class="footer-item">
<p class="copyright">
© Copyright 2024, Alejandro Moreo.
<br/>
</p>
</div>
<div class="footer-item">
<p class="sphinx-version">
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 9.0.4.
<br/>
</p>
</div>
</div>
<div class="footer-items__end">
<div class="footer-item">
<p class="theme-version">
<!-- # L10n: Setting the PST URL as an argument as this does not need to be localized -->
Built with the <a href="https://pydata-sphinx-theme.readthedocs.io/en/stable/index.html">PyData Sphinx Theme</a> 0.20.0.
</p></div>
</div>
</div>
</footer>
</body>
</html>