Exemplo n.º 1
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):
     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
Exemplo n.º 3
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
Exemplo n.º 4
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
Exemplo n.º 5
0
    def fit(self, X, y=None, sample_weight=None):
        backend = X.array_backend
        if backend == 'sparse':
            obj = X.set_backend('numpy')
        else:
            obj = copy.deepcopy(X)
        xp = obj.get_array_module()
        if not (self.paid_amount in X.columns and self.incurred_amount
                in X.columns and self.reported_count in X.columns
                and self.closed_count in X.columns):
            raise ValueError(
                'Must enter values valid columns for paid_amount, incurred_amount, reported_count and closed_count'
            )
        paid_amount = self.paid_amount
        incurred_amount = self.incurred_amount
        reported_count = self.reported_count
        closed_count = self.closed_count
        reported_count_estimator = self.reported_count_estimator
        # Case reserve adequacy adjustment
        open_count = obj[reported_count] - obj[closed_count]
        avg_case = (obj[incurred_amount] - obj[paid_amount]) / open_count
        adj_avg_case = (
            avg_case.trend(1 / (1 + self.trend) - 1, axis='valuation') /
            avg_case * avg_case[avg_case.valuation ==
                                avg_case.valuation_date].sum('origin'))
        adj_incurred_amount = adj_avg_case * open_count + obj[paid_amount]

        # Paid and closed claim adjustments
        if reported_count_estimator is None:
            reported_count_estimator = Chainladder()
        reported_count_estimator.fit(obj[reported_count])
        if reported_count_estimator.__class__.__name__ == 'Pipeline':
            rep_cnt_ult = reported_count_estimator.named_steps[
                reported_count_estimator.steps[-1][0]].ultimate_
        else:
            rep_cnt_ult = reported_count_estimator.ultimate_
        disposal_rate = (obj[closed_count] / rep_cnt_ult)
        adj_closed_clm = ((disposal_rate * 0 + 1) * disposal_rate[
            disposal_rate.valuation == X.valuation_date].mean('origin') *
                          rep_cnt_ult)
        adj_closed_clm.valuation_date = disposal_rate.valuation_date = X.valuation_date

        # Two-period exponential regression
        y = obj[paid_amount]
        x = obj[closed_count]
        x0 = x.values[..., :-1]
        x1 = x.values[..., 1:]
        y0 = xp.log(y.values[..., :-1])
        y1 = xp.log(y.values[..., 1:])
        b = ((x0*y0+x1*y1)/2-(x0+x1)/2*(y0+y1)/2) / \
            ((x0**2+x1**2)/2-((x0+x1)/2)**2)
        a = np.exp((y0 + y1) / 2 - b * (x0 + x1) / 2)

        # Need to Ignore warnings for NaN cells
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            lookup = np.maximum(
                xp.concatenate(
                    [(adj_closed_clm.values[..., i:i + 1] >
                      obj[closed_count].values).sum(axis=-1, keepdims=True)
                     for i in range(adj_closed_clm.shape[-1])],
                    axis=-1), 1) - 1
        a = xp.concatenate(
            [a[..., i, lookup[0, 0, i:i+1, :]]
             for i in range(lookup.shape[-2])], -2) * \
            adj_closed_clm.nan_triangle[None,None,...]
        b = xp.concatenate(
            [b[..., i, lookup[0, 0, i:i+1, :]]
             for i in range(lookup.shape[-2])], -2) * \
            adj_closed_clm.nan_triangle[None,None,...]
        # Adjust paids
        adj_paid_claims = adj_closed_clm * 0 + xp.exp(
            adj_closed_clm.values * b) * a
        adj_paid_claims = (
            y[y.valuation == y.valuation_date] + adj_paid_claims[
                adj_paid_claims.valuation < adj_paid_claims.valuation_date])

        adjusted_triangle_ = copy.deepcopy(obj)
        adjusted_triangle_[paid_amount] = adj_paid_claims
        adjusted_triangle_[incurred_amount] = adj_incurred_amount
        adjusted_triangle_[closed_count] = adj_closed_clm
        adjusted_triangle_ = adjusted_triangle_[
            adjusted_triangle_.valuation <= obj.valuation_date]
        self.adjusted_triangle_ = adjusted_triangle_.set_backend(backend)
        self.disposal_rate_ = disposal_rate.set_backend(backend)
        self.a_ = a
        self.b_ = b
        return self
Exemplo n.º 6
0
 def fit(self, X, y=None, sample_weight=None):
     if X.shape[1] > 1:
         from chainladder.utils.utility_functions import concat
         out = [
             BootstrapODPSample(**self.get_params()).fit(X.iloc[:, i])
             for i in range(X.shape[1])
         ]
         xp = X.get_array_module(out[0].design_matrix_)
         self.design_matrix_ = xp.concatenate(
             [i.design_matrix_[None] for i in out], axis=0)
         self.hat_ = xp.concatenate([i.hat_[None] for i in out], axis=0)
         self.resampled_triangles_ = concat(
             [i.resampled_triangles_ for i in out], axis=1)
         self.scale_ = xp.array([i.scale_ for i in out])
         self.w_ = out[0].w_
     else:
         backend = X.array_backend
         if backend == "sparse":
             X = X.set_backend("numpy")
         else:
             X = X.copy()
         xp = X.get_array_module()
         if len(X) != 1:
             raise ValueError("Only single index 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