Giter Club home page Giter Club logo

pykoop's People

Contributors

sdahdah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

pykoop's Issues

Improve unit tests

Some unit tests are slow and require Mosek, so they can't be run server-side. Only a subset of the tests are currently run. Unit tests need to be reorganized so that the most possible tests can be run at each merge.

Incorrect scoring with `NaN` entries

Scoring does not work correctly when X has NaN entries. Example to reproduce:

"""Example of how to use the Koopman pipeline."""

from sklearn.preprocessing import MaxAbsScaler, StandardScaler

import pykoop
import numpy as np


def example_pipeline_simple() -> None:
    """Demonstrate how to use the Koopman pipeline."""
    # Get example mass-spring-damper data
    eg = pykoop.example_data_msd()

    # Create pipeline
    kp = pykoop.KoopmanPipeline(
        lifting_functions=[
            ('pl', pykoop.PolynomialLiftingFn(order=10)),
        ],
        regressor=pykoop.Edmd(alpha=0),
    )

    # Fit the pipeline
    kp.fit(
        eg['X_train'],
        n_inputs=eg['n_inputs'],
        episode_feature=eg['episode_feature'],
    )

    # Predict using the pipeline
    X_pred = kp.predict_trajectory(eg['x0_valid'], eg['u_valid'])
    print(np.any(np.isnan(X_pred)))

    # Score using the pipeline
    score = kp.score(eg['X_valid'])
    print(score)


if __name__ == '__main__':
    example_pipeline_simple()

Solution is to implement the scikit-learn convention:

error_score 'raise' or numeric, default=np.nan
Value to assign to the score if an error occurs in estimator
fitting. If set to ‘raise’, the error is raised. If a numeric value
is given, FitFailedWarning is raised. This parameter does not affect
the refit step, which will always raise the error.

Also delete `doc/diagram/.gitignire`

Also delete useless doc/diagram/.gitignire file

Despite the branch name, the PDF sources do not need to be added because they can be generated form the Python script.

Examples are not properly run by `pytest`

Ever since numbers have been prefixed to the example file names, they are not correctly run by pytest. Need to either edit the pytest.ini pattern or rename the files.

`score_trajectory()` can return score worse than `error_score`

Expected Behavior

error_score should be the worst possible score returned by score_trajectory.

Actual Behavior

If error_score=-1, for example, a diverging trajectory could return a better score than a really bad bounded trajectory. This is problematic when pykoop is paired with a hyperparameter optimizer like skopt.BayesSearchCV.

Implement Hermite/Lagrange/Legendre polynomial lifting functions

Refactor PolynomialLiftingFn to support products of other polynomials instead
of just monomials. For example, instead of x1^2 * x2, allow H2(x1) * H1(x2)
where Hx is the xth Hermite polynomial.

This can be achieved by removing the wrapped scikit-learn polynomial
transformer and using a custom one with similar functionality. Specifically the
powers_ matrix.

`score_trajectory()` sometimes returns `-inf` instead of `error_score`

Expected Behavior

pykoop.score_trajectory() should always return a finite float (no np.inf or np.nan), return the error_score, or raise a ValueError.

Actual Behavior

If the inputs to pykoop.score_trajectory() are finite, but overflow during the calculation of the score, then the function will return -np.inf instead of error_score. This can cause external hyperparameter optimizers to crash.

Steps to Reproduce the Problem

import numpy as np

import pykoop

X_predicted = np.array([
    [1e-2, 1e-3],
]).T

X_expected = np.array([
    [1e150, 1e250],
]).T

score = pykoop.score_trajectory(X_predicted, X_expected, episode_feature=False)

print(score)

Specifications

  • Package version: 1.1.3
  • Python version: 3.10.9
  • Platform: Arch Linux

Automate plotting

Automate plotting of common tasks like prediction error comparison.

Either my_pipeline.plot_whatever() or pykoop.plot_whatever(my_pipeline). TBD.

Allow creation of a `KoopmanRegressor` object from a Koopman matrix

Desired Behavior

Given a Koopman matrix U, create a KoopmanRegressor object that functions as if it was fit with pykoop.

Proposed Solution

Along these lines:

class DataRegressor(KoopmanRegressor):

    def __init__(self, U):
        self.U = U
        
    def fit(X, y):
        self.n_features_in_ = ...
        self.coef_ = U.copy()

Update MyPy Optional typing

This project has been using implicit optional so far, but that's deprecated now. Need to change

def f(x: np.ndarray = None)

to

def f(x: Optional[np.ndarray] = None)

While we're at it, consider changing np.ndarray to ArrayLike.

Refine release procedure

I forgot to bump the version in the source code from v1.1.0 to v1.1.1. PyPi rejected the release, but Zenodo accepted it. When fixing this, PyPi accepted the new package, but Zenodo rejected it. So I had to draft v1.1.2 to make everything consistent again.

I need to look into an automated check to prevent this from happening. If not that, then at least a written checklist to follow.

Add option to skip rescaling of original states

Scale only lifted states without rescaling original states? Maybe the PolynomialLiftingFn should handle its own scaling.

Either way, it's becoming more clear that normalizing and standardizing should be done outside of the KoopmanPipeline, or within each lifting function as needed. But having a "normalizing" lifting function is a bit awkward since we want to keep the original state inside the lifted state unmodified.

Binder only supports Python 3.7

Expected Behavior

Binder should load when clicking the link in the README.

Actual Behavior

Binder does not load because it requires Python 3.7.

`KoopmanLiftingFn.transform()` does not check if output is finite

KoopmanLiftingFn.transform() can return non-finite outputs. I'm not sure if I should add a check before returning the transformed values, or if I should check for this elsewhere. Warnings are already raised by NumPy, so I think it's better to leave it alone for the time being.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.