Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge Develop for a new release #322

Merged
merged 55 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
9a53353
Add support for tensorflow backend which allows for differentiability…
chaithyagr Apr 14, 2021
514d0f7
Fix 115 (#116)
chaithyagr Apr 16, 2021
063a611
Minor bug fix, remove elif (#124)
chaithyagr Apr 20, 2021
1d2bd7b
Add tests for modopt.base.backend and fix minute bug uncovered (#126)
chaithyagr Apr 21, 2021
46b718a
Release cleanup (#128)
sfarrens Apr 21, 2021
4035f51
Unpin package dependencies (#189)
sfarrens Nov 26, 2021
353ef4d
Add Gradient descent algorithms (#196)
paquiteau Dec 10, 2021
643411f
Release cleanup (#198)
sfarrens Dec 17, 2021
c000118
resolved conflicts
sfarrens Dec 17, 2021
bc72be4
fixed index.rst
sfarrens Dec 17, 2021
4c7d9da
Merge branch 'master' of https://github.com/CEA-COSMIC/ModOpt into de…
sfarrens Dec 17, 2021
e1bd5d7
fixed conflict
sfarrens Dec 17, 2021
736e067
Merge branch 'master' of https://github.com/CEA-COSMIC/ModOpt into de…
sfarrens Dec 17, 2021
65e24f1
Fast Singular Value Thresholding (#209)
paquiteau Feb 7, 2022
b55f5a6
added writeable input data array feature for benchopt (#213)
sfarrens Mar 21, 2022
a04bb29
removed flake8 limit
sfarrens Apr 8, 2022
7632e07
updated patch version
sfarrens Apr 8, 2022
ad4c496
[lint] pydocstyle compliance. (#228)
paquiteau May 2, 2022
5dd6001
Power method: fix #211 (#212)
paquiteau Jun 9, 2022
75456f1
Switch from progressbar to tqdm (#231)
paquiteau Jun 9, 2022
0590907
Update README for tqdm dependency (#240)
paquiteau Jun 17, 2022
96f361d
add small help for the metric argument. (#241)
paquiteau Jun 17, 2022
11c260d
add implementation for admm and fast admm.
paquiteau Nov 15, 2022
3e0bef3
add Goldstein ref.
paquiteau Nov 15, 2022
83459ad
WPS compliance.
paquiteau Nov 15, 2022
23776d9
Abstract class for cost function.
paquiteau Nov 15, 2022
38fefba
add custom cost operator for admm.
paquiteau Nov 15, 2022
3d71044
fix WPS compliance.
paquiteau Nov 15, 2022
efcf301
Ci update (#268)
paquiteau Jan 2, 2023
eeb8d17
Test rewrite (#266)
paquiteau Jan 3, 2023
71af711
removed unnormalised Gaussian kernel option and corresponding test
sfarrens Mar 14, 2023
8046d10
Restrict scikit-image version for testing
sfarrens Mar 14, 2023
f8e5926
added fix for basic test suite
sfarrens Mar 14, 2023
0137a38
set behaviour for different astropy versions
sfarrens Mar 15, 2023
a961c3c
updated docstring for gaussian_kernel
sfarrens Mar 15, 2023
3f8dbee
Merge pull request #287 from sfarrens/272-gaussian-kernel-fix
paquiteau Mar 15, 2023
2d7da27
Use example scripts as tests. (#277)
paquiteau Mar 15, 2023
2b71870
Merge branch 'develop' into admm
paquiteau Mar 15, 2023
6d698bb
fix: specify data_range for ssim.
paquiteau Apr 19, 2023
53a6bdd
typos.
paquiteau May 11, 2023
8dfa8a3
feat(test): add test for admm.
paquiteau May 11, 2023
6d4e780
feat(admm): improve doc.
paquiteau May 11, 2023
843e65b
refactor: rename abstract cost to CostParent.
paquiteau May 11, 2023
676ecc0
feat: add test for fast admm.
paquiteau May 11, 2023
9af7fc4
feat(admm): improve docstrings.
paquiteau May 11, 2023
fd0a4f9
style: remove extra line.c
paquiteau May 11, 2023
0e03c90
feat: make POGM more memory efficient.
paquiteau Jul 26, 2023
7c94ede
feat: add a dummy cost for the identity operator.
paquiteau Jul 26, 2023
6f73f7b
Merge pull request #292 from paquiteau/develop
paquiteau Sep 25, 2023
767e930
Merge pull request #263 from paquiteau/admm
paquiteau Oct 7, 2023
869af9a
feat: create a linear operator module, add wavelet transform.
paquiteau Nov 15, 2023
906ddc4
feat: add test case for wavelet transform.
paquiteau Nov 15, 2023
15c8798
Merge pull request #315 from paquiteau/wavelet
paquiteau Jan 10, 2024
28ec91e
Merge branch 'master' into develop
chaithyagr Jan 19, 2024
13c1534
Update setup.py
chaithyagr Jan 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/cd-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ jobs:
- name: Set up Conda with Python 3.8
uses: conda-incubator/setup-miniconda@v2
with:
auto-update-conda: true
python-version: 3.8
auto-activate-base: false
python-version: "3.8"

- name: Install dependencies
shell: bash -l {0}
Expand Down
21 changes: 6 additions & 15 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,12 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: [3.8]
python-version: ["3.10"]

steps:
- name: Checkout
uses: actions/checkout@v2

- name: Report WPS Errors
uses: wemake-services/wemake-python-styleguide@0.14.1
continue-on-error: true
with:
reporter: 'github-pr-review'
path: './modopt'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Conda with Python ${{ matrix.python-version }}
uses: conda-incubator/setup-miniconda@v2
with:
Expand All @@ -52,7 +43,7 @@ jobs:
python -m pip install --upgrade pip
python -m pip install -r develop.txt
python -m pip install -r docs/requirements.txt
python -m pip install astropy scikit-image scikit-learn
python -m pip install astropy "scikit-image<0.20" scikit-learn matplotlib
python -m pip install tensorflow>=2.4.1
python -m pip install twine
python -m pip install .
Expand All @@ -61,7 +52,7 @@ jobs:
shell: bash -l {0}
run: |
export PATH=/usr/share/miniconda/bin:$PATH
python setup.py test
pytest -n 2

- name: Save Test Results
if: always()
Expand Down Expand Up @@ -98,7 +89,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: [3.6, 3.7, 3.9]
python-version: ["3.7", "3.8", "3.9"]

steps:
- name: Checkout
Expand All @@ -117,11 +108,11 @@ jobs:
python --version
python -m pip install --upgrade pip
python -m pip install -r develop.txt
python -m pip install astropy scikit-image scikit-learn
python -m pip install astropy "scikit-image<0.20" scikit-learn matplotlib
python -m pip install .

- name: Run Tests
shell: bash -l {0}
run: |
export PATH=/usr/share/miniconda/bin:$PATH
python setup.py test
pytest -n 2
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ instance/
docs/_build/
docs/source/fortuna.*
docs/source/scripts.*
docs/source/auto_examples/
docs/source/*.nblink

# PyBuilder
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ All packages required by ModOpt should be installed automatically. Optional pack
In order to run the code in this repository the following packages must be
installed:

* [Python](https://www.python.org/) [> 3.6]
* [Python](https://www.python.org/) [> 3.7]
* [importlib_metadata](https://importlib-metadata.readthedocs.io/en/latest/) [==3.7.0]
* [Numpy](http://www.numpy.org/) [==1.19.5]
* [Scipy](http://www.scipy.org/) [==1.5.4]
* [Progressbar 2](https://progressbar-2.readthedocs.io/) [==3.53.1]
* [tqdm](https://tqdm.github.io/) [>=4.64.0]

### Optional Packages

Expand Down
13 changes: 8 additions & 5 deletions develop.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
coverage>=5.5
flake8>=4
nose>=1.3.7
pytest>=6.2.2
pytest-raises>=0.10
pytest-cases>= 3.6
pytest-xdist>= 3.0.1
pytest-cov>=2.11.1
pytest-pep8>=1.0.6
pytest-emoji>=0.2.0
pytest-flake8>=1.0.7
wemake-python-styleguide>=0.15.2
pydocstyle==6.1.1
pytest-pydocstyle>=2.2.0
black
isort
pytest-black
1 change: 1 addition & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ numpydoc==1.1.0
sphinx==4.3.1
sphinxcontrib-bibtex==2.4.1
sphinxawesome-theme==3.2.1
sphinx-gallery==0.11.1
13 changes: 13 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
'nbsphinx',
'nbsphinx_link',
'numpydoc',
"sphinx_gallery.gen_gallery"
]

# Include module names for objects
Expand Down Expand Up @@ -145,6 +146,18 @@
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
html_show_copyright = True



# -- Options for Sphinx Gallery ----------------------------------------------

sphinx_gallery_conf = {
"examples_dirs": ["../../modopt/examples/"],
"filename_pattern": "/example_",
"ignore_pattern": r"/(__init__|conftest)\.py",
}



# -- Options for nbshpinx output ------------------------------------------


Expand Down
12 changes: 12 additions & 0 deletions docs/source/refs.bib
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,15 @@ @article{zou2005
journal = {Journal of the Royal Statistical Society Series B},
doi = {10.1111/j.1467-9868.2005.00527.x}
}

@article{Goldstein2014,
author={Goldstein, Tom and O’Donoghue, Brendan and Setzer, Simon and Baraniuk, Richard},
year={2014},
month={Jan},
pages={1588–1623},
title={Fast Alternating Direction Optimization Methods},
journal={SIAM Journal on Imaging Sciences},
volume={7},
ISSN={1936-4954},
doi={10/gdwr49},
}
1 change: 1 addition & 0 deletions docs/source/toc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

plugin_example
notebooks
auto_examples/index

.. toctree::
:hidden:
Expand Down
5 changes: 5 additions & 0 deletions modopt/examples/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
========
Examples
========

This is a collection of Python scripts demonstrating the use of ModOpt.
10 changes: 10 additions & 0 deletions modopt/examples/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
"""EXAMPLES.

This module contains documented examples that demonstrate the usage of various
ModOpt tools.

These examples also serve as integration tests for various methods.

:Author: Pierre-Antoine Comby

"""
46 changes: 46 additions & 0 deletions modopt/examples/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""TEST CONFIGURATION.

This module contains methods for configuring the testing of the example
scripts.

:Author: Pierre-Antoine Comby

Notes
-----
Based on:
https://stackoverflow.com/questions/56807698/how-to-run-script-as-pytest-test

"""
from pathlib import Path
import runpy
import pytest

def pytest_collect_file(path, parent):
"""Pytest hook.

Create a collector for the given path, or None if not relevant.
The new node needs to have the specified parent as parent.
"""
p = Path(path)
if p.suffix == '.py' and 'example' in p.name:
return Script.from_parent(parent, path=p, name=p.name)


class Script(pytest.File):
"""Script files collected by pytest."""

def collect(self):
"""Collect the script as its own item."""
yield ScriptItem.from_parent(self, name=self.name)

class ScriptItem(pytest.Item):
"""Item script collected by pytest."""

def runtest(self):
"""Run the script as a test."""
runpy.run_path(str(self.path))

def repr_failure(self, excinfo):
"""Return only the error traceback of the script."""
excinfo.traceback = excinfo.traceback.cut(path=self.path)
return super().repr_failure(excinfo)
153 changes: 153 additions & 0 deletions modopt/examples/example_lasso_forward_backward.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# noqa: D205
"""
Solving the LASSO Problem with the Forward Backward Algorithm.
==============================================================

This an example to show how to solve an example LASSO Problem
using the Forward-Backward Algorithm.

In this example we are going to use:
- Modopt Operators (Linear, Gradient, Proximal)
- Modopt implementation of solvers
- Modopt Metric API.
TODO: add reference to LASSO paper.
"""

import numpy as np
import matplotlib.pyplot as plt

from modopt.opt.algorithms import ForwardBackward, POGM
from modopt.opt.cost import costObj
from modopt.opt.linear import LinearParent, Identity
from modopt.opt.gradient import GradBasic
from modopt.opt.proximity import SparseThreshold
from modopt.math.matrix import PowerMethod
from modopt.math.stats import mse

# %%
# Here we create a instance of the LASSO Problem

BETA_TRUE = np.array(
[3.0, 1.5, 0, 0, 2, 0, 0, 0]
) # 8 original values from lLASSO Paper
DIM = len(BETA_TRUE)


rng = np.random.default_rng()
sigma_noise = 1
obs = 20
# create a measurement matrix with decaying covariance matrix.
cov = 0.4 ** abs((np.arange(DIM) * np.ones((DIM, DIM))).T - np.arange(DIM))
x = rng.multivariate_normal(np.zeros(DIM), cov, obs)

y = x @ BETA_TRUE
y_noise = y + (sigma_noise * np.random.standard_normal(obs))


# %%
# Next we create Operators for solving the problem.

# MatrixOperator could also work here.
lin_op = LinearParent(lambda b: x @ b, lambda bb: x.T @ bb)
grad_op = GradBasic(y_noise, op=lin_op.op, trans_op=lin_op.adj_op)

prox_op = SparseThreshold(Identity(), 1, thresh_type="soft")

# %%
# In order to get the best convergence rate, we first determine the Lipschitz constant of the gradient Operator
#

calc_lips = PowerMethod(grad_op.trans_op_op, 8, data_type="float32", auto_run=True)
lip = calc_lips.spec_rad
print("lipschitz constant:", lip)

# %%
# Solving using FISTA algorithm
# -----------------------------
#
# TODO: Add description/Reference of FISTA.

cost_op_fista = costObj([grad_op, prox_op], verbose=False)

fb_fista = ForwardBackward(
np.zeros(8),
beta_param=1 / lip,
grad=grad_op,
prox=prox_op,
cost=cost_op_fista,
metric_call_period=1,
auto_iterate=False, # Just to give us the pleasure of doing things by ourself.
)

fb_fista.iterate()

# %%
# After the run we can have a look at the results

print(fb_fista.x_final)
mse_fista = mse(fb_fista.x_final, BETA_TRUE)
plt.stem(fb_fista.x_final, label="estimation", linefmt="C0-")
plt.stem(BETA_TRUE, label="reference", linefmt="C1-")
plt.legend()
plt.title(f"FISTA Estimation MSE={mse_fista:.4f}")

# sphinx_gallery_start_ignore
assert mse(fb_fista.x_final, BETA_TRUE) < 1
# sphinx_gallery_end_ignore


# %%
# Solving Using the POGM Algorithm
# --------------------------------
#
# TODO: Add description/Reference to POGM.


cost_op_pogm = costObj([grad_op, prox_op], verbose=False)

fb_pogm = POGM(
np.zeros(8),
np.zeros(8),
np.zeros(8),
np.zeros(8),
beta_param=1 / lip,
grad=grad_op,
prox=prox_op,
cost=cost_op_pogm,
metric_call_period=1,
auto_iterate=False, # Just to give us the pleasure of doing things by ourself.
)

fb_pogm.iterate()

# %%
# After the run we can have a look at the results

print(fb_pogm.x_final)
mse_pogm = mse(fb_pogm.x_final, BETA_TRUE)

plt.stem(fb_pogm.x_final, label="estimation", linefmt="C0-")
plt.stem(BETA_TRUE, label="reference", linefmt="C1-")
plt.legend()
plt.title(f"FISTA Estimation MSE={mse_pogm:.4f}")
#
# sphinx_gallery_start_ignore
assert mse(fb_pogm.x_final, BETA_TRUE) < 1

# %%
# Comparing the Two algorithms
# ----------------------------

plt.figure()
plt.semilogy(cost_op_fista._cost_list, label="FISTA convergence")
plt.semilogy(cost_op_pogm._cost_list, label="POGM convergence")
plt.xlabel("iterations")
plt.ylabel("Cost Function")
plt.legend()
plt.show()


# %%
# We can see that the two algorithm converges quickly, and POGM requires less iterations.
# However the POGM iterations are more costly, so a proper benchmark with time measurement is needed.
# Check the benchopt benchmark for more details.
Loading
Loading