mirror of
https://github.com/wassname/simpeg.git
synced 2026-06-27 23:23:37 +08:00
161 lines
4.7 KiB
Python
161 lines
4.7 KiB
Python
import Utils, numpy as np
|
|
|
|
class InversionDirective(object):
|
|
"""InversionDirective"""
|
|
|
|
debug = False #: Print debugging information
|
|
|
|
current = None #: This hold
|
|
|
|
def __init__(self, **kwargs):
|
|
Utils.setKwargs(self, **kwargs)
|
|
|
|
@property
|
|
def inversion(self):
|
|
"""This is the inversion of the InversionDirective instance."""
|
|
return getattr(self,'_inversion',None)
|
|
@inversion.setter
|
|
def inversion(self, i):
|
|
if getattr(self,'_inversion',None) is not None:
|
|
print 'Warning: InversionDirective %s has switched to a new inversion.' % self.__name__
|
|
self._inversion = i
|
|
|
|
@property
|
|
def invProb(self): return self.inversion.invProb
|
|
@property
|
|
def opt(self): return self.inversion.opt
|
|
@property
|
|
def reg(self): return self.invProb.reg
|
|
@property
|
|
def dmisfit(self): return self.invProb.dmisfit
|
|
@property
|
|
def survey(self): return self.invProb.survey
|
|
@property
|
|
def prob(self): return self.invProb.prob
|
|
|
|
def initialize(self):
|
|
pass
|
|
|
|
def endIter(self):
|
|
pass
|
|
|
|
def finish(self):
|
|
pass
|
|
|
|
class DirectiveList(object):
|
|
|
|
dList = None #: The list of Directives
|
|
|
|
def __init__(self, *directives, **kwargs):
|
|
self.dList = []
|
|
for d in directives:
|
|
assert isinstance(d, InversionDirective), 'All directives must be InversionDirectives not %s' % d.__name__
|
|
self.dList.append(d)
|
|
Utils.setKwargs(self, **kwargs)
|
|
|
|
@property
|
|
def debug(self):
|
|
return getattr(self, '_debug', False)
|
|
@debug.setter
|
|
def debug(self, value):
|
|
for d in self.dList:
|
|
d.debug = value
|
|
self._debug = value
|
|
|
|
@property
|
|
def inversion(self):
|
|
"""This is the inversion of the InversionDirective instance."""
|
|
return getattr(self,'_inversion',None)
|
|
@inversion.setter
|
|
def inversion(self, i):
|
|
if self.inversion is i: return
|
|
if getattr(self,'_inversion',None) is not None:
|
|
print 'Warning: %s has switched to a new inversion.' % self.__name__
|
|
for d in self.dList:
|
|
d.inversion = i
|
|
self._inversion = i
|
|
|
|
def call(self, ruleType):
|
|
if self.dList is None:
|
|
if self.debug: 'DirectiveList is None, no directives to call!'
|
|
return
|
|
|
|
directives = ['initialize', 'endIter', 'finish']
|
|
assert ruleType in directives, 'Directive type must be in ["%s"]' % '", "'.join(directives)
|
|
for r in self.dList:
|
|
getattr(r, ruleType)()
|
|
|
|
|
|
class BetaEstimate_ByEig(InversionDirective):
|
|
"""BetaEstimate"""
|
|
|
|
beta0 = None #: The initial Beta (regularization parameter)
|
|
beta0_ratio = 0.1 #: estimateBeta0 is used with this ratio
|
|
|
|
def initialize(self):
|
|
"""
|
|
The initial beta is calculated by comparing the estimated
|
|
eigenvalues of JtJ and WtW.
|
|
|
|
To estimate the eigenvector of **A**, we will use one iteration
|
|
of the *Power Method*:
|
|
|
|
.. math::
|
|
|
|
\mathbf{x_1 = A x_0}
|
|
|
|
Given this (very course) approximation of the eigenvector,
|
|
we can use the *Rayleigh quotient* to approximate the largest eigenvalue.
|
|
|
|
.. math::
|
|
|
|
\lambda_0 = \\frac{\mathbf{x^\\top A x}}{\mathbf{x^\\top x}}
|
|
|
|
We will approximate the largest eigenvalue for both JtJ and WtW, and
|
|
use some ratio of the quotient to estimate beta0.
|
|
|
|
.. math::
|
|
|
|
\\beta_0 = \gamma \\frac{\mathbf{x^\\top J^\\top J x}}{\mathbf{x^\\top W^\\top W x}}
|
|
|
|
:rtype: float
|
|
:return: beta0
|
|
"""
|
|
|
|
if self.debug: print 'Calculating the beta0 parameter.'
|
|
|
|
m = self.invProb.m_current
|
|
u = self.invProb.u_current or self.prob.fields(m)
|
|
|
|
x0 = np.random.rand(*m.shape)
|
|
t = x0.dot(self.dmisfit.dataObj2Deriv(self.prob,m,x0,u=u))
|
|
b = x0.dot(self.reg.modelObj2Deriv(m, v=x0))
|
|
self.beta0 = self.beta0_ratio*(t/b)
|
|
|
|
self.invProb.beta = self.beta0
|
|
|
|
|
|
class BetaSchedule(InversionDirective):
|
|
"""BetaSchedule"""
|
|
|
|
coolingFactor = 2.
|
|
coolingRate = 3
|
|
|
|
def endIter(self):
|
|
if self.opt.iter > 0 and self.opt.iter % self.coolingRate == 0:
|
|
if self.debug: print 'BetaSchedule is cooling Beta. Iteration: %d' % self.opt.iter
|
|
self.invProb.beta /= self.coolingFactor
|
|
|
|
|
|
# class UpdateReferenceModel(Parameter):
|
|
|
|
# mref0 = None
|
|
|
|
# def nextIter(self):
|
|
# mref = getattr(self, 'm_prev', None)
|
|
# if mref is None:
|
|
# if self.debug: print 'UpdateReferenceModel is using mref0'
|
|
# mref = self.mref0
|
|
# self.m_prev = self.invProb.m_current
|
|
# return mref
|