def fit(self, X, y=None, sample_weight=None):
        """Fit the model with X.

        Parameters
        ----------
        X : Triangle
            Set of LDFs to which the munich adjustment will be applied.
        y : Ignored
        sample_weight : Ignored

        Returns
        -------
        self : object
            Returns the instance itself.
        """
        backend = "cupy" if X.array_backend == "cupy" else "numpy"
        self.X_ = X.copy()
        paid_tri = self.X_[self.paid_to_incurred[0]]
        incurred_tri = self.X_[self.paid_to_incurred[1]]
        self.paid_w_ = Development(n_periods=self.paid_n_periods).fit(self.X_.iloc[0,0]).w_
        self.case_w_ = Development(n_periods=self.case_n_periods).fit(self.X_.iloc[0,0]).w_
        self.case_ldf_ = self.case_to_prior_case_.mean(2)
        self.paid_ldf_ = self.paid_to_prior_case_.mean(2)

        case = incurred_tri-paid_tri
        patterns = ((1 - np.nan_to_num(case.nan_triangle[..., 1:])) *
                    self.case_ldf_.values)
        for i in range(np.isnan(case.nan_triangle[-1]).sum()):
            increment = (
                (case - case[case.valuation < case.valuation_date]).iloc[..., :-1] *
                patterns)
            increment.ddims = case.ddims[1:]
            increment.valuation_date = case.valuation[case.valuation>=case.valuation_date].drop_duplicates()[1]
            case = case + increment
예제 #2
0
 def fit(self, X, y=None, sample_weight=None):
     if (type(X.ddims) != np.ndarray):
         raise ValueError(
             'Triangle must be expressed with development lags')
     obj = copy.copy(X)
     self.w_ = X.nan_triangle() if not self.drop else self._drop(X)
     lag = {'M': 1, 'Q': 3, 'Y': 12}[X.development_grain]
     if type(self.drop) is not list and self.drop is not None:
         self.drop = [self.drop]
         drop = [(item[0], item[1] - lag) for item in self.drop]
     else:
         drop = self.drop
     obj = Development(n_periods=self.n_periods,
                       drop=drop).fit_transform(obj)
     obj = Chainladder().fit(obj)
     # Works for only a single triangle - can we generalize this
     exp_incr_triangle = obj.full_expectation_.cum_to_incr() \
                            .values[0, 0, :, :X.shape[-1]]
     exp_incr_triangle = np.nan_to_num(exp_incr_triangle) * \
         obj.X_.nan_triangle()
     self.design_matrix_ = self._get_design_matrix(X)
     self.hat_ = self._get_hat(X, exp_incr_triangle)
     self.resampled_triangles_, self.scale_ = \
         self._get_simulation(X, exp_incr_triangle)
     n_obs = np.nansum(self.w_)
     n_origin_params = X.shape[2]
     n_dev_params = X.shape[3] - 1
     deg_free = n_obs - n_origin_params - n_dev_params
     deg_free_adj_fctr = np.sqrt(n_obs / deg_free)
     return self
    def fit(self, X, y=None, sample_weight=None):
        """Fit the model with X.

        Parameters
        ----------
        X : Triangle-like
            Triangle to which the incremental method is applied.  Triangle must
            be cumulative.
        y : Ignored
        sample_weight : Exposure used in the method.

        Returns
        -------
        self : object
            Returns the instance itself.
        """
        from chainladder import ULT_VAL
        from chainladder.utils.utility_functions import num_to_nan
        if (type(X.ddims) != np.ndarray):
            raise ValueError('Triangle must be expressed with development lags')
        if X.array_backend == 'sparse':
            X = X.set_backend('numpy')
        else:
            X = copy.deepcopy(X)
        if sample_weight.array_backend == 'sparse':
            sample_weight = sample_weight.set_backend('numpy')
        else:
            sample_weight = copy.deepcopy(sample_weight)
        xp = X.get_array_module()
        sample_weight.is_cumulative = False
        obj = X.cum_to_incr()/sample_weight
        x = obj.trend(self.trend)
        w_ = Development(n_periods=self.n_periods-1).fit(x).w_
        w_ = num_to_nan(w_)
        w_ = xp.concatenate((w_, (w_[..., -1:]*x.nan_triangle)[..., -1:]),
                            axis=-1)
        if self.average == 'simple':
            y_ = xp.nanmean(w_*x.values, axis=-2)
        if self.average == 'volume':
            y_ = xp.nansum(w_*x.values*sample_weight.values, axis=-2)
            y_ = y_ / xp.nansum(w_*sample_weight.values, axis=-2)
        y_ = xp.repeat(y_[..., None, :], len(x.odims), -2)
        obj = copy.copy(x)
        keeps = 1-xp.nan_to_num(x.nan_triangle) + \
            xp.nan_to_num(
                x[x.valuation==x.valuation_date].values[0, 0, ...]*0+1)
        obj.values = (1+self.trend) ** \
            xp.flip((xp.abs(xp.arange(obj.shape[-2])[None].T -
                     xp.arange(obj.shape[-2])[None])), 0)*y_*keeps
        obj.values = obj.values*(1-xp.nan_to_num(x.nan_triangle)) + \
            xp.nan_to_num((X.cum_to_incr()/sample_weight).values)

        obj.values[obj.values == 0] = xp.nan
        obj._set_slicers()
        obj.valuation_date = pd.to_datetime(ULT_VAL)
        self.ldf_ = obj.incr_to_cum().link_ratio
        self.incremental_ = obj*sample_weight
        self.sigma_ = self.std_err_ = 0*self.ldf_
        return self
 def fit(self, X, y=None, sample_weight=None):
     obj = copy.deepcopy(X)
     obj = Development(n_periods=self.n_periods).fit_transform(obj)
     obj = Chainladder().fit(obj)
     # Works for only a single triangle - can we generalize this
     exp_incr_triangle = obj.full_expectation_ \
                            .cum_to_incr().triangle[0, 0, :, :X.shape[-1]]
     exp_incr_triangle = np.nan_to_num(exp_incr_triangle) * \
         obj.X_.nan_triangle()
     self.design_matrix_ = self._get_design_matrix(X)
     self.hat_ = self._get_hat(X, exp_incr_triangle)
     self.resampled_triangles_, self.scale_ = \
         self._get_simulation(X, exp_incr_triangle)
     return self
