def periodic_cov_ss_opt_params(balance=False): """ Export state-space covariance function """ model_params = io.loadmat('/home/agrigori/Programming/python/Sparse GP/solin-2014-supplement/arno_opt_params_to_python.mat') # model.param_array[:] = np.array( [ model_params['per_magnSigma2'], model_params['per_period'], model_params['per_lengthscale'], # 1.0, model_params['quasi_per_mat32_lengthscale'], model_params['mat32_inacc_magnSigma2'], # model_params['mat32_inacc_lengthScale'], model_params['opt_noise'] ] ) var_1_per = float(model_params['per_magnSigma2']) ls_1_per = float(model_params['per_lengthscale']) / 2.0 # division by 2 is done because meanings in parameters are different period = float(model_params['per_period'][0]) kernel1 = GPy.kern.sde_StdPeriodic(1, variance=var_1_per, lengthscale=ls_1_per, period=period, balance=False, approx_order = 6) #import pdb; pdb.set_trace() (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = kernel1.sde() if balance: import GPy.models.state_space_main as ssm (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = ssm.balance_ss_model(F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0 ) #import pdb; pdb.set_trace() return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0)
def exp_quad_cov_ss(balance=False): """ Export state-space covariance function There is a difference between Python and Matlab implementation of RBF kernel the difference is (accurding to tests) appear because of different lyapunov equation solver. Balancing is also different in matlab and in Python. Just balancing function works differently, hence the results are not comparable. """ model_params = io.loadmat('/home/agrigori/Programming/python/Sparse GP/solin-2014-supplement/arno_opt_params_to_python.mat') var_1_trend = model_params['rbf_magnSigma2'] ls_1_trend = model_params['rbf_lengthscale'] # var_1_trend = 1e4 # ls_1_trend = 100 kernel1 = GPy.kern.sde_RBF(1, variance=var_1_trend, lengthscale=ls_1_trend, balance = False, approx_order = 6) (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = kernel1.sde() #import pdb; pdb.set_trace() if balance: import GPy.models.state_space_main as ssm (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = ssm.balance_ss_model(F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0 ) #import pdb; pdb.set_trace() return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0)
def matern32_cov_ss(balance=False): """ Export state-space covariance function """ var_1_per = 1.37 ls_1_per = 140 kernel1 = GPy.kern.sde_Matern32(1, variance=var_1_per, lengthscale=ls_1_per) (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = kernel1.sde() if balance: import GPy.models.state_space_main as ssm (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = ssm.balance_ss_model(F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0 ) #import pdb; pdb.set_trace() return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0)
def cov_except_RBF_ss(balance=False): """ State space model of covariance """ var_1_per = 5 ls_1_per = 1.3 / 2 # division by 2 is done because meanings in parameters are different period = 1.2 kernel1 = GPy.kern.sde_StdPeriodic(1, variance=var_1_per, lengthscale=ls_1_per, period=period, balance=False, approx_order = 6) var_1_per = 1 # does not change ls_1_per = 140 kernel2 = GPy.kern.sde_Matern32(1, variance=var_1_per, lengthscale=ls_1_per) # model.ss{1}.lengthScale = 1; # model.ss{1}.magnSigma2 = 5; # model.ss{1}.period = 1; % one year # model.ss{1}.N = 6; # appr. order for periodic part # model.ss{1}.nu = 3/2; # model.ss{1}.mN = 6; # appr. order for squared exponential # model.ss{1}.mlengthScale = 140; # model.ss{1}.opt = {'magnSigma2','lengthScale','mlengthScale'}; # Short term fluctuations kernel var_1_per = 0.5 ls_1_per = 1.7 kernel3 = GPy.kern.sde_Matern32(1, variance=var_1_per, lengthscale=ls_1_per) kernel = kernel1 * kernel2 + kernel3 print( kernel.parameter_names() ) #import pdb; pdb.set_trace() (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = kernel.sde() if balance: import GPy.models.state_space_main as ssm (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = ssm.balance_ss_model(F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0 ) #import pdb; pdb.set_trace() return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0)
def periodic_cov_ss(balance=False): """ Export state-space covariance function """ var_1_per = 5 ls_1_per = 2.3 / 2.0 # division by 2 is done because meanings in parameters are different period = 1.46 kernel1 = GPy.kern.sde_StdPeriodic(1, variance=var_1_per, lengthscale=ls_1_per, period=period, balance=False, approx_order = 6) (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = kernel1.sde() if balance: import GPy.models.state_space_main as ssm (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = ssm.balance_ss_model(F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0 ) #import pdb; pdb.set_trace() return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0)
def cov_except_RBF_ss_opt_params(balance=False): """ Almost the same as before except parameters are optimal """ model_params = io.loadmat('/home/agrigori/Programming/python/Sparse GP/solin-2014-supplement/arno_opt_params_to_python.mat') # model.param_array[:] = np.array( [ model_params['per_magnSigma2'], model_params['per_period'], model_params['per_lengthscale'], # 1.0, model_params['quasi_per_mat32_lengthscale'], model_params['mat32_inacc_magnSigma2'], # model_params['mat32_inacc_lengthScale'], model_params['opt_noise'] ] ) var_1_per = model_params['per_magnSigma2'] ls_1_per = model_params['per_lengthscale'] / 2 # division by 2 is done because meanings in parameters are different period = model_params['per_period'] kernel1 = GPy.kern.sde_StdPeriodic(1, variance=var_1_per, lengthscale=ls_1_per, period=period, balance=False, approx_order = 6) var_1_per = 1 # does not change ls_1_per = model_params['quasi_per_mat32_lengthscale'] kernel2 = GPy.kern.sde_Matern32(1, variance=var_1_per, lengthscale=ls_1_per) # Short term fluctuations kernel var_1_per = model_params['mat32_inacc_magnSigma2'] ls_1_per = model_params['mat32_inacc_lengthScale'] kernel3 = GPy.kern.sde_Matern32(1, variance=var_1_per, lengthscale=ls_1_per) kernel = kernel1*kernel2 + kernel3 print( kernel.parameter_names() ) #import pdb; pdb.set_trace() (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = kernel.sde() if balance: import GPy.models.state_space_main as ssm (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = ssm.balance_ss_model(F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0 ) #import pdb; pdb.set_trace() return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0)
def sde(self): """ Return the state space representation of the covariance. """ N = 10 # approximation order ( number of terms in exponent series expansion) roots_rounding_decimals = 6 fn = np.math.factorial(N) kappa = 1.0 / 2.0 / self.lengthscale**2 Qc = np.array( (self.variance * np.sqrt(np.pi / kappa) * fn * (4 * kappa)**N, ), ) pp = np.zeros( (2 * N + 1, )) # array of polynomial coefficients from higher power to lower for n in range(0, N + 1): # (2N+1) - number of polynomial coefficients pp[2 * (N - n)] = fn * (4.0 * kappa)**( N - n) / np.math.factorial(n) * (-1)**n pp = sp.poly1d(pp) roots = sp.roots(pp) neg_real_part_roots = roots[ np.round(np.real(roots), roots_rounding_decimals) < 0] aa = sp.poly1d(neg_real_part_roots, r=True).coeffs F = np.diag(np.ones((N - 1, )), 1) F[-1, :] = -aa[-1:0:-1] L = np.zeros((N, 1)) L[N - 1, 0] = 1 H = np.zeros((1, N)) H[0, 0] = 1 # Infinite covariance: Pinf = sp.linalg.solve_lyapunov(F, -np.dot(L, np.dot(Qc[0, 0], L.T))) Pinf = 0.5 * (Pinf + Pinf.T) # Allocating space for derivatives dF = np.empty([F.shape[0], F.shape[1], 2]) dQc = np.empty([Qc.shape[0], Qc.shape[1], 2]) dPinf = np.empty([Pinf.shape[0], Pinf.shape[1], 2]) # Derivatives: dFvariance = np.zeros(F.shape) dFlengthscale = np.zeros(F.shape) dFlengthscale[-1, :] = -aa[-1:0:-1] / self.lengthscale * np.arange( -N, 0, 1) dQcvariance = Qc / self.variance dQclengthscale = np.array( ((self.variance * np.sqrt(2 * np.pi) * fn * 2**N * self.lengthscale**(-2 * N) * (1 - 2 * N, ), ))) dPinf_variance = Pinf / self.variance lp = Pinf.shape[0] coeff = np.arange(1, lp + 1).reshape(lp, 1) + np.arange( 1, lp + 1).reshape(1, lp) - 2 coeff[np.mod(coeff, 2) != 0] = 0 dPinf_lengthscale = -1 / self.lengthscale * Pinf * coeff dF[:, :, 0] = dFvariance dF[:, :, 1] = dFlengthscale dQc[:, :, 0] = dQcvariance dQc[:, :, 1] = dQclengthscale dPinf[:, :, 0] = dPinf_variance dPinf[:, :, 1] = dPinf_lengthscale P0 = Pinf.copy() dP0 = dPinf.copy() # Benefits of this are not very sound. Helps only in one case: # SVD Kalman + RBF kernel import GPy.models.state_space_main as ssm (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0, T) = ssm.balance_ss_model(F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0)
def sde(self): """ Return the state space representation of the covariance. Note! For Sparse GP inference too small or two high values of lengthscale lead to instabilities. This is because Qc are too high or too low and P_inf are not full rank. This effect depends on approximatio order. For N = 10. lengthscale must be in (0.8,8). For other N tests must be conducted. N=6: (0.06,31) Variance should be within reasonable bounds as well, but its dependence is linear. The above facts do not take into accout regularization. """ #import pdb; pdb.set_trace() if self.approx_order is not None: N = self.approx_order else: N = 10 # approximation order ( number of terms in exponent series expansion) roots_rounding_decimals = 6 fn = np.math.factorial(N) p_lengthscale = float(self.lengthscale) p_variance = float(self.variance) kappa = 1.0 / 2.0 / p_lengthscale**2 Qc = np.array( ((p_variance * np.sqrt(np.pi / kappa) * fn * (4 * kappa)**N, ), )) eps = 1e-12 if (float(Qc) > 1.0 / eps) or (float(Qc) < eps): warnings.warn( """sde_RBF kernel: the noise variance Qc is either very large or very small. It influece conditioning of P_inf: {0:e}""". format(float(Qc))) pp1 = np.zeros( (2 * N + 1, )) # array of polynomial coefficients from higher power to lower for n in range(0, N + 1): # (2N+1) - number of polynomial coefficients pp1[2 * (N - n)] = fn * (4.0 * kappa)**( N - n) / np.math.factorial(n) * (-1)**n pp = sp.poly1d(pp1) roots = sp.roots(pp) neg_real_part_roots = roots[ np.round(np.real(roots), roots_rounding_decimals) < 0] aa = sp.poly1d(neg_real_part_roots, r=True).coeffs F = np.diag(np.ones((N - 1, )), 1) F[-1, :] = -aa[-1:0:-1] L = np.zeros((N, 1)) L[N - 1, 0] = 1 H = np.zeros((1, N)) H[0, 0] = 1 # Infinite covariance: Pinf = lyap(F, -np.dot(L, np.dot(Qc[0, 0], L.T))) Pinf = 0.5 * (Pinf + Pinf.T) # Allocating space for derivatives dF = np.empty([F.shape[0], F.shape[1], 2]) dQc = np.empty([Qc.shape[0], Qc.shape[1], 2]) dPinf = np.empty([Pinf.shape[0], Pinf.shape[1], 2]) # Derivatives: dFvariance = np.zeros(F.shape) dFlengthscale = np.zeros(F.shape) dFlengthscale[-1, :] = -aa[-1:0:-1] / p_lengthscale * np.arange( -N, 0, 1) dQcvariance = Qc / p_variance dQclengthscale = np.array( ((p_variance * np.sqrt(2 * np.pi) * fn * 2**N * p_lengthscale**(-2 * N) * (1 - 2 * N), ), )) dPinf_variance = Pinf / p_variance lp = Pinf.shape[0] coeff = np.arange(1, lp + 1).reshape(lp, 1) + np.arange( 1, lp + 1).reshape(1, lp) - 2 coeff[np.mod(coeff, 2) != 0] = 0 dPinf_lengthscale = -1 / p_lengthscale * Pinf * coeff dF[:, :, 0] = dFvariance dF[:, :, 1] = dFlengthscale dQc[:, :, 0] = dQcvariance dQc[:, :, 1] = dQclengthscale dPinf[:, :, 0] = dPinf_variance dPinf[:, :, 1] = dPinf_lengthscale P0 = Pinf.copy() dP0 = dPinf.copy() if self.balance: # Benefits of this are not very sound. Helps only in one case: # SVD Kalman + RBF kernel import GPy.models.state_space_main as ssm (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) = ssm.balance_ss_model(F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0) return (F, L, Qc, H, Pinf, P0, dF, dQc, dPinf, dP0)
def sde(self): """ Return the state space representation of the standard periodic covariance. ! Note: one must constrain lengthscale not to drop below 0.2. (independently of approximation order) After this Bessel functions of the first becomes NaN. Rescaling time variable might help. ! Note: one must keep period also not very low. Because then the gradients wrt wavelength become ustable. However this might depend on the data. For test example with 300 data points the low limit is 0.15. """ #import pdb; pdb.set_trace() # Params to use: (in that order) #self.variance #self.period #self.lengthscale if self.approx_order is not None: N = int(self.approx_order) else: N = 7 # approximation order p_period = float(self.period) p_lengthscale = 2 * float(self.lengthscale) p_variance = float(self.variance) w0 = 2 * np.pi / p_period # frequency # lengthscale is multiplied by 2 because of different definition of lengthscale [q2, dq2l] = seriescoeff(N, p_lengthscale, p_variance) dq2l = 2 * dq2l # This is because the lengthscale if multiplied by 2. eps = 1e-12 if np.any(np.isfinite(q2) == False) or np.any( np.abs(q2) > 1.0 / eps) or np.any(np.abs(q2) < eps): warnings.warn( "sde_Periodic: Infinite, too small, or too large (eps={0:e}) values in q2 :" .format(eps) + q2.__format__("")) if np.any(np.isfinite(dq2l) == False) or np.any( np.abs(dq2l) > 1.0 / eps) or np.any(np.abs(dq2l) < eps): warnings.warn( "sde_Periodic: Infinite, too small, or too large (eps={0:e}) values in dq2l :" .format(eps) + q2.__format__("")) F = np.kron(np.diag(range(0, N + 1)), np.array(((0, -w0), (w0, 0)))) L = np.eye(2 * (N + 1)) Qc = np.zeros((2 * (N + 1), 2 * (N + 1))) P_inf = np.kron(np.diag(q2), np.eye(2)) H = np.kron(np.ones((1, N + 1)), np.array((1, 0))) P0 = P_inf.copy() # Derivatives dF = np.empty((F.shape[0], F.shape[1], 3)) dQc = np.empty((Qc.shape[0], Qc.shape[1], 3)) dP_inf = np.empty((P_inf.shape[0], P_inf.shape[1], 3)) # Derivatives wrt self.variance dF[:, :, 0] = np.zeros(F.shape) dQc[:, :, 0] = np.zeros(Qc.shape) dP_inf[:, :, 0] = P_inf / p_variance # Derivatives self.period dF[:, :, 1] = np.kron(np.diag(range(0, N + 1)), np.array(((0, w0), (-w0, 0))) / p_period) dQc[:, :, 1] = np.zeros(Qc.shape) dP_inf[:, :, 1] = np.zeros(P_inf.shape) # Derivatives self.lengthscales dF[:, :, 2] = np.zeros(F.shape) dQc[:, :, 2] = np.zeros(Qc.shape) dP_inf[:, :, 2] = np.kron(np.diag(dq2l), np.eye(2)) dP0 = dP_inf.copy() if self.balance: # Benefits of this are not very sound. import GPy.models.state_space_main as ssm (F, L, Qc, H, P_inf, P0, dF, dQc, dP_inf, dP0) = ssm.balance_ss_model(F, L, Qc, H, P_inf, P0, dF, dQc, dP_inf, dP0) return (F, L, Qc, H, P_inf, P0, dF, dQc, dP_inf, dP0)