def logpdf(self, f, y, Y_metadata=None): c = Y_metadata['censored'] c = c.reshape(*y.shape) D = y.shape[1] fv, gv = f[:, :D], f[:, D:] ef = safe_exp(fv) eg = safe_exp(gv) #y_link_f_r = np.clip((y/ef)**eg, 1e-150, 1e200) # y_link_f_r = (y/ef)**eg # log1p_y_link_f_r = np.log1p(y_link_f_r) def log1pexp(x): # more Numerically stable "softplus" b1 = np.atleast_1d(x <= -37) b2 = np.atleast_1d((x > -37) & (x <= 18)) b3 = np.atleast_1d((x > 18) & (x <= 33.3)) b4 = np.atleast_1d(x > 33.3) xc = np.atleast_1d(x) xnew = np.zeros_like(x)*np.nan xnew = np.atleast_1d(xnew) xnew[b1] = np.exp(xc[b1]) xnew[b2] = np.log1p(np.exp(xc[b2])) xnew[b3] = xc[b3] + np.exp(-xc[b3]) xnew[b4] = xc[b4] if np.isscalar(x): return float(xnew) return xnew # log1p_y_link_f_r = np.log1p(np.exp(eg*(np.log(y) - fv))) log1p_y_link_f_r = log1pexp(eg*(np.log(y) - fv)) uncensored = (1-c)*(np.log(eg) + (eg-1)*np.log(y) - eg*np.log(ef) - 2*log1p_y_link_f_r) censored = (c)*(-log1p_y_link_f_r) return uncensored + censored
def logpdf(self, f, y, Y_metadata=None): c = Y_metadata['censored'] c = c.reshape(*y.shape) D = y.shape[1] fv, gv = f[:, :D], f[:, D:] ef = safe_exp(fv) eg = safe_exp(gv) #y_link_f_r = np.clip((y/ef)**eg, 1e-150, 1e200) # y_link_f_r = (y/ef)**eg # log1p_y_link_f_r = np.log1p(y_link_f_r) def log1pexp(x): # more Numerically stable "softplus" b1 = np.atleast_1d(x <= -37) b2 = np.atleast_1d((x > -37) & (x <= 18)) b3 = np.atleast_1d((x > 18) & (x <= 33.3)) b4 = np.atleast_1d(x > 33.3) xc = np.atleast_1d(x) xnew = np.zeros_like(x) * np.nan xnew = np.atleast_1d(xnew) xnew[b1] = np.exp(xc[b1]) xnew[b2] = np.log1p(np.exp(xc[b2])) xnew[b3] = xc[b3] + np.exp(-xc[b3]) xnew[b4] = xc[b4] if np.isscalar(x): return float(xnew) return xnew # log1p_y_link_f_r = np.log1p(np.exp(eg*(np.log(y) - fv))) log1p_y_link_f_r = log1pexp(eg * (np.log(y) - fv)) uncensored = (1 - c) * (np.log(eg) + (eg - 1) * np.log(y) - eg * np.log(ef) - 2 * log1p_y_link_f_r) censored = (c) * (-log1p_y_link_f_r) return uncensored + censored
def d2logp_df2(self, F, y, Y_metadata=None): mu = safe_exp(F[:, 0, None]) alpha = safe_exp(F[:, 1, None]) / (safe_exp(F[:, 1, None]) + 1.0) r = 1.0 / alpha mu = np.clip(mu, 1e-9, 1e9) # numerical stability r = np.clip(r, 1e-9, 1e9) # numerical stability psi_yr = psi(y + r) psi_r = psi(r) dsig = alpha * (1 - alpha) C_prime = -(r) * (1 - alpha) A_prime = 2 * (r) * C_prime B_prime1 = -polygamma(1, y + r) * C_prime + polygamma( 1, r) * C_prime + (dsig / alpha) + C_prime / (r + mu) B_prime2 = (C_prime * (r + mu) - (r + y) * (C_prime)) / ((r + mu)**2) B_prime = B_prime1 + B_prime2 B = (-psi_yr + psi_r - np.log(r) + np.log(r + mu) + r / (r + mu) + y / (r + mu) - 1) d2logpdf_dalpha = A_prime * B + (r**2) * B_prime d2alpha_df1 = dsig * (1 - 2 * alpha) d2logp_df1 = d2alpha_df1 * (r**2) * B + dsig * d2logpdf_dalpha D = (-r / (r + mu) + y / mu - y / (r + mu)) E = mu.copy( ) # this is also E_prime sice mu = exp(f0) then E_prime=dmu_df0=exp(f0) D_prime = (r + y) * ((r + mu)**(-2)) * E - y * (mu**(-2)) * E d2logp_df0 = D_prime * E + D * E return d2logp_df0, d2logp_df1
def predictive(self, M, V, gh_points=None, Y_metadata=None): # Variational Expectation # gh: Gaussian-Hermite quadrature if gh_points is None: gh_f, gh_w = self._gh_points() else: gh_f, gh_w = gh_points gh_w = gh_w / np.sqrt(np.pi) # f1 = gh_f[None, :] * np.sqrt(2. * V[:,0,None]) + M[:,0,None] # f2 = gh_f[None, :] * np.sqrt(2. * V[:,1,None]) + M[:,1,None] _, R = M.shape mean_pred = [] var_pred = [] mean_pred.append(M[:, 0, None]) var_pred.append(V[:, 0, None]) for m in range(R - 1): auxm = safe_exp(M[:, m + 1, None] + V[:, m + 1, None] / 2) auxv = (safe_exp(V[:, m + 1, None]) - 1) * safe_exp(2 * M[:, m + 1, None] + V[:, m + 1, None]) mean_pred.append(auxm) var_pred.append(auxv) return mean_pred, var_pred
def variance(self, F, Y_metadata=None): mu = safe_exp(F[:, 0, None]) alpha = safe_exp(F[:, 1, None]) / (safe_exp(F[:, 1, None]) + 1.0) r = 1.0 / alpha mu = np.clip(mu, 1e-9, 1e9) # numerical stability r = np.clip(r, 1e-9, 1e9) # numerical stability var = mu + (1.0 / r) * (mu**2) return var
def pdf(self, F, y, Y_metadata=None): eF = safe_exp(F) a = eF[:, 0, None] b = eF[:, 1, None] a = np.clip(a, 1e-9, 1e9) # numerical stability b = np.clip(b, 1e-9, 1e9) # numerical stability pdf = (b**a) * (y**(a - 1)) * safe_exp(-b * y) / gamma(a) return pdf
def pdf(self, F, y, Y_metadata=None): # exp(F[:,0]) is the mean # sigmoid(F[:,1]) is the parameter alpha=1/r mu = safe_exp(F[:, 0, None]) alpha = safe_exp(F[:, 1, None]) / (safe_exp(F[:, 1, None]) + 1.0) r = 1.0 / alpha coef = gamma(y + r) / (gamma(y + 1) * gamma(r)) pdf = coef * ((r / (r + mu))**r) * ((mu / (r + mu))**y) return pdf
def logpdf(self, F, y, Y_metadata=None): mu = safe_exp(F[:, 0, None]) alpha = safe_exp(F[:, 1, None]) / (safe_exp(F[:, 1, None]) + 1.0) r = 1.0 / alpha mu = np.clip(mu, 1e-9, 1e9) # numerical stability r = np.clip(r, 1e-9, 1e9) # numerical stability logpdf = gammaln(y + r) - gammaln(y + 1) - gammaln(r) + r * ( np.log(r) - np.log(r + mu)) + y * (np.log(mu) - np.log(r + mu)) return logpdf
def samples(self, F, num_samples, Y_metadata=None): mu = safe_exp(F[:, 0, None]) alpha = safe_exp(F[:, 1, None]) / (safe_exp(F[:, 1, None]) + 1.0) r = 1.0 / alpha mu = np.clip(mu, 1e-9, 1e9) # numerical stability r = np.clip(r, 1e-9, 1e9) # numerical stability p = r / (mu + r) samples = np.random.negative_binomial(r, p) return samples
def pdf(self, F, y, Y_metadata): N, _ = y.shape iAnn = Y_metadata var_r = safe_exp(F[:, 1:]) ym = (y - F[:, 0]) logpdf_m = -0.5 (np.log(2 * np.pi * var_r) - ((ym**2) / var_r)) logpdf = np.sum(logpdf_m * iAnn, 1) pdf = safe_exp(logpdf).reshape((N, 1)) return pdf
def mean_sq(self, F, Y_metadata=None): ef0 = safe_exp(F[:, 0, None]) phi = ef0 / (1 + ef0) phi = np.clip(phi, 1.0e-15, 1.0) # numerical stability lamb_poisson = safe_exp(F[:, 1, None]) lamb_poisson = np.clip(lamb_poisson, 0.0, 1.797e308) # numerical stability mean = (1 - phi) * lamb_poisson mean_sq = np.square(mean) return mean_sq
def variance(self, F, Y_metadata=None): ef0 = safe_exp(F[:, 0, None]) phi = ef0 / (1 + ef0) phi = np.clip(phi, 1.0e-15, 1.0) # numerical stability lamb_poisson = safe_exp(F[:, 1, None]) lamb_poisson = np.clip(lamb_poisson, 0.0, 1.797e308) # numerical stability # a = np.clip(a, 1e-9, 1e9) # numerical stability # b = np.clip(b, 1e-9, 1e9) # numerical stability var = (1 - phi) * lamb_poisson * (1 + lamb_poisson * phi) return var
def quad2d(self, funcs, Y, mf, vf, mg, vg, gh_points, exp_f=False, exp_g=False, **kwargs): """ Given a list of functions to do quadrature over, expecting just latent functions f, and g to integrate over, do the quadrature for each and return a list of results Requires the list of functions, Y and the mean and variances of the two distributions to integrate over exp_g takes the exponential of g before passing it to ALL funcs in the list, be careful that this is what you want """ #Do some testing to see if the quadrature works well for one datapoint if gh_points is None: gh_x, gh_w = self._gh_points(T=10) else: gh_x, gh_w = gh_points #Numpy implementation of quadrature #We want to make it so we have the same shapes before we flatten them, so we make space for everything Xf = np.zeros((mf.shape[0], gh_x.shape[0], gh_x.shape[0], mf.shape[1])) Xg = np.zeros((mg.shape[0], gh_x.shape[0], gh_x.shape[0], mg.shape[1])) #Need to stretch the points Xf[:] = gh_x[None, :, None, None]*np.sqrt(2*vf[:, None, None, :]) + mf[:, None, None, :] Xg[:] = gh_x[None, None, :, None]*np.sqrt(2*vg[:, None, None, :]) + mg[:, None, None, :] #def f_func(f, g, y): #return -0.5*np.log(2*np.pi*np.exp(g)) -0.5*((y-f)**2)/np.exp(g) #Reshape into a big array ready for the function to be applied such that it broadcasts properly Xf_rs = Xf.reshape(Xf.shape[0]*Xf.shape[1]*Xf.shape[2], -1, order='C') Xg_rs = Xg.reshape(Xg.shape[0]*Xg.shape[1]*Xg.shape[2], -1, order='C') y_full = np.repeat(Y, gh_x.shape[0]**2, axis=0) results = [] if exp_g: Xg_rs = safe_exp(Xg_rs) if exp_f: Xf_rs = safe_exp(Xf_rs) for func in funcs: func_res= func(Xf_rs, Xg_rs, y_full, **kwargs) func_res = func_res.reshape(mf.shape[0], gh_x.shape[0], gh_x.shape[0]) #division by pi comes from fact that for each quadrature we need to scale by 1/sqrt(pi) #Assume 1D out at the moment quad_result = (np.dot(func_res, gh_w).dot(gh_w)/np.pi)[:, None] results.append(quad_result) #Could maybe do -? #quad_result = func*gh_w[None, :, None]*gh_w[None, None, :] #quad_result= quad_result.sum(-1).sum(-1)/np.pi return results
def samples(self, F, num_samples, Y_metadata=None): ef0 = safe_exp(F[:, 0, None]) phi = ef0 / (1 + ef0) phi = np.clip(phi, 1.0e-15, 1.0) # numerical stability lamb_poisson = safe_exp(F[:, 1, None]) lamb_poisson = np.clip(lamb_poisson, 0.0, 1.797e308) # numerical stability probability_for_zero = phi #+ (1-phi)*safe_exp(-lamb_poisson) #print('f and phi:',f[:,0],phi) bernoulli_samples = np.random.binomial(n=1, p=1 - probability_for_zero) poisson_samples = np.random.poisson(lam=lamb_poisson) samples = bernoulli_samples * poisson_samples return samples
def d2logp_df2(self, df, F, y, Y_metadata=None): # df: indicated the derivated function f from F Y_oneK = self.onehot(y) eF = safe_exp(F) den = 1 + eF.sum(1)[:, None] num = F + np.tile(F[:,df,None],(1,F.shape[1])) enum = safe_exp(num) enum[:,df] = safe_exp(F[:,df]) num = enum.sum(1)[:,None] p = num / safe_square(den) #añadir clip #p = p / np.tile(p.sum(1), (1, p.shape[1])) yp = Y_oneK*np.tile(p, (1, Y_oneK.shape[1])) #old, new is simpler d2logp = - yp.sum(1)[:,None] #old, new is simpler return d2logp
def log_ZI_argument(self, y, F): # Computing the Zero-Inflated (ZI) part of the likelihood: \log (phi*exp(lamb_poisson)+1-phi) # Here f[:,0] is latent GP for phi = sigmoid(f[:,0]) and f[:,1] is latent GP for lamb_poisson = exp(f[:,1]) ef0 = safe_exp(F[:, 0, None]) phi = ef0 / (1 + ef0) phi = np.clip(phi, 1.0e-15, 1.0) # numerical stability res = 1 - phi # Here phi should be a vector of probabilities, i.e. a squashing function of the latent GP lamb_poisson = safe_exp(F[:, 1, None]) lamb_poisson = np.clip(lamb_poisson, 0.0, 1.797e308) # numerical stability # res = y.copy() whichzeros = (y == 0) res[whichzeros] = res[whichzeros] + phi[whichzeros] * safe_exp( lamb_poisson[whichzeros]) return np.log(res)
def F_quad_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] x = safe_exp(-f * e_g + e_g * np.log(y)) log1px = np.log1p(x) uncensored = (1 - c) * (-2 * log1px) censored = c * (-log1px) return uncensored + censored
def d2logp_df2(self, f, y, Y_metadata=None): ef = safe_exp(f) p = ef / (1 + ef) p = np.clip(p, 1e-9, 1. - 1e-9) # numerical stability d2logp = -p / (1 + ef) #d2logp = (1 / (1 + ef))*((p*(y - 1)/((1 + ef)*(1 - p)**2)) - p*y + (1 - y)*(p**2 / (1 - p))) return d2logp
def dlogp_df(self, f, y, Y_metadata=None): ef = safe_exp(f) p = ef / (1 + ef) p = np.clip(p, 1e-9, 1. - 1e-9) # numerical stability dlogp = ((y - p) / (1 - p)) * (1 / (1 + ef)) #dlogp = ( y - (1 - y)*(p / (1 - p)))*(1 / (1 + ef)) return dlogp
def var_exp_derivatives(self, Y, M, V, GN=None, gh_points=None, Y_metadata=None): # Variational Expectations of derivatives N, R = Y.shape iAnn = Y_metadata var_exp_dm = np.empty((M.shape[0], R + 1)) var_exp_dv = np.empty((M.shape[0], R + 1)) m_fmean, m_fvar = M[:, :1], M[:, 1:] v_fmean, v_fvar = V[:, :1], V[:, 1:] precision = safe_exp(-m_fvar + (0.5 * v_fvar)) precision = np.clip(precision, -1e9, 1e9) # numerical stability squares = (np.square(Y) + np.square(m_fmean) + v_fmean - (2 * m_fmean * Y)) squares = np.clip(squares, -1e9, 1e9) # numerical stability var_exp_dm[:, 0] = np.sum(precision * (Y - m_fmean) * iAnn, axis=1) var_exp_dm[:, 1:] = 0.5 * ((precision * squares) - 1.) * iAnn var_exp_dv[:, 0] = np.sum(-0.5 * precision * iAnn, 1) var_exp_dv[:, 1:] = -0.25 * precision * squares * iAnn return var_exp_dm, var_exp_dv
def dlogp_df(self, F, y, Y_metadata=None): mu = safe_exp(F[:, 0, None]) alpha = safe_exp(F[:, 1, None]) / (safe_exp(F[:, 1, None]) + 1.0) r = 1.0 / alpha mu = np.clip(mu, 1e-9, 1e9) # numerical stability r = np.clip(r, 1e-9, 1e9) # numerical stability psi_yr = psi(y + r) psi_r = psi(r) dmu_df0 = mu.copy() dlogp_df0 = dmu_df0 * (-r / (r + mu) + y / mu - y / (r + mu)) dalpha_df1 = alpha * (1 - alpha) dlogp_df1 = dalpha_df1 * (-(r**2) * psi_yr + (r**2) * psi_r - (r**2) * np.log(r) + (r**2) * np.log(r + mu) + (r**3) / (r + mu) + (r**2) * y / (r + mu) - r**2) return dlogp_df0, dlogp_df1
def F_quad_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] x = safe_exp(-f*e_g + e_g*np.log(y)) log1px = np.log1p(x) uncensored = (1-c)*(-2*log1px) censored = c*(-log1px) return uncensored + censored
def variance(self, F, Y_metadata=None): eF = safe_exp(F) a = eF[:, 0, None] b = eF[:, 1, None] a = np.clip(a, 1e-9, 1e9) # numerical stability b = np.clip(b, 1e-9, 1e9) # numerical stability var = a * b / ((a + b)**2 * (a + b + 1)) return var
def samples(self, F, num_samples, Y_metadata=None): eF = safe_exp(F) a = eF[:, 0, None] b = eF[:, 1, None] a = np.clip(a, 1e-9, 1e9) # numerical stability b = np.clip(b, 1e-9, 1e9) # numerical stability samples = np.random.beta(a=a, b=b) return samples
def logpdf(self, F, y, Y_metadata=None): eF = safe_exp(F) a = eF[:,0,None] b = eF[:,1,None] a = np.clip(a, 1e-9, 1e9) # numerical stability b = np.clip(b, 1e-9, 1e9) # numerical stability logpdf = ((a - 1)*np.log(y)) + ((b - 1)*np.log(1-y)) - betaln(a, b) return logpdf
def logpdf(self, F, y, Y_metadata=None): eF = safe_exp(F) a = eF[:,0,None] b = eF[:,1,None] a = np.clip(a, 1e-9, 1e9) # numerical stability b = np.clip(b, 1e-9, 1e9) # numerical stability logpdf = - gammaln(a) + (a*np.log(b)) + ((a-1)*np.log(y)) - (b*y) return logpdf
def mean(self, F, Y_metadata=None): eF = safe_exp(F) a = eF[:, 0, None] b = eF[:, 1, None] a = np.clip(a, 1e-9, 1e9) # numerical stability b = np.clip(b, 1e-9, 1e9) # numerical stability mean = a / (a + b) return mean
def logpdf(self, F, y, Y_metadata=None): N, _ = y.shape iAnn = Y_metadata var_r = safe_exp(F[:, 1:]) ym = (y - F[:, 0]) logpdf_m = -0.5 (np.log(2 * np.pi * var_r) - ((ym**2) / var_r)) logpdf = np.sum(logpdf_m * iAnn, 1) return logpdf
def F_d2quad_df2_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] l_y = np.log(y) x = safe_exp(e_g*(l_y - f)) e2g = np.exp(2*np.log(e_g)) t = e2g/(x+1) - e2g/(x+1)**2 uncensored = (1-c)*(-t) censored = c*(-0.5*t) return uncensored + censored
def logpdf_sampling(self, F, y, Y_metadata=None): eF = safe_exp(F) a = eF[:,0,:] b = eF[:,1,:] a = np.clip(a, 1e-9, 1e9) # numerical stability b = np.clip(b, 1e-9, 1e9) # numerical stability ym = np.tile(y, (1, F.shape[2])) logpdf = - gammaln(a) + (a*np.log(b)) + ((a-1)*np.log(ym)) - (b*ym) return logpdf
def F_d2quad_df2_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] l_y = np.log(y) x = safe_exp(e_g * (l_y - f)) e2g = np.exp(2 * np.log(e_g)) t = e2g / (x + 1) - e2g / (x + 1)**2 uncensored = (1 - c) * (-t) censored = c * (-0.5 * t) return uncensored + censored
def d2logp_df2(self, F, y, Y_metadata=None): ef0 = safe_exp(F[:, 0, None]) phi = ef0 / (1 + ef0) phi = np.clip(phi, 1.0e-15, 1.0) # numerical stability lamb_poisson = safe_exp(F[:, 1, None]) lamb_poisson = np.clip(lamb_poisson, 0.0, 1.797e308) # numerical stability dphi_df0 = phi * (1 - phi) d2logp_f0 = -2 * phi**4 + 3 * phi**3 - 2 * phi**2 d2logp_f1 = -lamb_poisson #print('hola mundo') lim_max = 1.797e308 whichzeros = (y == 0) exp_neg_lamb = safe_exp(-lamb_poisson[whichzeros]) d2logp_f0[whichzeros] = (dphi_df0[whichzeros]**2) * ( (1 - exp_neg_lamb) * (1 - 2 * phi[whichzeros]) * (phi[whichzeros] + exp_neg_lamb * (1 - phi[whichzeros])) - (1 - exp_neg_lamb)**2) / ((phi[whichzeros] + exp_neg_lamb * (1 - phi[whichzeros]))**2) exp_1_phi = exp_neg_lamb * (1 - phi[whichzeros]) d2logp_f1[whichzeros] = d2logp_f1[whichzeros] + ( (phi[whichzeros] * lamb_poisson[whichzeros]) * (phi[whichzeros] + exp_1_phi) + (phi[whichzeros] * lamb_poisson[whichzeros]**2) * exp_1_phi) / ( (phi[whichzeros] + exp_1_phi)**2) if np.isnan(d2logp_f0).sum() > 0 or np.isnan(d2logp_f1).sum() > 0: print('nan') if np.isinf(d2logp_f0).sum() > 0: print('inf sec derivative f0') whichinf = np.isinf(d2logp_f0) getsign = np.sign(d2logp_f0[whichinf]) d2logp_f0[whichinf] = lim_max d2logp_f0[whichinf] = d2logp_f0[whichinf] * getsign if np.isinf(d2logp_f1).sum() > 0: print('inf Sec derivative f1') whichinf = np.isinf(d2logp_f1) getsign = np.sign(d2logp_f1[whichinf]) d2logp_f1[whichinf] = lim_max d2logp_f1[whichinf] = d2logp_f1[whichinf] * getsign return d2logp_f0, d2logp_f1
def F_dquad_dg_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] l_y = np.log(y) x = safe_exp(e_g * (l_y - f)) denom = x + 1 a = e_g * (l_y - f) t = a - a / denom uncensored = (1 - c) * (-2 * t) censored = c * (-t) return uncensored + censored
def F_dquad_dg_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] l_y = np.log(y) x = safe_exp(e_g*(l_y - f)) denom = x + 1 a = e_g*(l_y - f) t = a - a/denom uncensored = (1-c)*(-2*t) censored = c*(-t) return uncensored + censored
def logpdf(self, F, y, Y_metadata=None): Y_oneK = self.onehot(y) eF = safe_exp(F) den = 1 + eF.sum(1)[:, None] p = eF / np.tile(den, eF.shape[1]) p = np.hstack((p, 1 / den)) p = np.clip(p, 1e-9, 1- 1e-9) p = p / np.tile(p.sum(1)[:,None], (1, p.shape[1])) logpdf = multinomial.logpmf(x=Y_oneK, n=1, p=p) return logpdf
def logpdf(self, f, y, Y_metadata=None): """ Log Likelihood Function given f .. math:: \\ln p(y_{i}|f_{i}, g_{i}) = -(\\lambda(f_{i}) + \\lambda(g_{i}))\\ + y_{i}\\log (\\lambda(f_{i}) + \\lambda(g_{i})) - \\log y_{i}! :param link_f: latent variables (link(f)) :type link_f: Nx1 array :param y: data :type y: Nx1 array :param Y_metadata: Y_metadata which is not used in poisson distribution :returns: likelihood evaluated for this point :rtype: float """ D = y.shape[1] fv, gv = f[:, :D], f[:, D:] link_f = safe_exp(fv) link_g = safe_exp(gv) return -(link_f + link_g) + y*np.logaddexp(fv, gv) - sp.special.gammaln(y+1)
def variational_expectations(self, Y, m, v, gh_points=None, Y_metadata=None): D = Y.shape[1] mf, mg = m[:, :D], m[:, D:] vf, vg = v[:, :D], v[:, D:] from GPy.util.misc import safe_exp, safe_square lnY = np.log(Y) neglnY = np.log(1.0-Y) F = (safe_exp(mf + .5*vf) - 1)*lnY + (safe_exp(mg + .5*vg) - 1)*neglnY ##Some little code to check the result numerically using quadrature #from scipy import integrate #i = 6 # datapoint index #def quad_func(fi, gi, yi, mgi, vgi, mfi, vfi): #return ((-gammaln(np.exp(fi)) - gammaln(np.exp(gi)) + gammaln(np.exp(fi) + np.exp(gi))) #p(y|f,g) #* np.exp(-0.5*np.log(2*np.pi*vgi) - 0.5*((gi - mgi)**2)/vgi) #q(g) #* np.exp(-0.5*np.log(2*np.pi*vfi) - 0.5*((fi - mfi)**2)/vfi) #q(f) #) #quad_func_l = partial(quad_func, yi=Y[i], mgi=mg[i], vgi=vg[i], mfi=mf[i], vfi=vf[i]) #def integrl(gi): #return integrate.quad(quad_func_l, -50, 50, args=(gi))[0] #print "Numeric scipy F quad" #print integrate.quad(lambda fi: integrl(fi), -50, 50) def F_quad_func(e_f, e_g, y): return -gammaln(e_f) - gammaln(e_g) + gammaln(e_f + e_g) def F_dquad_df_func(e_f, e_g, y): #return -polygamma(0, e_f)*e_f + polygamma(0, e_f + e_g)*e_f return -psi(e_f)*e_f + psi(e_f + e_g)*e_f def F_d2quad_df2_func(e_f, e_g, y): e_2f = safe_square(e_f) #return 0.5*(-polygamma(1, e_f)*e_2f - polygamma(0, e_f)*e_f #+polygamma(1, e_f + e_g)*e_2f + polygamma(0, e_f + e_g)*e_f) return 0.5*(-zeta(2, e_f)*e_2f - psi(e_f)*e_f +zeta(2, e_f + e_g)*e_2f + psi(e_f + e_g)*e_f) def F_d2quad_df2_func_approx(e_f, e_g, y): e_2f = safe_square(e_f) #return 0.5*(-polygamma(1, e_f)*e_2f - polygamma(0, e_f)*e_f #+polygamma(1, e_f + e_g)*e_2f + polygamma(0, e_f + e_g)*e_f) #return 0.5*(-zeta(2, e_f)*e_2f - psi(e_f)*e_f #+zeta(2, e_f + e_g)*e_2f + psi(e_f + e_g)*e_f) return 0.5*(-approx_2zeta(e_f)*e_2f - psi(e_f)*e_f +approx_2zeta(e_f + e_g)*e_2f + psi(e_f + e_g)*e_f) def F_d2quad_df2_func_approx_sum(e_f, e_g, y): e_2f = safe_square(e_f) return 0.5*(-approx_2zeta_sum(e_f)*e_2f - psi(e_f)*e_f +approx_2zeta_sum(e_f + e_g)*e_2f + psi(e_f + e_g)*e_f) def F_dquad_dg_func(e_f, e_g, y): #return -polygamma(0, e_g)*e_g + polygamma(0, e_f + e_g)*e_g return -psi(e_g)*e_g + psi(e_f + e_g)*e_g def F_d2quad_dg2_func(e_f, e_g, y): e_2g = safe_square(e_g) #return 0.5*(-polygamma(1, e_g)*e_2g - polygamma(0, e_g)*e_g #+polygamma(1, e_f + e_g)*e_2g + polygamma(0, e_f + e_g)*e_g) return 0.5*(-zeta(2, e_g)*e_2g - psi(e_g)*e_g +zeta(2, e_f + e_g)*e_2g + psi(e_f + e_g)*e_g) def F_d2quad_dg2_func_approx(e_f, e_g, y): e_2g = safe_square(e_g) return 0.5*(-approx_2zeta(e_g)*e_2g - psi(e_g)*e_g +approx_2zeta(e_f + e_g)*e_2g + psi(e_f + e_g)*e_g) def F_d2quad_dg2_func_approx_sum(e_f, e_g, y): e_2g = safe_square(e_g) return 0.5*(-approx_2zeta_sum(e_g)*e_2g - psi(e_g)*e_g +approx_2zeta_sum(e_f + e_g)*e_2g + psi(e_f + e_g)*e_g) #(F_quad, dF_dmf, dF_dvf, #dF_dmg, dF_dvg) = self.quad2d([F_quad_func, F_dquad_df_func, #F_d2quad_df2_func, F_dquad_dg_func, #F_d2quad_dg2_func], #Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True) F_quad = self.quad2d([F_quad_func], Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True)[0] dF_dmf = self.quad2d([F_dquad_df_func], Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True)[0] #dF_dvf = self.quad2d([F_d2quad_df2_func], Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True)[0] dF_dmg = self.quad2d([F_dquad_dg_func], Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True)[0] #dF_dvg = self.quad2d([F_d2quad_dg2_func], Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True)[0] #dF_dvf_approx = self.quad2d([F_d2quad_df2_func_approx], Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True)[0] #dF_dvg_approx = self.quad2d([F_d2quad_dg2_func_approx], Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True)[0] dF_dvg = self.quad2d([F_d2quad_dg2_func_approx_sum], Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True)[0] dF_dvf = self.quad2d([F_d2quad_df2_func_approx_sum], Y, mf, vf, mg, vg, gh_points, exp_f=True, exp_g=True)[0] #print "f" #print np.min(dF_dvf) #print np.max(dF_dvf) #print np.max(dF_dvf - dF_dvf_approx_sum) #print np.min(dF_dvf - dF_dvf_approx_sum) #print "g" #print np.min(dF_dvg) #print np.max(dF_dvg) #print np.max(dF_dvg - dF_dvg_approx_sum) #print np.min(dF_dvg - dF_dvg_approx_sum) F += F_quad dF_dmf += safe_exp(mf + .5*vf)*lnY dF_dmg += safe_exp(mg + .5*vg)*neglnY dF_dvf += 0.5*safe_exp(mf + .5*vf)*lnY dF_dvg += 0.5*safe_exp(mg + .5*vg)*neglnY dF_dm = np.hstack((dF_dmf, dF_dmg)) dF_dv = np.hstack((dF_dvf, dF_dvg)) ##CYTHON ##Do some testing to see if the quadrature works well for one datapoint #Ngh = 20 #if gh_points is None: #gh_x, gh_w = self._gh_points(T=Ngh) #else: #gh_x, gh_w = gh_points #F_quad_cython = np.zeros(Y.shape) #dF_dmg_cython = np.zeros(mg.shape) #dF_dmf_cython = np.zeros(mf.shape) #dF_dvf_cython = np.zeros(vf.shape) #dF_dvg_cython = np.zeros(vg.shape) #dF_ddf_cython = np.zeros(vg.shape) #quad_cython.quad2d_beta(mf, vf, mg, vg, Y, gh_x, gh_w, F_quad_cython, #dF_dmf_cython, dF_dvf_cython, dF_dmg_cython, #dF_dvg_cython) #F_quad_cython /= np.pi #dF_dmg_cython /= np.pi #dF_dmf_cython /= np.pi #dF_dvf_cython /= np.pi #dF_dvg_cython /= np.pi #dF_ddf_cython /= np.pi return F, dF_dm, dF_dv, None
def pdf(self, f, g, y, Y_metadata=None): return safe_exp(self.logpdf(f,y,Y_metadata=Y_metadata))
def variational_expectations_pure(self, Y, m, v, gh_points=None, Y_metadata=None): D = Y.shape[1] mf, mg = m[:, :D], m[:, D:] vf, vg = v[:, :D], v[:, D:] from GPy.util.misc import safe_exp, safe_square c = Y_metadata['censored'] #ef = safe_exp(f) #eg = safe_exp(g) emg_vg2 = safe_exp(mg - 0.5*vg) uncensored = (1-c)*(mg + (emg_vg2 - 1)*np.log(Y) - mf*emg_vg2) censored = (c)*(0) F = 0 # uncensored + censored T = 20 #Need to get these now to duplicate the censored inputs for quadrature gh_x, gh_w = self._gh_points(T) Y_metadata_new = Y_metadata.copy() Y_metadata_new['censored'] = np.repeat(Y_metadata_new['censored'], gh_x.shape[0]**2, axis=0) ##Some little code to check the result numerically using quadrature #from scipy import integrate #i = 6 # datapoint index #def quad_func(fi, gi, yi, mgi, vgi, mfi, vfi,ci): ##x = safe_exp(-fi*safe_exp(gi))*yi**safe_exp(gi) #x = safe_exp(-fi*safe_exp(gi) + safe_exp(gi)*np.log(yi)) #log1px = np.log1p(x) ##return ((*-gammaln(np.exp(fi)) - gammaln(np.exp(gi)) + gammaln(np.exp(fi) + np.exp(gi))) #p(y|f,g) #return (((1-ci)*(-2*log1px) + ci*(-log1px)) #p(y|f,g) #* np.exp(-0.5*np.log(2*np.pi*vgi) - 0.5*((gi - mgi)**2)/vgi) #q(g) #* np.exp(-0.5*np.log(2*np.pi*vfi) - 0.5*((fi - mfi)**2)/vfi) #q(f) #) #quad_func_l = partial(quad_func, yi=Y[i], mgi=mg[i], vgi=vg[i], mfi=mf[i], vfi=vf[i], ci=Y_metadata['censored'][i]) #def integrl(gi): #return integrate.quad(quad_func_l, -30, 5, args=(gi))[0] #print "Numeric scipy F quad" #print integrate.quad(lambda fi: integrl(fi), -30, 5) def F_quad_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] x = safe_exp(-f*e_g + e_g*np.log(y)) log1px = np.log1p(x) uncensored = (1-c)*(-2*log1px) censored = c*(-log1px) return uncensored + censored def F_dquad_df_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] x = e_g*(1./(safe_exp(e_g*(-f + np.log(y))) + 1) - 1) uncensored = (1-c)*(-2*x) censored = c*(-x) return uncensored + censored def F_d2quad_df2_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] l_y = np.log(y) x = safe_exp(e_g*(l_y - f)) e2g = np.exp(2*np.log(e_g)) t = e2g/(x+1) - e2g/(x+1)**2 uncensored = (1-c)*(-t) censored = c*(-0.5*t) return uncensored + censored def F_dquad_dg_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] l_y = np.log(y) x = safe_exp(e_g*(l_y - f)) denom = x + 1 a = e_g*(l_y - f) t = a - a/denom uncensored = (1-c)*(-2*t) censored = c*(-t) return uncensored + censored def F_d2quad_dg2_func(f, e_g, y, Y_metadata): return np.zeros_like(y) # ? (F_quad, dF_dmf, dF_dvf, dF_dmg, dF_dvg) = self.quad2d([F_quad_func, F_dquad_df_func, F_d2quad_df2_func, F_dquad_dg_func, F_d2quad_dg2_func], Y, mf, vf, mg, vg, gh_points, exp_f=False, exp_g=True, Y_metadata=Y_metadata_new) #F_quad = self.quad2d([F_quad_func], Y, mf, vf, mg, vg, gh_points, exp_f=False, exp_g=True)[0] #dF_dmf = self.quad2d([F_dquad_df_func], Y, mf, vf, mg, vg, gh_points, exp_f=False, exp_g=True)[0] #dF_dvf = self.quad2d([F_d2quad_df2_func], Y, mf, vf, mg, vg, gh_points, exp_f=False, exp_g=True)[0] #dF_dmg = self.quad2d([F_dquad_dg_func], Y, mf, vf, mg, vg, gh_points, exp_f=False, exp_g=True)[0] #dF_dvg = self.quad2d([F_d2quad_dg2_func], Y, mf, vf, mg, vg, gh_points, exp_f=False, exp_g=True)[0] #print "2d quad F quad" #print F_quad[i] F += F_quad gprec = safe_exp(mg - 0.5*vg) dF_dmf += 0 #(1-c)*(-gprec) dF_dmg += 0 #(1-c)*(1 + gprec*(np.log(Y) - mf)) dF_dvf += 0 dF_dvg += 0 # ? dF_dm = np.hstack((dF_dmf, dF_dmg)) dF_dv = np.hstack((dF_dvf, dF_dvg)) ##CYTHON ##Do some testing to see if the quadrature works well for one datapoint #Ngh = 20 #if gh_points is None: #gh_x, gh_w = self._gh_points(T=Ngh) #else: #gh_x, gh_w = gh_points #F_quad_cython = np.zeros(Y.shape) #dF_dmg_cython = np.zeros(mg.shape) #dF_dmf_cython = np.zeros(mf.shape) #dF_dvf_cython = np.zeros(vf.shape) #dF_dvg_cython = np.zeros(vg.shape) #dF_ddf_cython = np.zeros(vg.shape) #quad_cython.quad2d_loglogistic(mf, vf, mg, vg, Y, gh_x, gh_w, F_quad_cython, #dF_dmf_cython, dF_dvf_cython, dF_dmg_cython, #dF_dvg_cython) #F_quad_cython /= np.pi #dF_dmg_cython /= np.pi #dF_dmf_cython /= np.pi #dF_dvf_cython /= np.pi #dF_dvg_cython /= np.pi #dF_ddf_cython /= np.pi return F, dF_dm, dF_dv, None
def F_dquad_df_func(f, e_g, y, Y_metadata): c = Y_metadata['censored'] x = e_g*(1./(safe_exp(e_g*(-f + np.log(y))) + 1) - 1) uncensored = (1-c)*(-2*x) censored = c*(-x) return uncensored + censored