예제 #5
0
    def fit(self, X, y=None, sample_weight=None):
        """Fit the model with X.

        Parameters
        ----------
        X : Triangle-like
            Triangle to which the incremental method is applied.  Triangle must
            be cumulative.
        y : Ignored
        sample_weight : Exposure used in the method.

        Returns
        -------
        self : object
            Returns the instance itself.
        """
        if (type(X.ddims) != np.ndarray):
            raise ValueError(
                'Triangle must be expressed with development lags')
        obj = X.cum_to_incr() / sample_weight
        xp = cp.get_array_module(obj.values)
        x = obj.trend(self.trend)
        w_ = Development(n_periods=self.n_periods - 1).fit(x).w_
        w_[w_ == 0] = xp.nan
        w_ = xp.concatenate((w_, (w_[..., -1:] * x._nan_triangle())[..., -1:]),
                            axis=-1)
        if self.average == 'simple':
            y_ = xp.nanmean(w_ * x.values, axis=-2)
        if self.average == 'volume':
            y_ = xp.nansum(w_ * x.values * sample_weight.values, axis=-2)
            y_ = y_ / xp.nansum(w_ * sample_weight.values, axis=-2)
        y_ = xp.repeat(xp.expand_dims(y_, -2), len(x.odims), -2)
        obj = copy.copy(x)
        keeps = 1-xp.nan_to_num(x._nan_triangle()) + \
            xp.nan_to_num(
                x._get_latest_diagonal(compress=False).values[0, 0, ...]*0+1)
        obj.values = (1+self.trend) ** \
            xp.flip((xp.abs(xp.arange(obj.shape[-2])[xp.newaxis].T -
                     xp.arange(obj.shape[-2])[xp.newaxis])), 0)*y_*keeps
        obj.values = obj.values*(X._expand_dims(1-xp.nan_to_num(x._nan_triangle()))) + \
            xp.nan_to_num((X.cum_to_incr()/sample_weight).values)
        obj.values[obj.values == 0] = xp.nan
        obj.nan_override = True
        obj._set_slicers()
        self.incremental_ = obj * sample_weight
        self.ldf_ = obj.incr_to_cum().link_ratio
        self.cdf_ = DevelopmentBase._get_cdf(self.ldf_)
        self.sigma_ = self.std_err_ = 0 * self.ldf_
        return self
