def constrain_params(self, unconstrained): """ Constrain parameter values to be valid through transformations. Parameters ---------- unconstrained : array_like Array of model unconstrained parameters. Returns ------- constrained : ndarray Array of model parameters transformed to produce a valid model. Notes ----- This is usually only used when performing numerical minimization of the log-likelihood function. This function is necessary because the minimizers consider values over the entire real space, while SARIMAX models require parameters in subspaces (for example positive variances). Examples -------- >>> spec = SARIMAXSpecification(ar_order=1) >>> spec.constrain_params([10, -2]) array([-0.99504, 4. ]) """ unconstrained = self.split_params(unconstrained) params = {} if self.k_exog_params: params['exog_params'] = unconstrained['exog_params'] if self.k_ar_params: if self.enforce_stationarity: params['ar_params'] = constrain(unconstrained['ar_params']) else: params['ar_params'] = unconstrained['ar_params'] if self.k_ma_params: if self.enforce_invertibility: params['ma_params'] = -constrain(unconstrained['ma_params']) else: params['ma_params'] = unconstrained['ma_params'] if self.k_seasonal_ar_params: if self.enforce_stationarity: params['seasonal_ar_params'] = (constrain( unconstrained['seasonal_ar_params'])) else: params['seasonal_ar_params'] = ( unconstrained['seasonal_ar_params']) if self.k_seasonal_ma_params: if self.enforce_invertibility: params['seasonal_ma_params'] = ( -constrain(unconstrained['seasonal_ma_params'])) else: params['seasonal_ma_params'] = ( unconstrained['seasonal_ma_params']) if not self.concentrate_scale: params['sigma2'] = unconstrained['sigma2']**2 return self.join_params(**params)
def test_specification(endog, exog, p, d, q, P, D, Q, s, enforce_stationarity, enforce_invertibility, concentrate_scale): # Assumptions: # - p, q, P, Q are either integers or lists of non-consecutive integers # (i.e. we are not testing boolean lists or consecutive lists here, which # should be tested in the `standardize_lag_order` tests) # Construct the specification if isinstance(p, list): k_ar_params = len(p) max_ar_order = p[-1] else: k_ar_params = max_ar_order = p if isinstance(q, list): k_ma_params = len(q) max_ma_order = q[-1] else: k_ma_params = max_ma_order = q if isinstance(P, list): k_seasonal_ar_params = len(P) max_seasonal_ar_order = P[-1] else: k_seasonal_ar_params = max_seasonal_ar_order = P if isinstance(Q, list): k_seasonal_ma_params = len(Q) max_seasonal_ma_order = Q[-1] else: k_seasonal_ma_params = max_seasonal_ma_order = Q # Get endog / exog nobs = d + D * s + max(3 * max_ma_order + 1, 3 * max_seasonal_ma_order * s + 1, max_ar_order, max_seasonal_ar_order * s) + 1 if endog is True: endog = np.arange(nobs) * 1.0 elif isinstance(endog, str): endog = pd.Series(np.arange(nobs) * 1.0, name=endog) elif endog is not None: raise ValueError('Invalid `endog` in test setup.') if isinstance(exog, int): exog_names = ['x%d' % (i + 1) for i in range(exog)] exog = np.arange(nobs * len(exog_names)).reshape(nobs, len(exog_names)) elif isinstance(exog, list): exog_names = exog exog = np.arange(nobs * len(exog_names)).reshape(nobs, len(exog_names)) exog = pd.DataFrame(exog, columns=exog_names) elif exog is None: exog_names = [] else: raise ValueError('Invalid `exog` in test setup.') # Setup args, kwargs args = ((p, d, q), (P, D, Q, s)) kwargs = { 'enforce_stationarity': enforce_stationarity, 'enforce_invertibility': enforce_invertibility, 'concentrate_scale': concentrate_scale } properties_kwargs = kwargs.copy() is_ar_consecutive = not isinstance(p, list) and max_seasonal_ar_order == 0 is_ma_consecutive = not isinstance(q, list) and max_seasonal_ma_order == 0 properties_kwargs.update({ 'is_ar_consecutive': is_ar_consecutive, 'is_ma_consecutive': is_ma_consecutive, 'exog_names': exog_names, 'ar_names': [ 'ar.L%d' % i for i in (p if isinstance(p, list) else range(1, p + 1)) ], 'ma_names': [ 'ma.L%d' % i for i in (q if isinstance(q, list) else range(1, q + 1)) ], 'seasonal_ar_names': [ 'ar.S.L%d' % (i * s) for i in (P if isinstance(P, list) else range(1, P + 1)) ], 'seasonal_ma_names': [ 'ma.S.L%d' % (i * s) for i in (Q if isinstance(Q, list) else range(1, Q + 1)) ] }) methods_kwargs = kwargs.copy() methods_kwargs.update({ 'exog_params': np.arange(len(exog_names)), 'ar_params': ([] if k_ar_params == 0 else constrain(np.arange(k_ar_params) / 10)), 'ma_params': ([] if k_ma_params == 0 else constrain( (np.arange(k_ma_params) + 10) / 100)), 'seasonal_ar_params': ([] if k_seasonal_ar_params == 0 else constrain(np.arange(k_seasonal_ar_params) - 4)), 'seasonal_ma_params': ([] if k_seasonal_ma_params == 0 else constrain( (np.arange(k_seasonal_ma_params) - 10) / 100)), 'sigma2': [] if concentrate_scale else 2.3424 }) # Test the spec created with order, seasonal_order spec = specification.SARIMAXSpecification( endog, exog=exog, order=(p, d, q), seasonal_order=(P, D, Q, s), enforce_stationarity=enforce_stationarity, enforce_invertibility=enforce_invertibility, concentrate_scale=concentrate_scale) check_attributes(spec, *args, **kwargs) check_properties(spec, *args, **properties_kwargs) check_methods(spec, *args, **methods_kwargs) # Test the spec created with ar_order, etc. spec = specification.SARIMAXSpecification( endog, exog=exog, ar_order=p, diff=d, ma_order=q, seasonal_ar_order=P, seasonal_diff=D, seasonal_ma_order=Q, seasonal_periods=s, enforce_stationarity=enforce_stationarity, enforce_invertibility=enforce_invertibility, concentrate_scale=concentrate_scale) check_attributes(spec, *args, **kwargs) check_properties(spec, *args, **properties_kwargs) check_methods(spec, *args, **methods_kwargs)