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

Feature/concurrent regression #531

Merged
merged 40 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
d2d2837
weighted inner product integrate
rafa9811 Dec 27, 2022
69277ef
weighted_inner_product_integrate test
rafa9811 Dec 28, 2022
b1dc2dd
some checks in math.py
rafa9811 Dec 30, 2022
f102163
Merge branch 'develop' into feature/concurrentRegression
rafa9811 Dec 30, 2022
94c334b
Merge branch 'develop' into feature/concurrentRegression
rafa9811 Jan 1, 2023
cfc3b09
first approach to concurrent regression
rafa9811 Jan 1, 2023
b27f107
weighted_inner_product_integrate with scalar weights
rafa9811 Jan 2, 2023
26691b3
transpose of multivariate covariates
rafa9811 Jan 29, 2023
522d659
Merge branch 'develop' into feature/concurrentRegression
rafa9811 Jan 29, 2023
9409830
moved weighted inner product to regression file. Refactoring.
rafa9811 Jan 30, 2023
0ed8c80
convert from constant coefs
rafa9811 Jan 31, 2023
4d46345
deleted false check
rafa9811 Mar 1, 2023
9cfd103
Merge branch 'develop' into feature/concurrentRegression
rafa9811 Mar 1, 2023
c9ff81a
Merge branch 'develop' into feature/concurrentRegression
rafa9811 Mar 24, 2023
ada5e40
deleted test: weighted inner product is now in lregression file. NDar…
rafa9811 Mar 28, 2023
32db8bd
Merge branch 'develop' into feature/concurrentRegression
rafa9811 Mar 28, 2023
371f056
updated tests
rafa9811 Mar 28, 2023
14be648
Merge branch 'develop' into feature/concurrentRegression
rafa9811 Mar 29, 2023
0ea1664
fix tests and small refactoring
rafa9811 Mar 30, 2023
a20ec8f
Merge branch 'develop' into feature/concurrentRegression
rafa9811 Mar 30, 2023
15ea681
test: multivariate and concurrent
rafa9811 Mar 30, 2023
aa630d5
updated doc
rafa9811 Mar 30, 2023
7d03538
weather example. Small fix in doc.
rafa9811 Mar 31, 2023
bdc69cb
Predict implementation with basis change. Updated tests.
rafa9811 Apr 15, 2023
100b7f4
Merge branch 'develop' into feature/concurrentRegression
rafa9811 Apr 15, 2023
c6bdf28
small fix in prediction function
rafa9811 Apr 15, 2023
4e6bed9
style fixes
rafa9811 Apr 15, 2023
925b602
no change of basis if it's the same. Fix intercept and example.
rafa9811 Apr 15, 2023
d418787
Merge branch 'develop' into feature/concurrentRegression
rafa9811 May 2, 2023
0d0fc19
Merge branch 'develop' into feature/concurrentRegression
vnmabus Jun 13, 2023
69aed6a
small fixes: example, types
rafa9811 Jun 14, 2023
679875d
Merge branch 'feature/concurrentRegression' of https://github.com/GAA…
rafa9811 Jun 14, 2023
ed03263
fix predict
rafa9811 Jun 21, 2023
09db85e
Merge branch 'develop' into feature/concurrentRegression
vnmabus Oct 20, 2023
f897a2b
Fix standalone tests.
vnmabus Oct 20, 2023
dc51e44
Fix doctest.
vnmabus Oct 20, 2023
596a5fc
Modify example.
vnmabus Oct 20, 2023
b9fd149
Fix comment in example.
vnmabus Oct 20, 2023
a946d95
Use function_to_fdatabasis from utils.
vnmabus Oct 23, 2023
a020784
Some fixes.
vnmabus Oct 23, 2023
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
89 changes: 89 additions & 0 deletions examples/plot_functional_regression.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
Functional Linear Regression with multivariate covariates.
==========================================================

This example explores the use of the linear regression with
multivariate (scalar) covariates and functional response.

