def _set_knots_scale_matrix()

in orbit/template/ktr.py [0:0]


    def _set_knots_scale_matrix(self, df, training_meta):
        num_of_observations = training_meta[TrainingMetaKeys.NUM_OF_OBS.value]
        if self._num_of_positive_regressors > 0:
            # calculate average local absolute volume for each segment
            local_val = np.ones(
                (self._num_of_positive_regressors, self._num_knots_coefficients)
            )
            if self.flat_multiplier:
                multiplier = np.ones(local_val.shape)
            else:
                multiplier = np.ones(local_val.shape)
                # store local value for the range on the left side since last knot
                for idx in range(len(self._regression_knots_idx)):
                    if idx < len(self._regression_knots_idx) - 1:
                        str_idx = self._regression_knots_idx[idx]
                        end_idx = self._regression_knots_idx[idx + 1]
                    else:
                        str_idx = self._regression_knots_idx[idx]
                        end_idx = num_of_observations

                    local_val[:, idx] = np.mean(
                        np.fabs(self._positive_regressor_matrix[str_idx:end_idx]),
                        axis=0,
                    )

                global_mean = np.expand_dims(
                    np.mean(np.fabs(self._positive_regressor_matrix), axis=0), -1
                )
                test_flag = local_val < 0.01 * global_mean

                # adjust knot scale with the multiplier derive by the average value and shift by 0.001 to avoid zeros in
                # scale parameters
                multiplier[test_flag] = DEFAULT_LOWER_BOUND_SCALE_MULTIPLIER
                # replace entire row of nan (when 0.1 * global_mean is equal to global_min) with upper bound
                multiplier[np.isnan(multiplier).all(axis=-1)] = 1.0

            # geometric drift i.e. 0.1 = 10% up-down in 1 s.d. prob.
            # self._positive_regressor_knot_scale has shape num_of_pr x num_of_knot
            self._positive_regressor_knot_scale = multiplier * np.expand_dims(
                self._positive_regressor_knot_scale_1d, -1
            )
            # keep a lower bound of scale parameters
            self._positive_regressor_knot_scale[
                self._positive_regressor_knot_scale < 1e-4
            ] = 1e-4
            # TODO: we change the type here, maybe we should change it earlier?
            self._positive_regressor_init_knot_scale = np.array(
                self._positive_regressor_init_knot_scale
            )
            self._positive_regressor_init_knot_scale[
                self._positive_regressor_init_knot_scale < 1e-4
            ] = 1e-4

        if self._num_of_negative_regressors > 0:
            # calculate average local absolute volume for each segment
            local_val = np.ones(
                (self._num_of_negative_regressors, self._num_knots_coefficients)
            )
            if self.flat_multiplier:
                multiplier = np.ones(local_val.shape)
            else:
                multiplier = np.ones(local_val.shape)
                # store local value for the range on the left side since last knot
                for idx in range(len(self._regression_knots_idx)):
                    if idx < len(self._regression_knots_idx) - 1:
                        str_idx = self._regression_knots_idx[idx]
                        end_idx = self._regression_knots_idx[idx + 1]
                    else:
                        str_idx = self._regression_knots_idx[idx]
                        end_idx = num_of_observations

                    local_val[:, idx] = np.mean(
                        np.fabs(self._negative_regressor_matrix[str_idx:end_idx]),
                        axis=0,
                    )

                global_mean = np.expand_dims(
                    np.mean(np.fabs(self._negative_regressor_matrix), axis=0), -1
                )
                test_flag = local_val < 0.01 * global_mean

                # adjust knot scale with the multiplier derive by the average value and shift by 0.001 to avoid zeros in
                # scale parameters
                multiplier[test_flag] = DEFAULT_LOWER_BOUND_SCALE_MULTIPLIER
                # replace entire row of nan (when 0.1 * global_mean is equal to global_min) with upper bound
                multiplier[np.isnan(multiplier).all(axis=-1)] = 1.0

            # geometric drift i.e. 0.1 = 10% up-down in 1 s.d. prob.
            self._negative_regressor_knot_scale = multiplier * np.expand_dims(
                self._negative_regressor_knot_scale_1d, -1
            )
            # keep a lower bound of scale parameters
            self._negative_regressor_knot_scale[
                self._negative_regressor_knot_scale < 1e-4
            ] = 1e-4
            # TODO: we change the type here, maybe we should change it earlier?
            self._negative_regressor_init_knot_scale = np.array(
                self._negative_regressor_init_knot_scale
            )
            self._negative_regressor_init_knot_scale[
                self._negative_regressor_init_knot_scale < 1e-4
            ] = 1e-4

        if self._num_of_regular_regressors > 0:
            # do the same for regular regressor
            # calculate average local absolute volume for each segment
            local_val = np.ones(
                (self._num_of_regular_regressors, self._num_knots_coefficients)
            )
            if self.flat_multiplier:
                multiplier = np.ones(local_val.shape)
            else:
                multiplier = np.ones(local_val.shape)
                # store local value for the range on the left side since last knot
                for idx in range(len(self._regression_knots_idx)):
                    if idx < len(self._regression_knots_idx) - 1:
                        str_idx = self._regression_knots_idx[idx]
                        end_idx = self._regression_knots_idx[idx + 1]
                    else:
                        str_idx = self._regression_knots_idx[idx]
                        end_idx = num_of_observations

                    local_val[:, idx] = np.mean(
                        np.fabs(self._regular_regressor_matrix[str_idx:end_idx]), axis=0
                    )

            # adjust knot scale with the multiplier derive by the average value and shift by 0.001 to avoid zeros in
            # scale parameters
            global_mean = np.expand_dims(
                np.mean(np.fabs(self._regular_regressor_matrix), axis=0), -1
            )
            test_flag = local_val < 0.01 * global_mean
            multiplier[test_flag] = DEFAULT_LOWER_BOUND_SCALE_MULTIPLIER
            # replace entire row of nan (when 0.1 * global_mean is equal to global_min) with upper bound
            multiplier[np.isnan(multiplier).all(axis=-1)] = 1.0

            # geometric drift i.e. 0.1 = 10% up-down in 1 s.d. prob.
            # self._regular_regressor_knot_scale has shape num_of_pr x num_of_knot
            self._regular_regressor_knot_scale = multiplier * np.expand_dims(
                self._regular_regressor_knot_scale_1d, -1
            )
            # keep a lower bound of scale parameters
            self._regular_regressor_knot_scale[
                self._regular_regressor_knot_scale < 1e-4
            ] = 1e-4
            # TODO: we change the type here, maybe we should change it earlier?
            self._regular_regressor_init_knot_scale = np.array(
                self._regular_regressor_init_knot_scale
            )
            self._regular_regressor_init_knot_scale[
                self._regular_regressor_init_knot_scale < 1e-4
            ] = 1e-4