Partial Functional Linear Model#
PartialFunctionalLinearModel combines scalar predictors with one or more functional predictors (via FPCA) and fits
an ElasticNet on the concatenated design matrix [scalar_features | FPCA_scores].
Single functional feature#
import numpy as np
from pflm.fpca import FunctionalDataGenerator, FunctionalPCA
from pflm.pflm.partial_flm import PartialFunctionalLinearModel, FPCAConfig
# --- Synthetic functional data ---
t = np.linspace(0.0, 10.0, 51)
gen = FunctionalDataGenerator(
t,
lambda x: np.sin(x) * 0.5,
lambda x: 1.0 + 0.2 * np.cos(x),
)
n = 100
y_list, t_list = gen.generate(n=n, seed=42)
# --- Scalar features and response ---
rng = np.random.default_rng(0)
scalar = rng.standard_normal((n, 3))
response = scalar @ np.array([1.0, -0.5, 0.3]) + rng.normal(0, 0.2, n)
# --- Fit ---
model = PartialFunctionalLinearModel()
model.fit([t_list], [y_list], scalar, response)
print("Scalar features:", model.n_scalar_features_in_)
print("Functional features:", model.n_functional_features_in_)
print("Selected #PCs:", model.fpca_models_[0].num_pcs_)
print("Total coefficients:", model.linear_model_.coef_.shape)
Customise ElasticNet and FPCA#
Use linear_opts to control the ElasticNet regularisation and fpca_configs to tune the FPCA pipeline.
from pflm.fpca import FunctionalPCAMuCovParams
model = PartialFunctionalLinearModel(
linear_opts=dict(alpha=0.1, l1_ratio=0.8, max_iter=2000),
fpca_configs=FPCAConfig(
num_points_reg_grid=101,
mu_cov_params=FunctionalPCAMuCovParams(
method_select_mu_bw="gcv",
method_select_cov_bw="gcv",
),
fit_params=dict(
fve_threshold=0.95,
method_pcs="CE",
),
),
)
model.fit([t_list], [y_list], scalar, response)
print("Coefficients:", model.linear_model_.coef_)
Multiple functional features#
When more than one functional predictor is available, pass each as a separate element in the lists and optionally provide per-feature FPCA configs.
# Generate a second functional feature
gen2 = FunctionalDataGenerator(
t,
lambda x: np.cos(x) * 0.3,
lambda x: 0.5 + 0.1 * np.sin(x),
)
y_list2, t_list2 = gen2.generate(n=n, seed=7)
model = PartialFunctionalLinearModel(
fpca_configs=[
FPCAConfig(fit_params=dict(method_pcs="IN")),
FPCAConfig(fit_params=dict(method_pcs="CE", fve_threshold=0.99)),
],
)
model.fit(
[t_list, t_list2],
[y_list, y_list2],
scalar,
response,
)
print("PCs feature 0:", model.fpca_models_[0].num_pcs_)
print("PCs feature 1:", model.fpca_models_[1].num_pcs_)
Prediction#
y_pred = model.predict(
[t_list[:10], t_list2[:10]],
[y_list[:10], y_list2[:10]],
scalar[:10],
)
print("Predicted (first 5):", y_pred[:5])