"""

# Author: Rafael Hidalgo Alejo
# License: MIT

import numpy as np
import pandas as pd
from sklearn.preprocessing import OneHotEncoder

import skfda
from skfda.ml.regression import LinearRegression
from skfda.representation.basis import FDataBasis, FourierBasis

# %%
# In this example, we will demonstrate the use of the Linear Regression with
# functional response and multivariate covariates using the
# :func:`weather <skfda.datasets.fetch_weather>` dataset.
# It is possible to divide the weather stations into four groups:
# Atlantic, Pacific, Continental and Artic.
# There are a total of 35 stations in this dataset.

X_weather, y_weather = skfda.datasets.fetch_weather(
return_X_y=True, as_frame=True,
)
fd = X_weather.iloc[:, 0].values

# %%
# The main goal is knowing about the effect of stations' geographic location
# on the shape of the temperature curves.
# So we will have a model with a functional response, the temperature curve,
# and five covariates. The first one is the intercept (all entries equal to 1)
# and it shows the contribution of the Canadian mean temperature. The remaining
# covariates use one-hot encoding, with 1 if that weather station is in the
# corresponding climate zone and 0 otherwise.

# We first create the one-hot encoding of the climates.

enc = OneHotEncoder(handle_unknown='ignore')
enc.fit([['Atlantic'], ['Continental'], ['Pacific']])
X = np.array(y_weather).reshape(-1, 1)
X = enc.transform(X).toarray()

# %%
# Then, we construct a dataframe with each covariate in a different column and
# the temperature curves (responses).

X_df = pd.DataFrame(X)

y_basis = FourierBasis(n_basis=65)
y_fd = fd.coordinates[0].to_basis(y_basis)

# %%
# An intercept term is incorporated.
# All functional coefficients will have the same basis as the response.

funct_reg = LinearRegression(fit_intercept=True)
funct_reg.fit(X_df, y_fd)

# %%
# The regression coefficients are shown below. The first one is the intercept
# coefficient, corresponding to Canadian mean temperature.

funct_reg.intercept_.plot()
funct_reg.coef_[0].plot()
funct_reg.coef_[1].plot()
funct_reg.coef_[2].plot()

# %%
# Finally, it is shown a panel with the prediction for all climate zones.

predictions = []

predictions.append(funct_reg.predict([[0, 1, 0, 0]])[0])
predictions.append(funct_reg.predict([[0, 0, 1, 0]])[0])
predictions.append(funct_reg.predict([[0, 0, 0, 1]])[0])

predictions_conc = FDataBasis.concatenate(*predictions)

predictions_conc.argument_names = ('day',)
predictions_conc.coordinate_names = ('temperature (ºC)',)

predictions_conc.plot()
21 changes: 18 additions & 3 deletions skfda/misc/_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import numpy as np
import scipy.integrate

from .._utils import nquad_vec
from .._utils import _same_domain, nquad_vec
from ..representation import FData, FDataBasis, FDataGrid
from ..representation.basis import Basis
from ..typing._base import DomainRange
Expand Down Expand Up @@ -243,6 +243,7 @@
Args:
arg1: First sample.
arg2: Second sample.
kwargs: Additional parameters for the function.

Returns:
Vector with the inner products of each pair of samples.
Expand Down Expand Up @@ -388,10 +389,17 @@
arg2: Union[FDataBasis, Basis],
*,
_matrix: bool = False,
_domain_range: Optional[DomainRange] = None,
inner_product_matrix: Optional[NDArrayFloat] = None,
force_numerical: bool = False,
) -> NDArrayFloat:

if not _same_domain(arg1, arg2):
raise ValueError("Both Objects should have the same domain_range")

Check warning on line 398 in skfda/misc/_math.py

View check run for this annotation

Codecov / codecov/patch

skfda/misc/_math.py#L398

Added line #L398 was not covered by tests

if _domain_range and not np.array_equal(arg1.domain_range, _domain_range):
raise ValueError("_domain_range should be the same as arg objects")

Check warning on line 401 in skfda/misc/_math.py

View check run for this annotation

Codecov / codecov/patch

skfda/misc/_math.py#L401

Added line #L401 was not covered by tests

if isinstance(arg1, Basis):
arg1 = arg1.to_basis()

Expand Down Expand Up @@ -479,8 +487,15 @@
def integrand(*args: NDArrayFloat) -> NDArrayFloat: # noqa: WPS430
f_args = np.asarray(args)

f1 = arg1(f_args)[:, 0, :]
f2 = arg2(f_args)[:, 0, :]
try:
f1 = arg1(f_args)[:, 0, :]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are you attempting here?

except Exception:
f1 = arg1(f_args)

Check warning on line 493 in skfda/misc/_math.py

View check run for this annotation

Codecov / codecov/patch

skfda/misc/_math.py#L492-L493

Added lines #L492 - L493 were not covered by tests

try:
f2 = arg2(f_args)[:, 0, :]
except Exception:
f2 = arg2(f_args)

Check warning on line 498 in skfda/misc/_math.py

View check run for this annotation

Codecov / codecov/patch

skfda/misc/_math.py#L497-L498

Added lines #L497 - L498 were not covered by tests

if _matrix:
ret = np.einsum('n...,m...->nm...', f1, f2)
Expand Down
4 changes: 4 additions & 0 deletions skfda/ml/regression/_coefficients.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,12 @@ def coefficient_info_from_covariate(
def _coefficient_info_from_covariate_ndarray( # type: ignore[misc]
X: NDArrayFloat,
y: NDArrayFloat,
basis: Basis = None,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [mypy] reported by reviewdog 🐶
Incompatible default for argument "basis" (default has type "None", argument has type "Basis") [assignment]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [mypy] reported by reviewdog 🐶
PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 [mypy] reported by reviewdog 🐶
Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase

**_: Any,
) -> CoefficientInfo[NDArrayFloat]:
if basis:
return CoefficientInfoNdarray(basis=basis)

return CoefficientInfoNdarray(basis=np.identity(X.shape[1], dtype=X.dtype))


Expand Down
Loading
Loading