mirror of
https://github.com/wassname/simpeg.git
synced 2026-09-11 12:44:29 +08:00
Simple profiling through decorator functions. (counting and timing of functions decorated with @count and @timeIt that have a SimPEG.utils.Counter)
e.g. output: ‘’’ Counters: InexactGaussNewton.doEndIteration : 6 InexactGaussNewton.printIter : 7 InexactGaussNewton.scaleSearchDirection : 6 Times: mean sum InexactGaussNewton.findSearchDirection : 1.55e-02, 9.29e-02, 6x InexactGaussNewton.minimize : 1.10e-01, 1.10e-01, 1x InexactGaussNewton.modifySearchDirection: 2.89e-04, 1.73e-03, 6x InexactGaussNewton.projection : 3.69e-06, 1.11e-04, 30x InexactGaussNewton.stoppingCriteria : 1.16e-04, 1.51e-03, 13x Inversion.dataObj : 6.60e-05, 8.58e-04, 13x Inversion.dataObj2Deriv : 1.03e-04, 6.20e-03, 60x Inversion.dataObjDeriv : 5.06e-05, 3.54e-04, 7x Inversion.evalFunction : 7.75e-04, 1.01e-02, 13x Inversion.run : 1.10e-01, 1.10e-01, 1x Regularization.modelObj : 3.56e-04, 4.63e-03, 13x Regularization.modelObj2Deriv : 1.29e-03, 7.76e-02, 60x Regularization.modelObjDeriv : 5.01e-04, 3.51e-03, 7x ‘’’
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
import scipy.sparse as sp
|
||||
import SimPEG
|
||||
from SimPEG.utils import sdiag, mkvc, setKwargs, checkStoppers, printStoppers
|
||||
from SimPEG.utils import sdiag, mkvc, setKwargs, checkStoppers, printStoppers, count, timeIt
|
||||
from Optimize import Remember
|
||||
from BetaSchedule import Cooling
|
||||
|
||||
@@ -13,6 +13,8 @@ class BaseInversion(object):
|
||||
debug = False
|
||||
beta0 = 1e4
|
||||
|
||||
counter = None
|
||||
|
||||
def __init__(self, prob, reg, opt, **kwargs):
|
||||
setKwargs(self, **kwargs)
|
||||
self.prob = prob
|
||||
@@ -56,6 +58,7 @@ class BaseInversion(object):
|
||||
def phi_d_target(self, value):
|
||||
self._phi_d_target = value
|
||||
|
||||
@timeIt
|
||||
def run(self, m0):
|
||||
self.startup(m0)
|
||||
while True:
|
||||
@@ -131,7 +134,7 @@ class BaseInversion(object):
|
||||
"""
|
||||
printStoppers(self, self.stoppers)
|
||||
|
||||
|
||||
@timeIt
|
||||
def evalFunction(self, m, return_g=True, return_H=True):
|
||||
|
||||
u = self.prob.field(m)
|
||||
@@ -162,7 +165,7 @@ class BaseInversion(object):
|
||||
out += (operator,)
|
||||
return out if len(out) > 1 else out[0]
|
||||
|
||||
|
||||
@timeIt
|
||||
def dataObj(self, m, u=None):
|
||||
"""
|
||||
:param numpy.array m: geophysical model
|
||||
@@ -184,6 +187,7 @@ class BaseInversion(object):
|
||||
R = mkvc(R)
|
||||
return 0.5*np.vdot(R, R)
|
||||
|
||||
@timeIt
|
||||
def dataObjDeriv(self, m, u=None):
|
||||
"""
|
||||
:param numpy.array m: geophysical model
|
||||
@@ -224,6 +228,7 @@ class BaseInversion(object):
|
||||
|
||||
return dmisfit
|
||||
|
||||
@timeIt
|
||||
def dataObj2Deriv(self, m, v, u=None):
|
||||
"""
|
||||
:param numpy.array m: geophysical model
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from SimPEG.utils import mkvc, sdiag, setKwargs, printTitles, printLine, printStoppers, checkStoppers
|
||||
from SimPEG.utils import mkvc, sdiag, setKwargs, printTitles, printLine, printStoppers, checkStoppers, count, timeIt
|
||||
norm = np.linalg.norm
|
||||
import scipy.sparse as sp
|
||||
from SimPEG import Solver
|
||||
@@ -106,6 +106,8 @@ class Minimize(object):
|
||||
debug = False
|
||||
debugLS = False
|
||||
|
||||
counter = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._id = int(np.random.rand()*1e6) # create a unique identifier to this program to be used in pubsub
|
||||
self.stoppers = [StoppingCriteria.tolerance_f, StoppingCriteria.moving_x, StoppingCriteria.tolerance_g, StoppingCriteria.norm_g, StoppingCriteria.iteration]
|
||||
@@ -116,6 +118,7 @@ class Minimize(object):
|
||||
|
||||
setKwargs(self, **kwargs)
|
||||
|
||||
@timeIt
|
||||
def minimize(self, evalFunction, x0):
|
||||
"""
|
||||
Minimizes the function (evalFunction) starting at the location x0.
|
||||
@@ -263,6 +266,7 @@ class Minimize(object):
|
||||
name = self.name if not inLS else self.nameLS
|
||||
printTitles(self, self.printers if not inLS else self.printersLS, name, pad)
|
||||
|
||||
@count
|
||||
def printIter(self, inLS=False):
|
||||
"""
|
||||
**printIter** is called directly after function evaluations.
|
||||
@@ -289,14 +293,14 @@ class Minimize(object):
|
||||
stoppers = self.stoppers if not inLS else self.stoppersLS
|
||||
printStoppers(self, stoppers, pad='', stop=stop, done=done)
|
||||
|
||||
|
||||
@timeIt
|
||||
def stoppingCriteria(self, inLS=False):
|
||||
if self._iter == 0:
|
||||
self.f0 = self.f
|
||||
self.g0 = self.g
|
||||
return checkStoppers(self, self.stoppers if not inLS else self.stoppersLS)
|
||||
|
||||
|
||||
@timeIt
|
||||
def projection(self, p):
|
||||
"""
|
||||
projects the search direction.
|
||||
@@ -309,6 +313,7 @@ class Minimize(object):
|
||||
"""
|
||||
return p
|
||||
|
||||
@timeIt
|
||||
def findSearchDirection(self):
|
||||
"""
|
||||
**findSearchDirection** should return an approximation of:
|
||||
@@ -338,6 +343,7 @@ class Minimize(object):
|
||||
"""
|
||||
return -self.g
|
||||
|
||||
@count
|
||||
def scaleSearchDirection(self, p):
|
||||
"""
|
||||
**scaleSearchDirection** should scale the search direction if appropriate.
|
||||
@@ -355,6 +361,7 @@ class Minimize(object):
|
||||
|
||||
nameLS = "Armijo linesearch"
|
||||
|
||||
@timeIt
|
||||
def modifySearchDirection(self, p):
|
||||
"""
|
||||
**modifySearchDirection** changes the search direction based on some sort of linesearch or trust-region criteria.
|
||||
@@ -391,6 +398,7 @@ class Minimize(object):
|
||||
|
||||
return self._LS_xt, self._iterLS < self.maxIterLS
|
||||
|
||||
@count
|
||||
def modifySearchDirectionBreak(self, p):
|
||||
"""
|
||||
Code is called if modifySearchDirection fails
|
||||
@@ -411,6 +419,7 @@ class Minimize(object):
|
||||
print 'The linesearch got broken. Boo.'
|
||||
return p, False
|
||||
|
||||
@count
|
||||
def doEndIteration(self, xt):
|
||||
"""
|
||||
**doEndIteration** is called at the end of each minimize iteration.
|
||||
@@ -529,18 +538,22 @@ class ProjectedGradient(Minimize, Remember):
|
||||
|
||||
self.aSet_prev = self.activeSet(x0)
|
||||
|
||||
@count
|
||||
def projection(self, x):
|
||||
"""Make sure we are feasible."""
|
||||
return np.median(np.c_[self.lower,x,self.upper],axis=1)
|
||||
|
||||
@count
|
||||
def activeSet(self, x):
|
||||
"""If we are on a bound"""
|
||||
return np.logical_or(x == self.lower, x == self.upper)
|
||||
|
||||
@count
|
||||
def inactiveSet(self, x):
|
||||
"""The free variables."""
|
||||
return np.logical_not(self.activeSet(x))
|
||||
|
||||
@count
|
||||
def bindingSet(self, x):
|
||||
"""
|
||||
If we are on a bound and the negative gradient points away from the feasible set.
|
||||
@@ -552,6 +565,7 @@ class ProjectedGradient(Minimize, Remember):
|
||||
bind_low = np.logical_and(x == self.upper, self.g <= 0)
|
||||
return np.logical_or(bind_up, bind_low)
|
||||
|
||||
@timeIt
|
||||
def findSearchDirection(self):
|
||||
self.aSet_prev = self.activeSet(self.xc)
|
||||
allBoundsAreActive = sum(self.aSet_prev) == self.xc.size
|
||||
@@ -592,6 +606,7 @@ class ProjectedGradient(Minimize, Remember):
|
||||
# aSet_after = self.activeSet(self.xc+p)
|
||||
return p
|
||||
|
||||
@timeIt
|
||||
def _doEndIteration_ProjectedGradient(self, xt):
|
||||
aSet = self.activeSet(xt)
|
||||
bSet = self.bindingSet(xt)
|
||||
@@ -622,6 +637,8 @@ class ProjectedGradient(Minimize, Remember):
|
||||
|
||||
class GaussNewton(Minimize, Remember):
|
||||
name = 'Gauss Newton'
|
||||
|
||||
@timeIt
|
||||
def findSearchDirection(self):
|
||||
return Solver(self.H).solve(-self.g)
|
||||
|
||||
@@ -632,6 +649,7 @@ class InexactGaussNewton(Minimize, Remember):
|
||||
maxIterCG = 10
|
||||
tolCG = 1e-5
|
||||
|
||||
@timeIt
|
||||
def findSearchDirection(self):
|
||||
# TODO: use BFGS as a preconditioner or gauss sidel of the WtW or solve WtW directly
|
||||
p, info = sp.linalg.cg(self.H, -self.g, tol=self.tolCG, maxiter=self.maxIterCG)
|
||||
@@ -640,6 +658,8 @@ class InexactGaussNewton(Minimize, Remember):
|
||||
|
||||
class SteepestDescent(Minimize, Remember):
|
||||
name = 'Steepest Descent'
|
||||
|
||||
@timeIt
|
||||
def findSearchDirection(self):
|
||||
return -self.g
|
||||
|
||||
|
||||
Reference in New Issue
Block a user