예제 #6
0
 def fit(self, X, y=None, sample_weight=None):
     backend = X.array_backend
     if backend == "sparse":
         X = X.set_backend("numpy")
     else:
         X = X.copy()
     xp = X.get_array_module()
     if X.shape[:2] != (1, 1):
         raise ValueError(
             "Only single index/column triangles are supported")
     if type(X.ddims) != np.ndarray:
         raise ValueError(
             "Triangle must be expressed with development lags")
     lag = {"M": 1, "Q": 3, "Y": 12}[X.development_grain]
     obj = Development(
         n_periods=self.n_periods,
         drop=self.drop,
         drop_high=self.drop_high,
         drop_low=self.drop_low,
         drop_valuation=self.drop_valuation,
     ).fit_transform(X)
     self.w_ = obj.w_
     obj = Chainladder().fit(obj)
     # Works for only a single triangle - can we generalize this
     exp_incr_triangle = obj.full_expectation_.cum_to_incr().values[
         0, 0, :, :X.shape[-1]]
     exp_incr_triangle = xp.nan_to_num(
         exp_incr_triangle) * obj.X_.nan_triangle
     self.design_matrix_ = self._get_design_matrix(X)
     if self.hat_adj:
         try:
             self.hat_ = self._get_hat(X, exp_incr_triangle)
         except:
             warn("Could not compute hat matrix.  Setting hat_adj to False")
             self.had_adj = False
             self.hat_ = None
     else:
         self.hat_ = None
     self.resampled_triangles_, self.scale_ = self._get_simulation(
         X, exp_incr_triangle)
     n_obs = xp.nansum(self.w_)
     n_origin_params = X.shape[2]
     n_dev_params = X.shape[3] - 1
     deg_free = n_obs - n_origin_params - n_dev_params
     deg_free_adj_fctr = xp.sqrt(n_obs / deg_free)
     return self
예제 #7
0
    def fit(self, X, y=None, sample_weight=None):
        """Fit the model with X.

        Parameters
        ----------
        X : Triangle-like
            Triangle to which the incremental method is applied.  Triangle must
            be cumulative.
        y : Ignored
        sample_weight : Exposure used in the method.

        Returns
        -------
        self : object
            Returns the instance itself.
        """
        obj = X.cum_to_incr() / sample_weight
        x = obj.trend(self.trend)
        w_ = Development(n_periods=self.n_periods - 1).fit(x).w_
        w_[w_ == 0] = np.nan
        w_ = np.concatenate((w_, (w_[..., -1:] * x.nan_triangle())[..., -1:]),
                            axis=-1)
        if self.average == 'simple':
            y_ = np.nanmean(w_ * x.values, axis=-2)
        if self.average == 'volume':
            y_ = np.nansum(w_ * x.values * sample_weight.values, axis=-2)
            y_ = y_ / np.nansum(w_ * sample_weight.values, axis=-2)
        y_ = np.repeat(np.expand_dims(y_, -2), len(x.odims), -2)
        obj = copy.deepcopy(x)
        keeps = 1-np.nan_to_num(x.nan_triangle()) + \
            np.nan_to_num(
                x.get_latest_diagonal(compress=False).values[0, 0, ...]*0+1)
        obj.values = (1+self.trend) ** \
            np.flip((np.abs(np.expand_dims(np.arange(obj.shape[-2]), 0).T -
                     np.expand_dims(np.arange(obj.shape[-2]), 0))), 0)*y_*keeps
        obj.values = obj.values*(x.expand_dims(1-np.nan_to_num(x.nan_triangle()))) + \
            np.nan_to_num((X.cum_to_incr()/sample_weight).values)
        obj.values[obj.values == 0] = np.nan
        obj.nan_override = True
        self.incremental_ = obj * sample_weight
        self.ldf_ = obj.incr_to_cum().link_ratio
        self.cdf_ = DevelopmentBase._get_cdf(self.ldf_)
        return self
