Changeset 2854 for trunk/GSASIImath.py
- Timestamp:
- Jun 3, 2017 12:23:04 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/GSASIImath.py
r2853 r2854 146 146 * 'lamMax': 147 147 * 'psing': 148 * 'SVD0': 148 149 149 150 """ … … 162 163 nfev = 0 163 164 if Print: 164 print ' Hessian SVD refinement on %d variables:'%(n)165 print ' Hessian Levenburg-Marquardt SVD refinement on %d variables:'%(n) 165 166 Lam = np.zeros((n,n)) 166 167 while icycle < maxcyc: … … 170 171 chisq0 = np.sum(M**2) 171 172 Yvec,Amat = Hess(x0,*args) 172 # print 'unscaled SVD zeros',pinv(Amat)[1]173 173 Adiag = np.sqrt(np.diag(Amat)) 174 174 psing = np.where(np.abs(Adiag) < 1.e-14,True,False) 175 175 if np.any(psing): #hard singularity in matrix 176 return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing }]176 return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing,'SVD0':-1}] 177 177 Anorm = np.outer(Adiag,Adiag) 178 178 Yvec /= Adiag … … 185 185 try: 186 186 Ainv,Nzeros = pinv(Amatlam,xtol) #do Moore-Penrose inversion (via SVD) 187 # Ainv = nl.inv(Amatlam); Nzeros = 0188 187 except nl.LinAlgError: 189 188 print 'ouch #1 bad SVD inversion; change parameterization' 190 189 psing = list(np.where(np.diag(nl.qr(Amatlam)[1]) < 1.e-14)[0]) 191 return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing }]190 return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing,'SVD0':-1}] 192 191 Xvec = np.inner(Ainv,Yvec) #solve 193 192 Xvec /= Adiag … … 228 227 # Bmat = nl.inv(Amatlam); Nzeros = 0 229 228 Bmat = Bmat/Anorm 230 return [x0,Bmat,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':[], 229 return [x0,Bmat,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':[],'SVD0':Nzero,'Converged': ifConverged, 'DelChi2':deltaChi2}] 231 230 except nl.LinAlgError: 232 231 print 'ouch #2 linear algebra error in making v-cov matrix' … … 234 233 if maxcyc: 235 234 psing = list(np.where(np.diag(nl.qr(Amat)[1]) < 1.e-14)[0]) 236 return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing}] 235 return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing,'SVD0':-1}] 236 237 def HessianSVD(func,x0,Hess,args=(),ftol=1.49012e-8,xtol=1.e-6, maxcyc=0,lamda=-3,Print=False): 238 239 """ 240 Minimize the sum of squares of a function (:math:`f`) evaluated on a series of 241 values (y): :math:`\sum_{y=0}^{N_{obs}} f(y,{args})` 242 where :math:`x = arg min(\sum_{y=0}^{N_{obs}} (func(y)^2,axis=0))` 243 244 :param function func: callable method or function 245 should take at least one (possibly length N vector) argument and 246 returns M floating point numbers. 247 :param np.ndarray x0: The starting estimate for the minimization of length N 248 :param function Hess: callable method or function 249 A required function or method to compute the weighted vector and Hessian for func. 250 It must be a symmetric NxN array 251 :param tuple args: Any extra arguments to func are placed in this tuple. 252 :param float ftol: Relative error desired in the sum of squares. 253 :param float xtol: Relative tolerance of zeros in the SVD solution in nl.pinv. 254 :param int maxcyc: The maximum number of cycles of refinement to execute, if -1 refine 255 until other limits are met (ftol, xtol) 256 :param bool Print: True for printing results (residuals & times) by cycle 257 258 :returns: (x,cov_x,infodict) where 259 260 * x : ndarray 261 The solution (or the result of the last iteration for an unsuccessful 262 call). 263 * cov_x : ndarray 264 Uses the fjac and ipvt optional outputs to construct an 265 estimate of the jacobian around the solution. ``None`` if a 266 singular matrix encountered (indicates very flat curvature in 267 some direction). This matrix must be multiplied by the 268 residual standard deviation to get the covariance of the 269 parameter estimates -- see curve_fit. 270 * infodict : dict 271 a dictionary of optional outputs with the keys: 272 273 * 'fvec' : the function evaluated at the output 274 * 'num cyc': 275 * 'nfev': 276 * 'lamMax':0. 277 * 'psing': 278 * 'SVD0': 279 280 """ 281 282 ifConverged = False 283 deltaChi2 = -10. 284 x0 = np.array(x0, ndmin=1) #might be redundant? 285 n = len(x0) 286 if type(args) != type(()): 287 args = (args,) 288 289 icycle = 0 290 nfev = 0 291 if Print: 292 print ' Hessian SVD refinement on %d variables:'%(n) 293 while icycle < maxcyc: 294 time0 = time.time() 295 M = func(x0,*args) 296 nfev += 1 297 chisq0 = np.sum(M**2) 298 Yvec,Amat = Hess(x0,*args) 299 Adiag = np.sqrt(np.diag(Amat)) 300 psing = np.where(np.abs(Adiag) < 1.e-14,True,False) 301 if np.any(psing): #hard singularity in matrix 302 return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':0.,'psing':psing,'SVD0':-1}] 303 Anorm = np.outer(Adiag,Adiag) 304 Yvec /= Adiag 305 Amat /= Anorm 306 if Print: 307 print 'initial chi^2 %.5g'%(chisq0) 308 try: 309 Ainv,Nzeros = pinv(Amat,xtol) #do Moore-Penrose inversion (via SVD) 310 except nl.LinAlgError: 311 print 'ouch #1 bad SVD inversion; change parameterization' 312 psing = list(np.where(np.diag(nl.qr(Amat)[1]) < 1.e-14)[0]) 313 return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':0.,'psing':psing,'SVD0':-1}] 314 Xvec = np.inner(Ainv,Yvec) #solve 315 Xvec /= Adiag 316 M2 = func(x0+Xvec,*args) 317 nfev += 1 318 chisq1 = np.sum(M2**2) 319 deltaChi2 = (chisq0-chisq1)/chisq0 320 if Print: 321 print ' Cycle: %d, Time: %.2fs, Chi**2: %.5g, Delta: %.3g'%( 322 icycle,time.time()-time0,chisq1,deltaChi2) 323 if deltaChi2 < ftol: 324 ifConverged = True 325 if Print: print "converged" 326 break 327 icycle += 1 328 M = func(x0,*args) 329 nfev += 1 330 Yvec,Amat = Hess(x0,*args) 331 Adiag = np.sqrt(np.diag(Amat)) 332 Anorm = np.outer(Adiag,Adiag) 333 Amat = Amat/Anorm 334 try: 335 Bmat,Nzero = pinv(Amat,xtol) #Moore-Penrose inversion (via SVD) & count of zeros 336 print 'Found %d SVD zeros'%(Nzero) 337 # Bmat = nl.inv(Amatlam); Nzeros = 0 338 Bmat = Bmat/Anorm 339 return [x0,Bmat,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':0.,'psing':[], 340 'SVD0':Nzero,'Converged': ifConverged, 'DelChi2':deltaChi2}] 341 except nl.LinAlgError: 342 print 'ouch #2 linear algebra error in making v-cov matrix' 343 psing = [] 344 if maxcyc: 345 psing = list(np.where(np.diag(nl.qr(Amat)[1]) < 1.e-14)[0]) 346 return [x0,None,{'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':0.,'psing':psing,'SVD0':-1}] 237 347 238 348 def getVCov(varyNames,varyList,covMatrix):
Note: See TracChangeset
for help on using the changeset viewer.