Commit a35319be authored by Martin Reinecke's avatar Martin Reinecke
Browse files

performance tweak

parent b94097df
Pipeline #22730 passed with stage
in 4 minutes and 51 seconds
from .. import Field, exp
from ..operators.diagonal_operator import DiagonalOperator
from ..minimization.energy import Energy
from ..utilities import memo
class NoiseEnergy(Energy):
def __init__(self, position, d, m, D, t, FFT, Instrument, nonlinearity,
alpha, q, Projection, samples=3, sample_list=None,
inverter=None):
super(NoiseEnergy, self).__init__(position=position.copy())
super(NoiseEnergy, self).__init__(position=position)
self.m = m
self.D = D
self.d = d
......@@ -25,17 +24,14 @@ class NoiseEnergy(Energy):
self.power = self.Projection.adjoint_times(exp(0.5 * self.t))
self.one = Field(self.position.domain, val=1.)
if sample_list is None:
sample_list = []
if samples is None:
sample_list.append(self.m)
if samples is None or samples == 0:
sample_list = [m]
else:
for i in range(samples):
sample = D.generate_posterior_sample(m)
sample = FFT(Field(FFT.domain, val=(
FFT.adjoint_times(sample).val)))
sample_list.append(sample)
sample_list = [D.generate_posterior_sample(m)
for _ in range(samples)]
self.sample_list = sample_list
self.inverter = inverter
self._value, self._gradient = self._value_and_grad()
def at(self, position):
return self.__class__(
......@@ -44,43 +40,35 @@ class NoiseEnergy(Energy):
self.Projection, sample_list=self.sample_list,
samples=self.samples, inverter=self.inverter)
@property
@memo
def value(self):
likelihood = 0.
def _value_and_grad(self):
likelihood_gradient = None
for sample in self.sample_list:
likelihood += self._likelihood(sample)
return ((likelihood / float(len(self.sample_list))) +
0.5 * self.one.vdot(self.position) +
(self.alpha - self.one).vdot(self.position) +
self.q.vdot(exp(-self.position)))
residual = self.d - \
self.Instrument(self.nonlinearity(
self.FFT.adjoint_times(self.power*sample)))
lh = 0.5 * residual.vdot(self.N.inverse_times(residual))
grad = -0.5 * self.N.inverse_times(residual.conjugate() * residual)
if likelihood_gradient is None:
likelihood = lh
likelihood_gradient = grad.copy()
else:
likelihood += lh
likelihood_gradient += grad
def _likelihood(self, m):
residual = self.d - \
self.Instrument(self.nonlinearity(
self.FFT.adjoint_times(self.power * m)))
energy = 0.5 * residual.vdot(self.N.inverse_times(residual))
return energy.real
likelihood = ((likelihood / float(len(self.sample_list))) +
0.5 * self.position.integrate() +
(self.alpha - 1.).vdot(self.position) +
self.q.vdot(exp(-self.position)))
likelihood_gradient = (
likelihood_gradient / float(len(self.sample_list)) +
(self.alpha-0.5) -
self.q * (exp(-self.position)))
return likelihood, likelihood_gradient
@property
@memo
def gradient(self):
likelihood_gradient = Field(self.position.domain, val=0.)
for sample in self.sample_list:
likelihood_gradient += self._likelihood_gradient(sample)
return (likelihood_gradient / float(len(self.sample_list)) +
0.5 * self.one + (self.alpha - self.one) -
self.q * (exp(-self.position)))
def _likelihood_gradient(self, m):
residual = self.d - \
self.Instrument(self.nonlinearity(
self.FFT.adjoint_times(self.power * m)))
gradient = - 0.5 * \
self.N.inverse_times(residual.conjugate() * residual)
return gradient
def value(self):
return self._value
@property
@memo
def curvature(self):
pass
def gradient(self):
return self._gradient
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment