HOBIT 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- HOBIT/HOBIT.py +71 -0
- HOBIT/__init__.py +1 -0
- hobit-1.0.0.dist-info/METADATA +78 -0
- hobit-1.0.0.dist-info/RECORD +5 -0
- hobit-1.0.0.dist-info/WHEEL +4 -0
HOBIT/HOBIT.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import logging
|
|
3
|
+
import optuna
|
|
4
|
+
from sklearn.base import BaseEstimator, TransformerMixin
|
|
5
|
+
from sklearn.linear_model import LinearRegression
|
|
6
|
+
|
|
7
|
+
optuna.logging.set_verbosity(optuna.logging.WARNING)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RegressionForTrigonometric(BaseEstimator, TransformerMixin):
|
|
11
|
+
def __init__(self, omega_range=(0, 10), phi_range=(-np.pi, np.pi)):
|
|
12
|
+
self.omega_range = omega_range
|
|
13
|
+
self.phi_range = phi_range
|
|
14
|
+
self.model = LinearRegression()
|
|
15
|
+
self.best_parameters = {}
|
|
16
|
+
|
|
17
|
+
def opt_trig_params(self, X, y, **kwargs):
|
|
18
|
+
# Accept max_evals (legacy hyperopt name) or n_trials (optuna name)
|
|
19
|
+
n_trials = kwargs.pop('max_evals', kwargs.pop('n_trials', 100))
|
|
20
|
+
|
|
21
|
+
def objective(trial):
|
|
22
|
+
omega = trial.suggest_float('omega', self.omega_range[0], self.omega_range[1])
|
|
23
|
+
phi = trial.suggest_float('phi', self.phi_range[0], self.phi_range[1])
|
|
24
|
+
return float(np.mean((self.a0 + self.a1 * self.trig_func(omega * X + phi) - y) ** 2))
|
|
25
|
+
|
|
26
|
+
logging.debug('Performing TPE algorithm to find optimal omega and phi')
|
|
27
|
+
study = optuna.create_study(direction='minimize', sampler=optuna.samplers.TPESampler())
|
|
28
|
+
study.optimize(objective, n_trials=n_trials)
|
|
29
|
+
return study.best_params
|
|
30
|
+
|
|
31
|
+
def _fit_trig_params(self, X, y, **kwargs):
|
|
32
|
+
self.a1 = (y.max() - y.min()) / 2.
|
|
33
|
+
self.a0 = y.mean()
|
|
34
|
+
trig_params = self.opt_trig_params(X, y, **kwargs)
|
|
35
|
+
self.best_parameters = trig_params
|
|
36
|
+
|
|
37
|
+
def _transform_params(self, X):
|
|
38
|
+
omega = self.best_parameters['omega'] * np.ones(len(X))
|
|
39
|
+
phi = self.best_parameters['phi'] * np.ones(len(X))
|
|
40
|
+
x_new = self.trig_func(omega * X + phi)
|
|
41
|
+
x_new = x_new[:, np.newaxis]
|
|
42
|
+
return x_new
|
|
43
|
+
|
|
44
|
+
def _fit(self, X, y, trig_func='cos', **kwargs):
|
|
45
|
+
if trig_func == 'cos':
|
|
46
|
+
self.trig_func = np.cos
|
|
47
|
+
elif trig_func == 'sin':
|
|
48
|
+
self.trig_func = np.sin
|
|
49
|
+
else:
|
|
50
|
+
raise Exception('trig_func must be sin or cos.')
|
|
51
|
+
|
|
52
|
+
self._fit_trig_params(X, y, **kwargs)
|
|
53
|
+
X_transf = self._transform_params(X)
|
|
54
|
+
self.model.fit(X_transf, y)
|
|
55
|
+
self.best_parameters['intercept'] = self.model.intercept_
|
|
56
|
+
self.best_parameters['amplitude'] = self.model.coef_[0]
|
|
57
|
+
return self
|
|
58
|
+
|
|
59
|
+
def predict(self, X):
|
|
60
|
+
X_transf = self._transform_params(X)
|
|
61
|
+
ypred = self.model.predict(X_transf)
|
|
62
|
+
return ypred
|
|
63
|
+
|
|
64
|
+
def fit_sin(self, X, y, **kwargs):
|
|
65
|
+
if self.phi_range == (-np.pi, np.pi):
|
|
66
|
+
logging.debug('The defined domain of Sine function is (0, 2*pi)')
|
|
67
|
+
self.phi_range = (0, 2 * np.pi)
|
|
68
|
+
return self._fit(X, y, trig_func='sin', **kwargs)
|
|
69
|
+
|
|
70
|
+
def fit_cos(self, X, y, **kwargs):
|
|
71
|
+
return self._fit(X, y, trig_func='cos', **kwargs)
|
HOBIT/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .HOBIT import *
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: HOBIT
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: an installable package for Hybrid fitting of Sine and Cosine functions
|
|
5
|
+
Author: Jose Arturo Celis Gil
|
|
6
|
+
Author-email: solocelis@gmail.com
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
+
Requires-Dist: numpy (>=1.26.0)
|
|
15
|
+
Requires-Dist: optuna (>=3.0.0)
|
|
16
|
+
Requires-Dist: pandas (>=2.0.0)
|
|
17
|
+
Requires-Dist: scikit-learn (>=1.4.0)
|
|
18
|
+
Project-URL: Homepage, https://github.com/Harmonic-Oscillator-hyBrid-fIT/HOBIT
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<img src="https://github.com/anamabo/HOBIT/blob/master/images/logo.png?raw=true" alt="Sublime's custom image"/>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
# HOBIT: Harmonic Oscillator hyBrid fIT
|
|
26
|
+
## Efficient fit of sine/cosine functions using a hybrid method
|
|
27
|
+
### Read our [blog](https://towardsdatascience.com/fitting-cosine-sine-functions-with-machine-learning-in-python-610605d9b057)
|
|
28
|
+
|
|
29
|
+
HOBIT is a Python library that combines [Optuna](https://optuna.org/)'s TPE algorithm with the flexibility of scikit-learn's `LinearRegression` to efficiently fit functions of the form
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
f(x) = y_0 + y_1 * Sin(omega * x + phi)
|
|
33
|
+
f(x) = y_0 + y_1 * Cos(omega * x + phi)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
commonly used to describe harmonic oscillators.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
pip install HOBIT
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Requirements
|
|
45
|
+
|
|
46
|
+
HOBIT requires Python >= 3.11 and will install the following dependencies:
|
|
47
|
+
|
|
48
|
+
* `pandas >= 2.0.0`
|
|
49
|
+
* `numpy >= 1.26.0`
|
|
50
|
+
* `optuna >= 3.0.0`
|
|
51
|
+
* `scikit-learn >= 1.4.0`
|
|
52
|
+
|
|
53
|
+
## Get started
|
|
54
|
+
|
|
55
|
+
In the `test_scripts/` folder you will find the following examples:
|
|
56
|
+
|
|
57
|
+
1. `scipy_and_gradient_descent.py` — fit of a cosine function using scipy's `curve_fit` and a walkthrough of gradient descent.
|
|
58
|
+
2. `only_optuna.py` — fit of a cosine function using Optuna's TPE sampler directly.
|
|
59
|
+
3. `hybrid_method_cos.py` — fit of a cosine function using HOBIT.
|
|
60
|
+
4. `hybrid_method_sin.py` — fit of a sine function using HOBIT.
|
|
61
|
+
|
|
62
|
+
### Quick example
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
import numpy as np
|
|
66
|
+
from HOBIT import RegressionForTrigonometric
|
|
67
|
+
|
|
68
|
+
x = np.linspace(-5, 5, 100)
|
|
69
|
+
y = 10 + 5 * np.cos(3 * x + 2) + 1.5 * np.random.normal(size=100)
|
|
70
|
+
|
|
71
|
+
model = RegressionForTrigonometric()
|
|
72
|
+
model.fit_cos(x, y, n_trials=500)
|
|
73
|
+
|
|
74
|
+
print(model.best_parameters)
|
|
75
|
+
# {'omega': ..., 'phi': ..., 'intercept': ..., 'amplitude': ...}
|
|
76
|
+
|
|
77
|
+
y_pred = model.predict(x)
|
|
78
|
+
```
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
HOBIT/HOBIT.py,sha256=x4n-2eT4qVev1U7zKEgyNI6olzt101NUFmwS2rybYnc,2793
|
|
2
|
+
HOBIT/__init__.py,sha256=jXrtlbeEg0FfjKGzZeoP1hjs_IqkkuRSq0fJju10Oys,21
|
|
3
|
+
hobit-1.0.0.dist-info/METADATA,sha256=LCJVhUK-3V7zdeQA-VA9fcXDr51wgvusu-evbg4EaTQ,2505
|
|
4
|
+
hobit-1.0.0.dist-info/WHEEL,sha256=EGEvSphFYqXKs23-kQBeyNoJP1nrT8ZJKQoi5p5DYL8,88
|
|
5
|
+
hobit-1.0.0.dist-info/RECORD,,
|