def FDCheckH(self): """ Finite-difference checker for the objective function Hessian. For each element in the Hessian, use a five-point stencil in both parameter indices to compute a finite-difference derivative, and compare it to the analytic result. This is meant to be a foolproof checker, so it is pretty slow. We could write a faster checker if we assumed we had accurate first derivatives, but it's better to not make that assumption. The second derivative is computed by double-wrapping the objective function via the 'wrap2' function. """ Adata = self.Objective.Full(self.mvals0,Order=2)['H'] Fdata = np.zeros((self.FF.np,self.FF.np),dtype=float) printcool("Checking second derivatives by finite difference!\n%-8s%-20s%-20s%13s%13s%13s%13s" \ % ("Index", "Parameter1 ID", "Parameter2 ID", "Analytic","Numerical","Difference","Fractional"),bold=1,color=5) # Whee, our double-wrapped finite difference second derivative! def wrap2(mvals0,pidxi,pidxj): def func1(arg): mvals = list(mvals0) mvals[pidxj] += arg return f1d5p(fdwrap(self.Objective.Full,mvals,pidxi,'X',Order=0),self.h) return func1 for i in range(self.FF.np): for j in range(i,self.FF.np): Fdata[i,j] = f1d5p(wrap2(self.mvals0,i,j),self.h) Denom = max(abs(Adata[i,j]),abs(Fdata[i,j])) Denom = Denom > 1e-8 and Denom or 1e-8 D = Adata[i,j] - Fdata[i,j] Q = (Adata[i,j] - Fdata[i,j])/Denom cD = abs(D) > 0.5 and "\x1b[1;91m" or (abs(D) > 1e-2 and "\x1b[91m" or (abs(D) > 1e-5 and "\x1b[93m" or "\x1b[92m")) cQ = abs(Q) > 0.5 and "\x1b[1;91m" or (abs(Q) > 1e-2 and "\x1b[91m" or (abs(Q) > 1e-5 and "\x1b[93m" or "\x1b[92m")) print "\r %-8i%-20s%-20s% 13.4e% 13.4e%s% 13.4e%s% 13.4e\x1b[0m" \ % (i, self.FF.plist[i][:20], self.FF.plist[j][:20], Adata[i,j], Fdata[i,j], cD, D, cQ, Q)
def func1(arg): mvals = list(mvals0) mvals[pidxj] += arg return f1d5p(fdwrap(self.Objective.Full,mvals,pidxi,'X',Order=0),self.h)