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

Sklearn-like functionality and HyperSpy compatibility #33

Merged
merged 2 commits into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ This document records all notable changes to
This project adheres to `PEP 440 -- Version Identification
and Dependency Specification <https://www.python.org/dev/peps/pep-0440/>`_.

0.3.3 ()
---------

- Providing sklearn-like features
- Added fit_transform method that acts like the `sklearn NMF fit_transform
method <https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.NMF.html#sklearn.decomposition.NMF.fit>`_.
- Returns C_
- Added components_ attribute, which is synonymous with ST_
- Added fit_kwargs parameter to McrAR that will pass forward to the fit and fit_transform methods
- One can, e.g., set the ST or C guess from instantiation instead of calling fit or fit_transform

0.3.2 (19-06-25)
----------------

Expand Down
6 changes: 3 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
.. -*- mode: rst -*-

.. image:: https://travis-ci.com/CCampJr/pyMCR.svg?branch=master
.. image:: https://travis-ci.com/CCampJr/pyMCR.svg?branch=0.3.X
:alt: Travis CI Status
:target: https://travis-ci.com/CCampJr/pyMCR

.. image:: https://ci.appveyor.com/api/projects/status/ajld1bj7jo4oweio/branch/master?svg=true
.. image:: https://ci.appveyor.com/api/projects/status/ajld1bj7jo4oweio/branch/0.3.X?svg=true
:alt: AppVeyor CI Status
:target: https://ci.appveyor.com/project/CCampJr/pyMCR

.. image:: https://codecov.io/gh/CCampJr/pyMCR/branch/master/graph/badge.svg
.. image:: https://codecov.io/gh/CCampJr/pyMCR/branch/0.3.X/graph/badge.svg
:alt: Codecov
:target: https://codecov.io/gh/CCampJr/pyMCR

Expand Down
71 changes: 69 additions & 2 deletions pymcr/mcr.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
""" MCR Main Class for Computation"""
import sys as _sys
import copy as _copy

import numpy as _np
import logging as _logging
Expand Down Expand Up @@ -30,6 +31,9 @@ class McrAR:
Instantiated regression class (or string, see Notes) for calculating
the S^T matrix

fit_kwargs : dict
kwargs sent to fit and fit_transform methods

c_fit_kwargs : dict
kwargs sent to c_regr.fit method

Expand Down Expand Up @@ -78,6 +82,9 @@ class McrAR:
Most recently calculated S^T matrix (that did not cause a tolerance
failure)

components_ : ndarray [n_targets, n_features]
Synonym for ST_, providing sklearn like compatibility

C_opt_ : ndarray [n_samples, n_targets]
[Optimal] C matrix for lowest err attribute

Expand Down Expand Up @@ -131,8 +138,8 @@ class McrAR:

"""

def __init__(self, c_regr=OLS(), st_regr=OLS(), c_fit_kwargs={},
st_fit_kwargs={}, c_constraints=[ConstraintNonneg()],
def __init__(self, c_regr=OLS(), st_regr=OLS(), fit_kwargs={},
c_fit_kwargs={}, st_fit_kwargs={}, c_constraints=[ConstraintNonneg()],
st_constraints=[ConstraintNonneg()],
max_iter=50, err_fcn=mse,
tol_increase=0.0, tol_n_increase=10, tol_err_change=None,
Expand All @@ -142,6 +149,8 @@ def __init__(self, c_regr=OLS(), st_regr=OLS(), c_fit_kwargs={},
Multivariate Curve Resolution - Alternating Regression
"""

self.fit_kwargs = fit_kwargs

self.max_iter = max_iter

self.tol_increase = tol_increase
Expand Down Expand Up @@ -282,6 +291,13 @@ def fit(self, D, C=None, ST=None, st_fix=None, c_fix=None, c_first=True,
Notes
-----

- Parameters to fit will SUPERCEDE anything in fit_kwargs, if provided during McrAR
instantiation.
- Note that providing C (or ST) to fit_kwargs and providing ST (or C) to fit or
fit_transform will raise an error.
- When in doubt, clear fit_kwargs via self.fit_kwargs = {}
- Does not affect verbose or c_first parameters

- pyMCR (>= 0.3.1) uses the native Python logging module
rather than print statements; thus, to see the messages, one will
need to log-to-file or stream to stdout. More info is available in
Expand All @@ -294,6 +310,31 @@ def fit(self, D, C=None, ST=None, st_fix=None, c_fix=None, c_first=True,
else:
_logger.setLevel(_logging.INFO)

if self.fit_kwargs:
temp = self.fit_kwargs.get('C')
if (temp is not None) & (C is None):
C = temp

temp = self.fit_kwargs.get('ST')
if (temp is not None) & (ST is None):
ST = temp

temp = self.fit_kwargs.get('st_fix')
if (temp is not None) & (st_fix is None):
st_fix = temp

temp = self.fit_kwargs.get('c_fix')
if (temp is not None) & (c_fix is None):
c_fix = temp

temp = self.fit_kwargs.get('post_iter_fcn')
if (temp is not None) & (post_iter_fcn is None):
post_iter_fcn = temp

temp = self.fit_kwargs.get('post_half_fcn')
if (temp is not None) & (post_iter_fcn is None):
post_half_fcn = temp

# Ensure only C or ST provided
if (C is None) & (ST is None):
raise TypeError('C or ST estimate must be provided')
Expand Down Expand Up @@ -513,6 +554,32 @@ def fit(self, D, C=None, ST=None, st_fix=None, c_fix=None, c_first=True,
self.exit_tol_err_change = True
break

def fit_transform(self, D, **kwargs):
"""
This performs the same purpose as the fit method, but returns the C_ matrix.
Really, it's just to enable sklearn-expectant APIs compatible with pyMCR.

It is recommended to use the fit method and retrieve your results from C_ and ST_

See documentation for the fit method

Returns
--------

C_ : ndarray
C-matrix is returned

"""

self.fit(D, **kwargs)

return self.C_

@property
def components_(self):
""" This is just provided for sklearn-like functionality """

return self.ST_

if __name__ == '__main__': # pragma: no cover
# PyMCR uses the Logging facility to capture messaging
Expand Down
Loading