From d97c52ab8264f3a594237a2570bd6f27d051b271 Mon Sep 17 00:00:00 2001 From: statmlben Date: Tue, 3 Sep 2024 17:40:29 +0800 Subject: [PATCH] update doc --- doc/_templates/autoapi/index.rst | 10 - doc/source/_static/css/label.css | 16 + doc/source/_templates/autoapi/index.rst | 12 + doc/source/_templates/autoapi/macros.rst | 68 ++++ .../_templates/autoapi/python/class.rst | 71 ++++ .../_templates/autoapi/python/module.rst | 112 ++++++ doc/source/autoapi/index.rst | 9 + doc/source/autoapi/rehline/index.rst | 325 ++++++++++++++++++ doc/source/benchmark.rst | 10 +- doc/source/conf.py | 79 +++-- doc/source/tutorials.rst | 7 +- rehline/_base.py | 2 +- rehline/_class.py | 51 ++- 13 files changed, 720 insertions(+), 52 deletions(-) delete mode 100644 doc/_templates/autoapi/index.rst create mode 100644 doc/source/_static/css/label.css create mode 100644 doc/source/_templates/autoapi/index.rst create mode 100644 doc/source/_templates/autoapi/macros.rst create mode 100644 doc/source/_templates/autoapi/python/class.rst create mode 100644 doc/source/_templates/autoapi/python/module.rst create mode 100644 doc/source/autoapi/index.rst create mode 100644 doc/source/autoapi/rehline/index.rst diff --git a/doc/_templates/autoapi/index.rst b/doc/_templates/autoapi/index.rst deleted file mode 100644 index 78035e1..0000000 --- a/doc/_templates/autoapi/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -API Reference -============= - -This page contains auto-generated API reference documentation [#f1]_. - -.. toctree:: - - /autoapi/rehline/index - -.. [#f1] Created with `sphinx-autoapi `_ \ No newline at end of file diff --git a/doc/source/_static/css/label.css b/doc/source/_static/css/label.css new file mode 100644 index 0000000..5fdd5cb --- /dev/null +++ b/doc/source/_static/css/label.css @@ -0,0 +1,16 @@ +.summarylabel { + background-color: var(--color-foreground-secondary); + color: var(--color-background-secondary); + font-size: 70%; + padding-left: 2px; + padding-right: 2px; + border-radius: 3px; + vertical-align: 15%; + padding-bottom: 2px; + filter: opacity(40%); +} + + +table.summarytable { + width: 100%; +} \ No newline at end of file diff --git a/doc/source/_templates/autoapi/index.rst b/doc/source/_templates/autoapi/index.rst new file mode 100644 index 0000000..802ea8a --- /dev/null +++ b/doc/source/_templates/autoapi/index.rst @@ -0,0 +1,12 @@ +API Reference +============= + +This page contains auto-generated API reference documentation. + +.. toctree:: + :titlesonly: + + {% for page in pages %} + {{ page.include_path }} + {% endfor %} + diff --git a/doc/source/_templates/autoapi/macros.rst b/doc/source/_templates/autoapi/macros.rst new file mode 100644 index 0000000..7b8051c --- /dev/null +++ b/doc/source/_templates/autoapi/macros.rst @@ -0,0 +1,68 @@ +{# AutoApiSummary replacement macro #} +{# +The intent of this macro is to replace the autoapisummary directive with the following +improvements: +1) Method signature is generated without typing annotation regardless of the value of + `autodoc_typehints` +2) Properties are treated like attribute (but labelled as properties). +3) Label are added as summary prefix to indicate if the member is a property, class + method, or static method. + +Copyright: Antoine Beyeler, 2022 +License: MIT +#} + +{# Renders an object's name with a proper reference and optional signature. + +The signature is re-generated from obj.obj.args, which is undocumented but is the +only way to have a type-less signature if `autodoc_typehints` is `signature` or +`both`. #} +{% macro _render_item_name(obj, sig=False) -%} +:py:obj:`{{ obj.name }} <{{ obj.id }}>` + {%- if sig -%} + \ ( + {%- for arg in obj.obj.args -%} + {%- if arg[0] %}{{ arg[0]|replace('*', '\*') }}{% endif -%}{{ arg[1] -}} + {%- if not loop.last %}, {% endif -%} + {%- endfor -%} + ){%- endif -%} +{%- endmacro %} + + +{# Generates a single object optionally with a signature and a labe. #} +{% macro _item(obj, sig=False, label='') %} + * - {{ _render_item_name(obj, sig) }} + - {% if label %}:summarylabel:`{{ label }}` {% endif %}{% if obj.summary %}{{ obj.summary }}{% else %}\-{% endif +%} +{% endmacro %} + + + +{# Generate an autosummary-like table with the provided members. #} +{% macro auto_summary(objs, title='') -%} + +.. list-table:: {{ title }} + :header-rows: 0 + :widths: auto + :class: summarytable {#- apply CSS class to customize styling +#} + + {% for obj in objs -%} + {#- should the full signature be used? -#} + {%- set sig = (obj.type in ['method', 'function'] and not 'property' in obj.properties) -%} + + {#- compute label -#} + {%- if 'property' in obj.properties -%} + {%- set label = 'prop' -%} + {%- elif 'classmethod' in obj.properties -%} + {%- set label = 'class' -%} + {%- elif 'abstractmethod' in obj.properties -%} + {%- set label = 'abc' -%} + {%- elif 'staticmethod' in obj.properties -%} + {%- set label = 'static' -%} + {%- else -%} + {%- set label = '' -%} + {%- endif -%} + + {{- _item(obj, sig=sig, label=label) -}} + {%- endfor -%} + +{% endmacro %} diff --git a/doc/source/_templates/autoapi/python/class.rst b/doc/source/_templates/autoapi/python/class.rst new file mode 100644 index 0000000..6f24503 --- /dev/null +++ b/doc/source/_templates/autoapi/python/class.rst @@ -0,0 +1,71 @@ +{% import 'macros.rst' as macros %} + +{% if obj.display %} +.. py:{{ obj.type }}:: {{ obj.short_name }}{% if obj.args %}({{ obj.args }}){% endif %} +{% for (args, return_annotation) in obj.overloads %} + {{ " " * (obj.type | length) }} {{ obj.short_name }}{% if args %}({{ args }}){% endif %} +{% endfor %} + + + {% if obj.bases %} + {% if "show-inheritance" in autoapi_options %} + Bases: {% for base in obj.bases %}{{ base|link_objs }}{% if not loop.last %}, {% endif %}{% endfor %} + {% endif %} + + + {% if "show-inheritance-diagram" in autoapi_options and obj.bases != ["object"] %} + .. autoapi-inheritance-diagram:: {{ obj.obj["full_name"] }} + :parts: 1 + {% if "private-members" in autoapi_options %} + :private-bases: + {% endif %} + + {% endif %} + {% endif %} + {% if obj.docstring %} + {{ obj.docstring|indent(3) }} + {% endif %} + {% if "inherited-members" in autoapi_options %} + {% set visible_classes = obj.classes|selectattr("display")|list %} + {% else %} + {% set visible_classes = obj.classes|rejectattr("inherited")|selectattr("display")|list %} + {% endif %} + {% for klass in visible_classes %} + {{ klass.render()|indent(3) }} + {% endfor %} + {% if "inherited-members" in autoapi_options %} + {% set visible_attributes = obj.attributes|selectattr("display")|list %} + {% else %} + {% set visible_attributes = obj.attributes|rejectattr("inherited")|selectattr("display")|list %} + {% endif %} + {% if "inherited-members" in autoapi_options %} + {% set visible_methods = obj.methods|selectattr("display")|list %} + {% else %} + {% set visible_methods = obj.methods|rejectattr("inherited")|selectattr("display")|list %} + {% endif %} + + {% if visible_methods or visible_attributes %} + Overview + ======== + + {% set summary_methods = visible_methods|rejectattr("properties", "contains", "property")|list %} + {% set summary_attributes = visible_attributes + visible_methods|selectattr("properties", "contains", "property")|list %} + {% if summary_attributes %} + {{ macros.auto_summary(summary_attributes, title="Attributes")|indent(3) }} + {% endif %} + + {% if summary_methods %} + {{ macros.auto_summary(summary_methods, title="Methods")|indent(3) }} + {% endif %} + + Members + ======= + + {% for attribute in visible_attributes %} + {{ attribute.render()|indent(3) }} + {% endfor %} + {% for method in visible_methods %} + {{ method.render()|indent(3) }} + {% endfor %} + {% endif %} +{% endif %} diff --git a/doc/source/_templates/autoapi/python/module.rst b/doc/source/_templates/autoapi/python/module.rst new file mode 100644 index 0000000..32143c3 --- /dev/null +++ b/doc/source/_templates/autoapi/python/module.rst @@ -0,0 +1,112 @@ +{% import 'macros.rst' as macros %} + +{% if not obj.display %} +:orphan: + +{% endif %} +{{ obj.name }} +{{ "=" * obj.name|length }} + +.. py:module:: {{ obj.name }} + +{% if obj.docstring %} +.. autoapi-nested-parse:: + + {{ obj.docstring|indent(3) }} + +{% endif %} + +{% block subpackages %} +{% set visible_subpackages = obj.subpackages|selectattr("display")|list %} +{% if visible_subpackages %} +Subpackages +----------- +.. toctree:: + :titlesonly: + :maxdepth: 3 + +{% for subpackage in visible_subpackages %} + {{ subpackage.short_name }}/index.rst +{% endfor %} + + +{% endif %} +{% endblock %} +{% block submodules %} +{% set visible_submodules = obj.submodules|selectattr("display")|list %} +{% if visible_submodules %} +Submodules +---------- +.. toctree:: + :titlesonly: + :maxdepth: 1 + +{% for submodule in visible_submodules %} + {{ submodule.short_name }}/index.rst +{% endfor %} + + +{% endif %} +{% endblock %} +{% block content %} +{% if obj.all is not none %} +{% set visible_children = obj.children|selectattr("display")|selectattr("short_name", "in", obj.all)|list %} +{% elif obj.type is equalto("package") %} +{% set visible_children = obj.children|selectattr("display")|list %} +{% else %} +{% set visible_children = obj.children|selectattr("display")|rejectattr("imported")|list %} +{% endif %} +{% if visible_children %} +Overview +-------- + +{% set visible_classes = visible_children|selectattr("type", "equalto", "class")|list %} +{% set visible_functions = visible_children|selectattr("type", "equalto", "function")|list %} +{% set visible_attributes = visible_children|selectattr("type", "equalto", "data")|list %} +{% if "show-module-summary" in autoapi_options and (visible_classes or visible_functions) %} +{% block classes scoped %} +{% if visible_classes %} +{{ macros.auto_summary(visible_classes, title="Classes") }} +{% endif %} +{% endblock %} + +{% block functions scoped %} +{% if visible_functions %} +{{ macros.auto_summary(visible_functions, title="Function") }} +{% endif %} +{% endblock %} + +{% block attributes scoped %} +{% if visible_attributes %} +{{ macros.auto_summary(visible_attributes, title="Attributes") }} +{% endif %} +{% endblock %} +{% endif %} + +{% if visible_classes %} +Classes +------- +{% for obj_item in visible_classes %} +{{ obj_item.render()|indent(0) }} +{% endfor %} +{% endif %} + +{% if visible_functions %} +Functions +--------- +{% for obj_item in visible_functions %} +{{ obj_item.render()|indent(0) }} +{% endfor %} +{% endif %} + +{% if visible_attributes %} +Attributes +---------- +{% for obj_item in visible_attributes %} +{{ obj_item.render()|indent(0) }} +{% endfor %} +{% endif %} + + +{% endif %} +{% endblock %} diff --git a/doc/source/autoapi/index.rst b/doc/source/autoapi/index.rst new file mode 100644 index 0000000..57a725f --- /dev/null +++ b/doc/source/autoapi/index.rst @@ -0,0 +1,9 @@ +API Reference +============= + +This page contains auto-generated API reference documentation. + +.. toctree:: + :titlesonly: + + /autoapi/rehline/index diff --git a/doc/source/autoapi/rehline/index.rst b/doc/source/autoapi/rehline/index.rst new file mode 100644 index 0000000..146db75 --- /dev/null +++ b/doc/source/autoapi/rehline/index.rst @@ -0,0 +1,325 @@ + +rehline +======= + +.. py:module:: rehline + + +Overview +-------- + +.. list-table:: Classes + :header-rows: 0 + :widths: auto + :class: summarytable + + * - :py:obj:`ReHLine ` + - ReHLine Minimization. + * - :py:obj:`plqERM_Ridge ` + - Empirical Risk Minimization (ERM) with a piecewise linear-quadratic (PLQ) objective with a ridge penalty. + + + + +Classes +------- + +.. py:class:: ReHLine(C=1.0, U=np.empty(shape=(0, 0)), V=np.empty(shape=(0, 0)), Tau=np.empty(shape=(0, 0)), S=np.empty(shape=(0, 0)), T=np.empty(shape=(0, 0)), A=np.empty(shape=(0, 0)), b=np.empty(shape=0), max_iter=1000, tol=0.0001, shrink=1, verbose=0, trace_freq=100) + + Bases: :py:obj:`rehline._base._BaseReHLine`, :py:obj:`sklearn.base.BaseEstimator` + + ReHLine Minimization. + + .. math:: + + \min_{\mathbf{\beta} \in \mathbb{R}^d} \sum_{i=1}^n \sum_{l=1}^L \text{ReLU}( u_{li} \mathbf{x}_i^\intercal \mathbf{\beta} + v_{li}) + \sum_{i=1}^n \sum_{h=1}^H {\text{ReHU}}_{\tau_{hi}}( s_{hi} \mathbf{x}_i^\intercal \mathbf{\beta} + t_{hi}) + \frac{1}{2} \| \mathbf{\beta} \|_2^2, \\ \text{ s.t. } + \mathbf{A} \mathbf{\beta} + \mathbf{b} \geq \mathbf{0}, + + where :math:`\mathbf{U} = (u_{li}),\mathbf{V} = (v_{li}) \in \mathbb{R}^{L \times n}` + and :math:`\mathbf{S} = (s_{hi}),\mathbf{T} = (t_{hi}),\mathbf{\tau} = (\tau_{hi}) \in \mathbb{R}^{H \times n}` + are the ReLU-ReHU loss parameters, and :math:`(\mathbf{A},\mathbf{b})` are the constraint parameters. + + Parameters + ---------- + C : float, default=1.0 + Regularization parameter. The strength of the regularization is + inversely proportional to C. Must be strictly positive. + + U, V: array of shape (L, n_samples), default=np.empty(shape=(0, 0)) + The parameters pertaining to the ReLU part in the loss function. + + Tau, S, T: array of shape (H, n_samples), default=np.empty(shape=(0, 0)) + The parameters pertaining to the ReHU part in the loss function. + + A: array of shape (K, n_features), default=np.empty(shape=(0, 0)) + The coefficient matrix in the linear constraint. + + b: array of shape (K, ), default=np.empty(shape=0) + The intercept vector in the linear constraint. + + verbose : int, default=0 + Enable verbose output. Note that this setting takes advantage of a + per-process runtime setting in liblinear that, if enabled, may not work + properly in a multithreaded context. + + max_iter : int, default=1000 + The maximum number of iterations to be run. + + Attributes + ---------- + coef\_ : array-like + The optimized model coefficients. + + n_iter\_ : int + The number of iterations performed by the ReHLine solver. + + opt_result\_ : object + The optimization result object. + + dual_obj\_ : array-like + The dual objective function values. + + primal_obj\_ : array-like + The primal objective function values. + + Examples + -------- + + >>> ## test SVM on simulated dataset + >>> import numpy as np + >>> from rehline import ReHLine + + >>> # simulate classification dataset + >>> n, d, C = 1000, 3, 0.5 + >>> np.random.seed(1024) + >>> X = np.random.randn(1000, 3) + >>> beta0 = np.random.randn(3) + >>> y = np.sign(X.dot(beta0) + np.random.randn(n)) + + >>> # Usage of ReHLine + >>> n, d = X.shape + >>> U = -(C*y).reshape(1,-1) + >>> L = U.shape[0] + >>> V = (C*np.array(np.ones(n))).reshape(1,-1) + >>> clf = ReHLine(loss={'name': 'svm'}, C=C) + >>> clf.U, clf.V = U, V + >>> clf.fit(X=X) + >>> print('sol privided by rehline: %s' %clf.coef_) + >>> sol privided by rehline: [ 0.7410154 -0.00615574 2.66990408] + >>> print(clf.decision_function([[.1,.2,.3]])) + >>> [0.87384162] + + References + ---------- + .. [1] `Dai, B., Qiu, Y,. (2023). ReHLine: Regularized Composite ReLU-ReHU Loss Minimization with Linear Computation and Linear Convergence `_ + + + Overview + ======== + + + .. list-table:: Methods + :header-rows: 0 + :widths: auto + :class: summarytable + + * - :py:obj:`fit `\ (X, sample_weight) + - Fit the model based on the given training data. + * - :py:obj:`decision_function `\ (X) + - The decision function evaluated on the given dataset + + + Members + ======= + + .. py:method:: fit(X, sample_weight=None) + + Fit the model based on the given training data. + + Parameters + ---------- + + X: {array-like} of shape (n_samples, n_features) + Training vector, where `n_samples` is the number of samples and + `n_features` is the number of features. + + sample_weight : array-like of shape (n_samples,), default=None + Array of weights that are assigned to individual + samples. If not provided, then each sample is given unit weight. + + Returns + ------- + self : object + An instance of the estimator. + + + .. py:method:: decision_function(X) + + The decision function evaluated on the given dataset + + Parameters + ---------- + X : array-like of shape (n_samples, n_features) + The data matrix. + + Returns + ------- + ndarray of shape (n_samples, ) + Returns the decision function of the samples. + + + + +.. py:class:: plqERM_Ridge(loss, constraint=[], C=1.0, U=np.empty(shape=(0, 0)), V=np.empty(shape=(0, 0)), Tau=np.empty(shape=(0, 0)), S=np.empty(shape=(0, 0)), T=np.empty(shape=(0, 0)), A=np.empty(shape=(0, 0)), b=np.empty(shape=0), max_iter=1000, tol=0.0001, shrink=1, verbose=0, trace_freq=100) + + Bases: :py:obj:`rehline._base._BaseReHLine`, :py:obj:`sklearn.base.BaseEstimator` + + Empirical Risk Minimization (ERM) with a piecewise linear-quadratic (PLQ) objective with a ridge penalty. + + .. math:: + + \min_{\mathbf{\beta} \in \mathbb{R}^d} \sum_{i=1}^n \text{PLQ}(y_i, \mathbf{x}_i^T \mathbf{\beta}) + \frac{1}{2} \| \mathbf{\beta} \|_2^2, \ \text{ s.t. } \ + \mathbf{A} \mathbf{\beta} + \mathbf{b} \geq \mathbf{0}, + + The function supports various loss functions, including: + - 'hinge', 'svm' or 'SVM' + - 'check' or 'quantile' or 'quantile regression' or 'QR' + - 'sSVM' or 'smooth SVM' or 'smooth hinge' + - 'TV' + - 'huber' or 'Huber' + - 'SVR' or 'svr' + + The following constraint types are supported: + * 'nonnegative' or '>=0': A non-negativity constraint. + * 'fair' or 'fairness': A fairness constraint. + * 'custom': A custom constraint, where the user must provide the constraint matrix 'A' and vector 'b'. + + Parameters + ---------- + loss : dict + A dictionary specifying the loss function parameters. + + constraint : list of dict + A list of dictionaries, where each dictionary represents a constraint. + Each dictionary must contain a 'name' key, which specifies the type of constraint. + + C : float, default=1.0 + Regularization parameter. The strength of the regularization is + inversely proportional to C. Must be strictly positive. + `C` will be absorbed by the ReHLine parameters when `self.make_ReLHLoss` is conducted. + + verbose : int, default=0 + Enable verbose output. Note that this setting takes advantage of a + per-process runtime setting in liblinear that, if enabled, may not work + properly in a multithreaded context. + + max_iter : int, default=1000 + The maximum number of iterations to be run. + + U, V: array of shape (L, n_samples), default=np.empty(shape=(0, 0)) + The parameters pertaining to the ReLU part in the loss function. + + Tau, S, T: array of shape (H, n_samples), default=np.empty(shape=(0, 0)) + The parameters pertaining to the ReHU part in the loss function. + + A: array of shape (K, n_features), default=np.empty(shape=(0, 0)) + The coefficient matrix in the linear constraint. + + b: array of shape (K, ), default=np.empty(shape=0) + The intercept vector in the linear constraint. + + Attributes + ---------- + coef\_ : array-like + The optimized model coefficients. + + n_iter\_ : int + The number of iterations performed by the ReHLine solver. + + opt_result\_ : object + The optimization result object. + + dual_obj\_ : array-like + The dual objective function values. + + primal_obj\_ : array-like + The primal objective function values. + + Methods + ------- + fit(X, y, sample_weight=None) + Fit the model based on the given training data. + + decision_function(X) + The decision function evaluated on the given dataset. + + Notes + ----- + The `plqERM_Ridge` class is a subclass of `_BaseReHLine` and `BaseEstimator`, which suggests that it is part of a larger framework for implementing ReHLine algorithms. + + + + Overview + ======== + + + .. list-table:: Methods + :header-rows: 0 + :widths: auto + :class: summarytable + + * - :py:obj:`fit `\ (X, y, sample_weight) + - Fit the model based on the given training data. + * - :py:obj:`decision_function `\ (X) + - The decision function evaluated on the given dataset + + + Members + ======= + + .. py:method:: fit(X, y, sample_weight=None) + + Fit the model based on the given training data. + + Parameters + ---------- + + X: {array-like} of shape (n_samples, n_features) + Training vector, where `n_samples` is the number of samples and + `n_features` is the number of features. + + y : array-like of shape (n_samples,) + The target variable. + + sample_weight : array-like of shape (n_samples,), default=None + Array of weights that are assigned to individual + samples. If not provided, then each sample is given unit weight. + + Returns + ------- + self : object + An instance of the estimator. + + + + + .. py:method:: decision_function(X) + + The decision function evaluated on the given dataset + + Parameters + ---------- + X : array-like of shape (n_samples, n_features) + The data matrix. + + Returns + ------- + ndarray of shape (n_samples, ) + Returns the decision function of the samples. + + + + + + + diff --git a/doc/source/benchmark.rst b/doc/source/benchmark.rst index b837ff1..9b00182 100644 --- a/doc/source/benchmark.rst +++ b/doc/source/benchmark.rst @@ -9,15 +9,15 @@ We have developed a benchmark for evaluating the performance of optimization met +-------------+--------------------------------------------------------+ | Problem | Results | +=============+========================================================+ - | FairSVM_ | `Result <./_static/benchmark/benchmark_FairSVM.html>`_ | + | FairSVM_ | `Result <./_static/benchmark/benchmark_FairSVM.html>`__| +-------------+--------------------------------------------------------+ - | ElasticQR_ | `Result <./_static/benchmark/benchmark_QR.html>`_ | + | ElasticQR_ | `Result <./_static/benchmark/benchmark_QR.html>`__ | +-------------+--------------------------------------------------------+ - | RidgeHuber_ | `Result <./_static/benchmark/benchmark_Huber.html>`_ | + | RidgeHuber_ | `Result <./_static/benchmark/benchmark_Huber.html>`__ | +-------------+--------------------------------------------------------+ - | SVM_ | `Result <./_static/benchmark/benchmark_SVM.html>`_ | + | SVM_ | `Result <./_static/benchmark/benchmark_SVM.html>`__ | +-------------+--------------------------------------------------------+ - | sSVM_ | `Result <./_static/benchmark/benchmark_sSVM.html>`_ | + | sSVM_ | `Result <./_static/benchmark/benchmark_sSVM.html>`__ | +-------------+--------------------------------------------------------+ .. _FairSVM: https://github.com/softmin/ReHLine-benchmark/tree/main/benchmark_FairSVM diff --git a/doc/source/conf.py b/doc/source/conf.py index 275ea1e..3b86657 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -47,20 +47,68 @@ # ones. master_doc = 'index' extensions = [ - 'sphinx.ext.autodoc', + # 'sphinx.ext.autodoc', 'autoapi.extension', # "sphinx.ext.linkcode", - # "sphinx.ext.intersphinx", + "sphinx.ext.intersphinx", "sphinx_autodoc_typehints", - 'sphinx.ext.autosummary', + # 'sphinx.ext.autosummary', # 'sphinx_gallery.gen_gallery', - 'numpydoc', + # 'numpydoc', 'nbsphinx', ] + +# -- Plausible support +ENABLE_PLAUSIBLE = os.environ.get("READTHEDOCS_VERSION_TYPE", "") in ["branch", "tag"] +html_context = {"enable_plausible": ENABLE_PLAUSIBLE} + +# -- autoapi configuration --------------------------------------------------- +autodoc_typehints = "signature" # autoapi respects this + +autoapi_type = "python" autoapi_dirs = ['../../rehline/'] +autoapi_template_dir = "_templates/autoapi" +autoapi_options = [ + "members", + "undoc-members", + "show-inheritance", + "show-module-summary", + "imported-members", +] +autoapi_keep_files = True + + +# -- custom auto_summary() macro --------------------------------------------- +def contains(seq, item): + """Jinja2 custom test to check existence in a container. + + Example of use: + {% set class_methods = methods|selectattr("properties", "contains", "classmethod") %} + + Related doc: https://jinja.palletsprojects.com/en/3.1.x/api/#custom-tests + """ + return item in seq -autosummary_generate = True -numpydoc_show_class_members = False + +def prepare_jinja_env(jinja_env) -> None: + """Add `contains` custom test to Jinja environment.""" + jinja_env.tests["contains"] = contains + + +autoapi_prepare_jinja_env = prepare_jinja_env + +# Custom role for labels used in auto_summary() tables. +rst_prolog = """ +.. role:: summarylabel +""" + +# Related custom CSS +html_css_files = [ + "css/label.css", +] + +# autosummary_generate = True +# numpydoc_show_class_members = False nbsphinx_execute = 'never' nbsphinx_allow_errors = True # autodoc_mock_imports = ['numpy'] @@ -78,22 +126,12 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -# html_theme = 'renku' -# html_logo = "logo.png" # html_theme_path = [hachibee_sphinx_theme.get_html_themes_path()] -# html_theme = 'karma_sphinx_theme' -# html_theme = 'sphinx_book_theme' -# html_theme = 'python_docs_theme' -# html_theme = 'sphinx_material' -# html_theme = 'insegel' html_theme = 'furo' -# html_theme = 'yummy_sphinx_theme' -# html_theme = 'groundwork' # html_permalinks_icon = 'ยง' -# html_theme = 'insipid' # html_permalinks_icon = 'alpha' # html_theme = 'sphinxawesome_theme' @@ -115,14 +153,11 @@ # 'css/custom.css', # ] -def skip_submodules(app, what, name, obj, skip, options): - if what == "module": +def autoapi_skip_members(app, what, name, obj, skip, options): + if what == "attribute": skip = True return skip - def setup(sphinx): - sphinx.connect("autoapi-skip-member", skip_submodules) + sphinx.connect("autoapi-skip-member", autoapi_skip_members) -autoapi_template_dir = "_templates/autoapi" -# autoapi_add_toctree_entry = False \ No newline at end of file diff --git a/doc/source/tutorials.rst b/doc/source/tutorials.rst index fcbc63a..9bf7915 100644 --- a/doc/source/tutorials.rst +++ b/doc/source/tutorials.rst @@ -20,7 +20,7 @@ and ridge regularized Huber minimization (RidgeHuber). .. image:: ./figs/tab.png Solving PLQ ERMs -------------------- +---------------- Loss **** @@ -97,4 +97,7 @@ constraint - | ``loss_name``: 'SVR' / 'svr' | ``epsilon`` (*float*): 0.1 | - | *Example:* ``loss = {'name': 'svr', 'epsilon': 0.1}`` \ No newline at end of file + | *Example:* ``loss = {'name': 'svr', 'epsilon': 0.1}`` + +manual ReHLine +-------------- \ No newline at end of file diff --git a/rehline/_base.py b/rehline/_base.py index b4ed573..144bd4b 100644 --- a/rehline/_base.py +++ b/rehline/_base.py @@ -48,7 +48,7 @@ class _BaseReHLine(BaseEstimator): """ - def __init__(self, C=1., + def __init__(self, *, C=1., U=np.empty(shape=(0,0)), V=np.empty(shape=(0,0)), Tau=np.empty(shape=(0,0)), S=np.empty(shape=(0,0)), T=np.empty(shape=(0,0)), diff --git a/rehline/_class.py b/rehline/_class.py index 73802b6..76ea4d9 100644 --- a/rehline/_class.py +++ b/rehline/_class.py @@ -57,13 +57,20 @@ class ReHLine(_BaseReHLine, BaseEstimator): Attributes ---------- + coef\_ : array-like + The optimized model coefficients. + + n_iter\_ : int + The number of iterations performed by the ReHLine solver. - coef_ : array of shape (n_features,) - Weights assigned to the features (coefficients in the primal - problem). + opt_result\_ : object + The optimization result object. - n_iter_: int - Maximum number of iterations run across all classes. + dual_obj\_ : array-like + The dual objective function values. + + primal_obj\_ : array-like + The primal objective function values. Examples -------- @@ -103,7 +110,17 @@ def __init__(self, C=1., S=np.empty(shape=(0,0)), T=np.empty(shape=(0,0)), A=np.empty(shape=(0,0)), b=np.empty(shape=(0)), max_iter=1000, tol=1e-4, shrink=1, verbose=0, trace_freq=100): - _BaseReHLine.__init__(self, C, U, V, Tau, S, T, A, b) + self.C = C + self.U = U + self.V = V + self.S = S + self.T = T + self.Tau = Tau + self.A = A + self.b = b + self.L = U.shape[0] + self.H = S.shape[0] + self.K = A.shape[0] self.max_iter = max_iter self.tol = tol self.shrink = shrink @@ -251,19 +268,19 @@ class plqERM_Ridge(_BaseReHLine, BaseEstimator): Attributes ---------- - coef_ : array-like + coef\_ : array-like The optimized model coefficients. - n_iter_ : int + n_iter\_ : int The number of iterations performed by the ReHLine solver. - opt_result_ : object + opt_result\_ : object The optimization result object. - dual_obj_ : array-like + dual_obj\_ : array-like The dual objective function values. - primal_obj_ : array-like + primal_obj\_ : array-like The primal objective function values. Methods @@ -288,9 +305,19 @@ def __init__(self, loss, S=np.empty(shape=(0,0)), T=np.empty(shape=(0,0)), A=np.empty(shape=(0,0)), b=np.empty(shape=(0)), max_iter=1000, tol=1e-4, shrink=1, verbose=0, trace_freq=100): - _BaseReHLine.__init__(self, C, U, V, Tau, S, T, A, b) self.loss = loss self.constraint = constraint + self.C = C + self.U = U + self.V = V + self.S = S + self.T = T + self.Tau = Tau + self.A = A + self.b = b + self.L = U.shape[0] + self.H = S.shape[0] + self.K = A.shape[0] self.max_iter = max_iter self.tol = tol self.shrink = shrink