- Timestamp:
- Dec 31, 2020 4:11:48 PM (2 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/GSASIIdataGUI.py
r4690 r4693 5180 5180 text += '\nMax shift/sigma={:.3f}\n'.format(Rvals['Max shft/sig']) 5181 5181 if 'msg' in Rvals: text += '\n' + Rvals['msg'] + '\n' 5182 text += '\nLoad new result?'5183 5182 if lamMax >= 10.: 5184 5183 text += '\nWARNING: Steepest descents dominates;'+ \ 5185 5184 ' minimum may not have been reached or result may be false minimum.'+ \ 5186 ' You should reconsider which parameters you refine' 5185 ' You should reconsider which parameters you refine. Check covariance matrix.\n' 5186 text += '\nLoad new result?' 5187 5187 dlg2 = wx.MessageDialog(self,text,'Refinement results, Rw =%.3f'%(Rw),wx.OK|wx.CANCEL) 5188 5188 dlg2.CenterOnParent() -
trunk/GSASIImath_new.py
r4690 r4693 106 106 return res,nzero 107 107 108 def dropTerms( hessian, xvector, yvector, indices, bad):108 def dropTerms(bad, hessian, indices, *vectors): 109 109 '''Remove the 'bad' terms from the Hessian and vector 110 110 111 :param tuple bad: a list of variable (row/column) numbers that should be 112 removed from the hessian and vector. Example: (0,3) removes the 1st and 113 4th column/row 111 114 :param np.array hessian: a square matrix of length n x n 112 :param np.array xvector: the least-squares model values, length n113 :param np.array yvector: the least-square vector of length n114 115 :param np.array indices: the indices of the least-squares vector of length n 115 116 referenced to the initial variable list; as this routine is called 116 117 multiple times, more terms may be removed from this list 117 :param tuple bad: a list of variable (row/column) numbers that should be 118 removed from the hessian and vector. Example: (0,3) removes the 1st and 119 4th column/row 120 :returns: hessian, xvector, yvector, indices where the lengths are 118 :param additional-args: various least-squares model values, length n 119 120 :returns: hessian, indices, vector0, vector1,... where the lengths are 121 121 now n' x n' and n', with n' = n - len(bad) 122 122 ''' 123 return (np.delete(np.delete(hessian,bad,1),bad,0), 124 np.delete(xvector,bad), 125 np.delete(yvector,bad), 126 np.delete(indices,bad)) 127 123 out = [np.delete(np.delete(hessian,bad,1),bad,0),np.delete(indices,bad)] 124 for v in vectors: 125 out.append(np.delete(v,bad)) 126 return out 127 128 129 128 130 def setHcorr(info,Amat,xtol,problem=False): 129 131 Adiag = np.sqrt(np.diag(Amat)) … … 141 143 m = max(0.95,0.99*np.amax(AcovUp)) 142 144 info['Hcorr'] = [(i,j,AcovUp[i,j]) for i,j in zip(*np.where(AcovUp > m))] 143 return Bmat 145 return Bmat,Nzeros 144 146 145 147 def HessianLSQ(func,x0,Hess,args=(),ftol=1.49012e-8,xtol=1.e-6, maxcyc=0,lamda=-3,Print=False,refPlotUpdate=None): … … 194 196 195 197 icycle = 0 196 lam = 0 # Could start w/o Marquardt and add it in if needed 197 lam = 10.**lamda 198 lamMax = lam 198 lamMax = lam = 0 # start w/o Marquardt and add it in if needed 199 199 nfev = 0 200 200 if Print: … … 215 215 if n == 0: 216 216 info = {'num cyc':0,'fvec':M2,'nfev':1,'lamMax':0,'psing':[],'SVD0':0} 217 info['msg'] = 'no variables , norefinement\n'217 info['msg'] = 'no variables: skipping refinement\n' 218 218 return [x0,None,info] 219 219 while icycle < maxcyc: … … 226 226 Xvec = copy.copy(XvecAll) 227 227 # we could remove vars that were dropped in previous cycles here (use indices), but for 228 # now let's reset them each cycle in case the singularities go awa t228 # now let's reset them each cycle in case the singularities go away 229 229 indices = range(n) 230 230 Adiag = np.sqrt(np.diag(Amat)) 231 psing = np.where(np.abs(Adiag) < 1.e-14)[0] # removeany hard singularities231 psing = np.where(np.abs(Adiag) < 1.e-14)[0] # find any hard singularities 232 232 if len(psing): 233 G2fil.G2Print('ouch #1 dropping singularities for variable(s) #{}'.format(psing), mode='warn') 234 Amat, Xvec, Yvec, indices = dropTerms(Amat, Xvec, Yvec, indices, psing) 235 Adiag = np.sqrt(np.diag(Amat)) 233 G2fil.G2Print('ouch #1 dropping singularities for variable(s) #{}'.format( 234 psing), mode='warn') 235 Amat, indices, Xvec, Yvec, Adiag = dropTerms(psing, 236 Amat, indices, Xvec, Yvec, Adiag) 236 237 Anorm = np.outer(Adiag,Adiag) # normalize matrix & vector 237 238 Yvec /= Adiag … … 240 241 maxdrop = 3 # max number of drop var attempts 241 242 loops = 0 242 while True: #---------------------- loop as we increase lamda and possibly drop terms from hessian, x & y vectors 243 while True: #--------- loop as we increase lamda and possibly drop terms 244 lamMax = max(lamMax,lam) 243 245 Amatlam = Amat*(1.+np.eye(Amat.shape[0])*lam) 244 246 try: 245 Ainv,Nzeros = pinv(Amatlam,xtol) # do Moore-Penrose inversion (via SVD)247 Ainv,Nzeros = pinv(Amatlam,xtol) # Moore-Penrose SVD inversion 246 248 except nl.LinAlgError: 247 249 loops += 1 … … 252 254 G2fil.G2Print('ouch #2 bad SVD inversion; dropping terms for for variable(s) #{}'. 253 255 format(psing), mode='warn') 254 Amatlam, Xvec, Yvec, indices = dropTerms(Amatlam, Xvec, Yvec, indices, psing) 255 if loops < maxdrop: continue 256 Amat, indices, Xvec, Yvec, Adiag = dropTerms(psing, 257 Amat, indices, Xvec, Yvec, Adiag) 258 if loops < maxdrop: continue # try again, same lam but fewer vars 256 259 G2fil.G2Print('giving up with ouch #2', mode='error') 257 info = {'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'psing':psing,'SVD0':Nzeros} 260 info = {'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'SVD0':Nzeros} 261 info['psing'] = [i for i in range(n) if i not in indices] 262 258 263 info['msg'] = 'SVD inversion failure\n' 259 264 return [x0,None,info] … … 265 270 G2fil.G2Print('{} SVD Zeros: dropping terms for for variable(s) #{}'. 266 271 format(Nzeros,psing), mode='warn') 267 Amat, Xvec, Yvec, indices = dropTerms(Amat, Xvec, Yvec, indices, psing) 272 Amat, indices, Xvec, Yvec, Adiag = dropTerms(psing, 273 Amat, indices, Xvec, Yvec, Adiag) 268 274 Amatlam = Amat*(1.+np.eye(Amat.shape[0])*lam) 269 Ainv,Nzeros = pinv(Amatlam,xtol) #do Moore-Penrose inversion (via SVD) 270 Adiag = np.sqrt(np.diag(Amat)) 275 Ainv,nz = pinv(Amatlam,xtol) #do Moore-Penrose inversion (via SVD) 276 if nz > 0: G2fil.G2Print('Note: there are {} new SVD Zeros after drop', 277 mode='warn') 271 278 Xvec = np.inner(Ainv,Yvec)/Adiag #solve for LS terms 272 279 XvecAll[indices] = Xvec # expand … … 275 282 except Exception as Msg: 276 283 if not hasattr(Msg,'msg'): Msg.msg = str(Msg) 284 G2fil.G2Print(Msg.msg,mode='warn') 277 285 loops += 1 278 286 d = np.abs(np.diag(nl.qr(Amatlam)[1])) 279 psing = list(np.where(d < 1.e-14)[0]) 280 if len(psing) < Nzeros: 281 psing = list(np.where(d <= sorted(d)[max(Nzeros,1)-1])[0]) 282 G2fil.G2Print(Msg.msg,mode='warn') 283 # dropping variables does not seem to help 284 if len(psing): 285 G2fil.G2Print('ouch #3 unable to evaluate objective function;'+ 286 '\n\tdropping terms for variable(s) #{}'.format(psing), 287 mode='warn') 288 Amatlam, Xvec, Yvec, indices = dropTerms(Amatlam, Xvec, Yvec, indices, psing) 289 if loops < maxdrop: continue 290 G2fil.G2Print('giving up with ouch #3', mode='error') 291 else: #nothing to improve 292 G2fil.G2Print('ouch #3 unable to evaluate objective function. Giving up', 293 mode='warn') 287 G2fil.G2Print('ouch #3 unable to evaluate objective function;', 288 mode='error') 294 289 info = {'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'SVD0':Nzeros} 295 290 info['psing'] = [i for i in range(n) if i not in indices] 296 try: # report highly correlated parameters from full Hessian, if we can291 try: # try to report highly correlated parameters from full Hessian 297 292 setHcorr(info,AmatAll,xtol,problem=True) 298 293 except nl.LinAlgError: … … 304 299 G2fil.G2Print('Error determining highly correlated vars',mode='warn') 305 300 G2fil.G2Print(Msg.msg,mode='warn') 306 info['msg'] = Msg.msg + '\n '301 info['msg'] = Msg.msg + '\n\n' 307 302 return [x0,None,info] 308 303 nfev += 1 309 304 chisq1 = np.sum(M2**2) 310 305 if chisq1 > chisq0*(1.+chitol): #TODO put Alan Coehlo's criteria for lambda here? 311 lam *= 10. 312 if lam == 0: lam = 10.**lamda # this is here if we start w/o Marquardt term 306 if lam == 0: 307 lam = 10.**lamda # set to initial Marquardt term 308 else: 309 lam *= 10. 313 310 if Print: 314 G2fil.G2Print(('divergence: chi^2 %.5g on %d obs. w/%d SVD zeros\n'+311 G2fil.G2Print(('divergence: chi^2 %.5g on %d obs. (%d SVD zeros)\n'+ 315 312 '\tincreasing Marquardt lambda to %.1e')%(chisq1,Nobs,Nzeros,lam)) 316 313 if lam > 10.: … … 318 315 (chisq1,chisq0,lam), mode='warn') 319 316 try: # report highly correlated parameters from full Hessian, if we can 320 info = {'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax, 'SVD0':Nzeros,317 info = {'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax, 321 318 'Converged':False, 'DelChi2':deltaChi2, 'Xvec':XvecAll, 'chisq0':chisq00} 322 319 info['psing'] = [i for i in range(n) if i not in indices] 323 Bmat = setHcorr(info,AmatAll,xtol,problem=True) 320 Bmat,Nzeros = setHcorr(info,AmatAll,xtol,problem=True) 321 info['SVD0'] = Nzeros 324 322 return [x0,Bmat,info] 325 323 except Exception as Msg: … … 335 333 break 336 334 # complete current cycle 337 lamMax = max(lamMax,lam)338 335 deltaChi2 = (chisq0-chisq1)/chisq0 339 336 if Print and n-len(indices): … … 366 363 chisqf = np.sum(M**2) # ending chi**2 367 364 Yvec,Amat = Hess(x0,*args) # we could save some time and use the last Hessian from the last refinement cycle 368 psing_prev = [i for i in range(n) if i not in indices] 365 psing_prev = [i for i in range(n) if i not in indices] # save dropped vars 369 366 indices = range(n) 370 367 info = {} 371 368 try: # report highly correlated parameters from full Hessian, if we can 372 Bmat = setHcorr(info,Amat,xtol,problem=False)369 Bmat,Nzeros = setHcorr(info,Amat,xtol,problem=False) 373 370 info.update({'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'SVD0':Nzeros,'psing':psing_prev, 374 371 'Converged':ifConverged, 'DelChi2':deltaChi2, 'Xvec':XvecAll, 'chisq0':chisq00}) … … 382 379 G2fil.G2Print('Error determining highly correlated vars',mode='warn') 383 380 G2fil.G2Print(Msg.msg,mode='warn') 384 # matrix above inversion failed, drop previously removed variables 385 dummy = np.zeros(n) 386 Amat, Xvec, Yvec, indices = dropTerms(Amat, dummy, Yvec, indices, psing_prev) 381 # matrix above inversion failed, drop previously removed variables & try again 382 Amat, indices, Yvec = dropTerms(psing_prev, Amat, indices, Yvec) 387 383 Adiag = np.sqrt(np.diag(Amat)) 388 384 Anorm = np.outer(Adiag,Adiag) … … 394 390 G2fil.G2Print('ouch #5 linear algebra error in making final v-cov matrix', mode='error') 395 391 psing = list(np.where(np.abs(np.diag(nl.qr(Amat)[1])) < 1.e-14)[0]) 396 if not len(psing): # make sure at least the worst is returned392 if not len(psing): # make sure at least the worst term is flagged 397 393 psing = [np.argmin(d)] 398 Amat, Xvec, Yvec, indices = dropTerms(Amat, Xvec, Yvec, indices, psing)394 Amat, indices, Yvec = dropTerms(psing, Amat, indices, Yvec) 399 395 info = {'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'SVD0':-1,'Xvec':None, 'chisq0':chisqf} 400 396 info['psing'] = [i for i in range(n) if i not in indices] 401 397 return [x0,None,info] 402 if Nzeros: # this is unexpected, since previous refinements should have removed the zeros398 if Nzeros: # sometimes SVD zeros show up when lam=0 403 399 d = np.abs(np.diag(nl.qr(Amat)[1])) 404 400 psing = list(np.where(d < 1.e-14)[0]) … … 406 402 psing = list(np.where(d <= sorted(d)[Nzeros-1])[0]) 407 403 if Print: 408 G2fil.G2Print('Found %d SVD zeros w/o Lambda. Change problem with variable(s) #%s'% 404 G2fil.G2Print('Found %d SVD zeros w/o Lambda. '+ 405 'Likely problem with variable(s) #%s'% 409 406 (Nzeros,psing), mode='warn') 410 Amat, Xvec, Yvec, indices = dropTerms(Amat, Xvec, Yvec, indices, psing) 411 # expand Bmat by filling with zeros 407 Amat, indices, Yvec = dropTerms(psing, Amat, indices, Yvec) 408 # expand Bmat by filling with zeros if columns have been dropped 409 psing = [i for i in range(n) if i not in indices] 412 410 if len(psing): 413 Bmat = np.insert(np.insert(Bmat,psing,0,1),psing,0,0) 411 ins = [j-i for i,j in enumerate(psing)] 412 Bmat = np.insert(np.insert(Bmat,ins,0,1),ins,0,0) 414 413 info.update({'num cyc':icycle,'fvec':M,'nfev':nfev,'lamMax':lamMax,'SVD0':Nzeros, 415 414 'Converged':ifConverged, 'DelChi2':deltaChi2, 'Xvec':XvecAll, 'chisq0':chisq00}) -
trunk/GSASIIstrMain.py
r4691 r4693 60 60 if len(psing): 61 61 if msg: msg += '\n' 62 msg += 'Parameters dropped due to singularities:' 63 for i,val in enumerate(psing): 64 if i == 0: 65 msg += '\n\t{}'.format(varyList[val]) 66 else: 67 msg += ', {}'.format(varyList[val]) 62 msg += '{} Parameters dropped due to singularities:'.format(len(psing)) 63 for i,val in enumerate(psing): 64 if i == 0: 65 msg += '\n\t{}'.format(varyList[val]) 66 else: 67 msg += ', {}'.format(varyList[val]) 68 G2fil.G2Print(msg, mode='warn') 68 69 #report on highly correlated variables 69 70 Hcorr = result[2].get('Hcorr',[]) 70 for i,(v1,v2,corr) in enumerate(Hcorr):71 if len(Hcorr) > 0: 71 72 if msg: msg += '\n' 72 if i == 0: 73 msg += 'Note highly correlated parameters:\n' 73 msg += 'Note highly correlated parameters:' 74 elif SVD0 > 0: 75 if msg: msg += '\n' 76 msg += 'Check covariance matrix for parameter correlation' 77 for v1,v2,corr in Hcorr: 74 78 if corr > .95: 75 79 stars = '**' 76 80 else: 77 81 stars = ' ' 78 msg += ' {} {} and {} (@{:.2f}%)'.format(82 msg += '\n {} {} and {} (@{:.2f}%)'.format( 79 83 stars,varyList[v1],varyList[v2],100.*corr) 80 84 if msg:
Note: See TracChangeset
for help on using the changeset viewer.