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
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
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
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
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
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
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