예제 #8
0
 def fit(self, X, y=None, sample_weight=None):
     xp = cp.get_array_module(X.values)
     if X.shape[:2] != (1, 1):
         raise ValueError(
             'Only single index/column triangles are supported')
     if (type(X.ddims) != np.ndarray):
         raise ValueError(
             'Triangle must be expressed with development lags')
     obj = copy.copy(X)
     lag = {'M': 1, 'Q': 3, 'Y': 12}[X.development_grain]
     obj = Development(
         n_periods=self.n_periods,
         drop=self.drop,
         drop_high=self.drop_high,
         drop_low=self.drop_low,
         drop_valuation=self.drop_valuation).fit_transform(obj)
     self.w_ = obj.w_
     obj = Chainladder().fit(obj)
     # Works for only a single triangle - can we generalize this
     exp_incr_triangle = obj.full_expectation_.cum_to_incr() \
                            .values[0, 0, :, :X.shape[-1]]
     exp_incr_triangle = xp.nan_to_num(exp_incr_triangle) * \
         obj.X_._nan_triangle()
     self.design_matrix_ = self._get_design_matrix(X)
     if self.hat_adj:
         try:
             self.hat_ = self._get_hat(X, exp_incr_triangle)
         except:
             warn('Could not compute hat matrix.  Setting hat_adj to False')
             self.had_adj = False
             self.hat_ = None
     else:
         self.hat_ = None
     self.resampled_triangles_, self.scale_ = \
         self._get_simulation(X, exp_incr_triangle)
     n_obs = xp.nansum(self.w_)
     n_origin_params = X.shape[2]
     n_dev_params = X.shape[3] - 1
     deg_free = n_obs - n_origin_params - n_dev_params
     deg_free_adj_fctr = np.sqrt(n_obs / deg_free)
     return self
예제 #9
0
    def fit(self, X, y=None, sample_weight=None):
        """Fit the model with X.

        Parameters
        ----------
        X : Triangle-like
            Triangle to which the incremental method is applied.  Triangle must
            be cumulative.
        y : None
            Ignored
        sample_weight :
            Exposure used in the method.

        Returns
        -------
        self : object
            Returns the instance itself.
        """
        from chainladder import ULT_VAL
        from chainladder.utils.utility_functions import num_to_nan

        if type(X.ddims) != np.ndarray:
            raise ValueError("Triangle must be expressed with development lags")
        if X.array_backend == "sparse":
            X = X.set_backend("numpy")
        else:
            X = X.copy()
        if sample_weight.array_backend == "sparse":
            sample_weight = sample_weight.set_backend("numpy")
        xp = X.get_array_module()
        sample_weight.is_cumulative = False
        obj = X.cum_to_incr() / sample_weight.values
        if hasattr(X, "trend_"):
            if self.trend != 0:
                warnings.warn(
                    "IncrementalAdditive Trend assumption is ignored when X has a trend_ property."
                )
            x = obj * obj.trend_.values
        else:
            x = obj.trend(self.trend, axis='valuation')

        w_ = Development(
            n_periods=self.n_periods - 1, drop=self.drop,
            drop_high=self.drop_high, drop_low=self.drop_low,
            drop_valuation=self.drop_valuation).fit(x).w_
        # This will miss drops on the latest diagonal
        w_ = num_to_nan(w_)
        w_ = xp.concatenate((w_, (w_[..., -1:] * x.nan_triangle)[..., -1:]), axis=-1)
        if self.average == "simple":
            y_ = xp.nanmean(w_ * x.values, axis=-2)
        if self.average == "volume":
            y_ = xp.nansum(w_ * x.values * sample_weight.values, axis=-2)
            y_ = y_ / xp.nansum(w_ * sample_weight.values, axis=-2)
        self.zeta_ = X.iloc[..., -1:, :]
        self.zeta_.values = y_[:, :, None, :]
        y_ = xp.repeat(y_[..., None, :], len(x.odims), -2)
        obj = x.copy()
        keeps = (
            1
            - xp.nan_to_num(x.nan_triangle)
            + xp.nan_to_num(
                x[x.valuation == x.valuation_date].values[0, 0, ...] * 0 + 1
            )
        )
        obj.values = y_ * keeps
        obj.valuation_date = obj.valuation.max()
        obj.values = obj.values * (1 - xp.nan_to_num(x.nan_triangle)) + xp.nan_to_num(
            (X.cum_to_incr().values / sample_weight.values)
        )

        obj.values[obj.values == 0] = xp.nan
        obj._set_slicers()
        obj.valuation_date = obj.valuation.max()
        future_trend = self.trend if not self.future_trend else self.future_trend
        self.incremental_ = obj * sample_weight.values
        self.incremental_ = self.incremental_.trend(
            1/(1+future_trend)-1, axis='valuation', start=X.valuation_date,
            end=self.incremental_.valuation_date)
        self.ldf_ = obj.incr_to_cum().link_ratio
        self.sigma_ = self.std_err_ = 0 * self.ldf_
        return self