def inference_minibatch(self, kern, X, Z, likelihood, Y):
num_data, output_dim = Y.shape<EOL>if isinstance(X, VariationalPosterior):<EOL><INDENT>uncertain_inputs = True<EOL><DEDENT>else:<EOL><INDENT>uncertain_inputs = False<EOL><DEDENT>beta = <NUM_LIT:1.>/np.fmax(likelihood.variance, <NUM_LIT>)<EOL>het_noise = beta.size > <NUM_LIT:1><EOL>if self.Y_speedup and not het_noise:<EOL><INDENT>YYT_factor = self.get_YYTfactor(Y)<EOL><DEDENT>else:<EOL><INDENT>YYT_factor = Y<EOL><DEDENT>n_start = self.batch_pos<EOL>batchsize = num_data if self.batchsize is None else self.batchsize<EOL>n_end = min(batchsize+n_start, num_data)<EOL>if n_end==num_data:<EOL><INDENT>isEnd = True<EOL>self.batch_pos = <NUM_LIT:0><EOL><DEDENT>else:<EOL><INDENT>isEnd = False<EOL>self.batch_pos = n_end<EOL><DEDENT>if batchsize==num_data:<EOL><INDENT>Y_slice = YYT_factor<EOL>X_slice =X<EOL><DEDENT>else:<EOL><INDENT>Y_slice = YYT_factor[n_start:n_end]<EOL>X_slice = X[n_start:n_end]<EOL><DEDENT>if not uncertain_inputs:<EOL><INDENT>psi0 = kern.Kdiag(X_slice)<EOL>psi1 = kern.K(X_slice, Z)<EOL>psi2 = None<EOL>betapsi1 = np.einsum('<STR_LIT>',beta,psi1)<EOL><DEDENT>elif het_noise:<EOL><INDENT>psi0 = kern.psi0(Z, X_slice)<EOL>psi1 = kern.psi1(Z, X_slice)<EOL>psi2 = kern.psi2(Z, X_slice)<EOL>betapsi1 = np.einsum('<STR_LIT>',beta,psi1)<EOL><DEDENT>if het_noise:<EOL><INDENT>beta = beta[n_start] <EOL><DEDENT>betaY = beta*Y_slice<EOL>dL_dpsi2R = self.midRes['<STR_LIT>']<EOL>v = self.midRes['<STR_LIT:v>']<EOL>dL_dpsi0 = -output_dim * (beta * np.ones((n_end-n_start,)))/<NUM_LIT><EOL>dL_dpsi1 = np.dot(betaY,v.T)<EOL>if uncertain_inputs:<EOL><INDENT>dL_dpsi2 = beta* dL_dpsi2R<EOL><DEDENT>else:<EOL><INDENT>dL_dpsi1 += np.dot(betapsi1,dL_dpsi2R)*<NUM_LIT><EOL>dL_dpsi2 = None<EOL><DEDENT>if het_noise:<EOL><INDENT>if uncertain_inputs:<EOL><INDENT>psiR = np.einsum('<STR_LIT>',dL_dpsi2R,psi2)<EOL><DEDENT>else:<EOL><INDENT>psiR = np.einsum('<STR_LIT>',psi1,psi1,dL_dpsi2R)<EOL><DEDENT>dL_dthetaL = ((np.square(betaY)).sum(axis=-<NUM_LIT:1>) + np.square(beta)*(output_dim*psi0)-output_dim*beta)/<NUM_LIT> - np.square(beta)*psiR- (betaY*np.dot(betapsi1,v)).sum(axis=-<NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>if isEnd:<EOL><INDENT>dL_dthetaL = self.midRes['<STR_LIT>']<EOL><DEDENT>else:<EOL><INDENT>dL_dthetaL = <NUM_LIT:0.><EOL><DEDENT><DEDENT>if uncertain_inputs:<EOL><INDENT>grad_dict = {'<STR_LIT>':dL_dpsi0,<EOL>'<STR_LIT>':dL_dpsi1,<EOL>'<STR_LIT>':dL_dpsi2,<EOL>'<STR_LIT>':dL_dthetaL}<EOL><DEDENT>else:<EOL><INDENT>grad_dict = {'<STR_LIT>':dL_dpsi0,<EOL>'<STR_LIT>':dL_dpsi1,<EOL>'<STR_LIT>':dL_dthetaL}<EOL><DEDENT>return isEnd, (n_start,n_end), grad_dict<EOL>
The second phase of inference: Computing the derivatives over a minibatch of Y
Compute: dL_dpsi0, dL_dpsi1, dL_dpsi2, dL_dthetaL
return a flag showing whether it reached the end of Y (isEnd)