Skip to content

multilinear

Multilinear

Bases: NToOneTransformer

N-to-1 transformation allowing to get 1 variable by applying a linear combination of N other variables.

Parameters:

Name Type Description Default
coefs List[float]

Coefficients of the multilinear function.

required
ignore_input_indexes Optional[List[int]]

Indexes of the data in series to ignore when computing the repartition.

None
Source code in eki_mmo_equations/n_to_one_transformations/multilinear.py
class Multilinear(NToOneTransformer):
    """N-to-1 transformation allowing to get 1 variable by applying a linear combination of N other variables.

    ```math
        \\alpha_1 \\times serie_1 + \\alpha_2 \\times serie_2 + ... + \\alpha_N \\times serie_N
    ```

    Args:
        coefs (List[float]): Coefficients of the multilinear function.
        ignore_input_indexes (Optional[List[int]], optional): Indexes of the data in series to ignore when
            computing the repartition.
    """

    def __init__(self, coefs: List[float], ignore_input_indexes: Optional[List[int]] = None):
        self.coefs: List[float] = coefs
        self.ignore_input_indexes: List[int] = ignore_input_indexes if ignore_input_indexes else []

    @property
    def parameters(self) -> Dict[str, float]:
        return self.__dict__

    @property
    def is_linear(self) -> bool:
        return True

    # ------- METHODS -------

    def transform(self, series: List[np.ndarray], copy=False) -> np.ndarray:
        series = super().transform(series, copy)

        return self._transformer(series, self.coefs)

    def repartition(self, series: List[np.ndarray]) -> List[np.ndarray]:
        "Returns the repartition of the output series from the initial input series."
        repartition_series = [serie for i, serie in enumerate(series) if i not in self.ignore_input_indexes]
        repartition_coefs = [coef for i, coef in enumerate(self.coefs) if i not in self.ignore_input_indexes]

        weighted_series = [serie * coef for serie, coef in zip(repartition_series, repartition_coefs)]
        proportionned_weighted_series = [
            np.nan_to_num(weighted_serie / np.sum(weighted_series, axis=0)) for weighted_serie in weighted_series
        ]
        for index in self.ignore_input_indexes:
            proportionned_weighted_series.insert(index, np.zeros(len(series[index])))

        return proportionned_weighted_series

    # ------- TRANSFORMERS -------

    @staticmethod
    def _transformer(series: List[np.ndarray], coefs: List[float]) -> np.ndarray:
        "Returns the linear combination of the different input variables."
        return np.sum([serie * coef for serie, coef in zip(series, coefs)], axis=0)

    # ------- CHECKERS -------

    def check_params(self, series: List[np.ndarray]):
        """Check if parameters respect their application scope."""
        if not len(self.coefs) == len(series):
            raise ParameterScopeException(
                "Number of series don't match number of coefs. "
                + f"Number of coefs:{len(self.coefs)} . Number of series:{len(series)}"
            )
        if len(self.ignore_input_indexes) != len(set(self.ignore_input_indexes)):
            raise ParameterScopeException(
                f"Incorrect {self.__class__.__name__} parameters. Values ignore_input_indexes"
                f" should be unique. Current values:{self.ignore_input_indexes}"
            )
        if not all(index < len(series) for index in self.ignore_input_indexes):
            raise ParameterScopeException(
                f"Incorrect {self.__class__.__name__} parameters. Each value of ignore_input_indexes"
                f" should be lower than the number of series as input - lower than {len(series)}."
            )
        if len(self.ignore_input_indexes) >= len(series):
            raise ParameterScopeException(
                f"Incorrect {self.__class__.__name__}. Length of ignore_input_indexes"
                f" should be inferior to length of input series - lower than {len(series)}."
            )

check_params(series)

Check if parameters respect their application scope.

Source code in eki_mmo_equations/n_to_one_transformations/multilinear.py
def check_params(self, series: List[np.ndarray]):
    """Check if parameters respect their application scope."""
    if not len(self.coefs) == len(series):
        raise ParameterScopeException(
            "Number of series don't match number of coefs. "
            + f"Number of coefs:{len(self.coefs)} . Number of series:{len(series)}"
        )
    if len(self.ignore_input_indexes) != len(set(self.ignore_input_indexes)):
        raise ParameterScopeException(
            f"Incorrect {self.__class__.__name__} parameters. Values ignore_input_indexes"
            f" should be unique. Current values:{self.ignore_input_indexes}"
        )
    if not all(index < len(series) for index in self.ignore_input_indexes):
        raise ParameterScopeException(
            f"Incorrect {self.__class__.__name__} parameters. Each value of ignore_input_indexes"
            f" should be lower than the number of series as input - lower than {len(series)}."
        )
    if len(self.ignore_input_indexes) >= len(series):
        raise ParameterScopeException(
            f"Incorrect {self.__class__.__name__}. Length of ignore_input_indexes"
            f" should be inferior to length of input series - lower than {len(series)}."
        )

repartition(series)

Returns the repartition of the output series from the initial input series.

Source code in eki_mmo_equations/n_to_one_transformations/multilinear.py
def repartition(self, series: List[np.ndarray]) -> List[np.ndarray]:
    "Returns the repartition of the output series from the initial input series."
    repartition_series = [serie for i, serie in enumerate(series) if i not in self.ignore_input_indexes]
    repartition_coefs = [coef for i, coef in enumerate(self.coefs) if i not in self.ignore_input_indexes]

    weighted_series = [serie * coef for serie, coef in zip(repartition_series, repartition_coefs)]
    proportionned_weighted_series = [
        np.nan_to_num(weighted_serie / np.sum(weighted_series, axis=0)) for weighted_serie in weighted_series
    ]
    for index in self.ignore_input_indexes:
        proportionned_weighted_series.insert(index, np.zeros(len(series[index])))

    return proportionned_weighted_series