Beispiel #1
0
 def plot(self, x, y, z=None, ep=None, **kwargs):
     if np.any(ep):
         zern = Zernike(ep)
         fig, ax = zern.plot(x, y, **kwargs)
     elif np.any(z):
         fig, ax = self.zern.plot(x, y, z=z, **kwargs)
     else:
         fig, ax = self.zern.plot(x, y, **kwargs)
     return fig, ax
Beispiel #2
0
class GradientDissenter(object):

    def __init__(self, emunup, Imax=15, Jmax=21, Kmax=3):
        self.emunup = emunup
        self.zern = Zernike(self.emunup[0][0])
        self.Mu = self.emunup.shape[0]
        self.Nu = self.emunup.shape[1]
        self.Pmax = self.emunup.shape[2]
        self.Imax = Imax
        self.Jmax = Jmax
        self.Kmax = Kmax

        # get relevant matrices
        self.beta, self.alphaJ = self.make_matrices(self.Imax, self.Jmax)

        self.ndim = self.Imax * (self.Jmax + self.Kmax * self.Nu) + self.Mu
        p0 = 1e-2 * np.random.randn(self.ndim)
        p0[:3] = 1
        self.kmu, self.bij, self.cnuik = self.p_to_matrices(p0)
        self.loss_history = [np.inf]  # number, not object
        self.kmus = [self.kmu.copy()]
        self.bijs = [self.bij.copy()]
        self.cnuiks = [self.cnuik.copy()]
        self.logs = [[np.inf] * 3]
        self.ehat = fast_zernike.fast_calc(self.kmu, self.bij, self.cnuik, self.beta, self.alphaJ)
        self.ehats = [self.ehat.copy()]

    @classmethod
    def make_matrices(cls, Imax, Jmax):
        Zern = Zernike(Imax)
        gamma_x = Zern.gamma_x
        gamma_y = Zern.gamma_y
        alpha_I = Zern.mult_matrix
        # do multiplication of gammas and alpha to beta
        # TODO: Might have to flip gamma's
        # beta^mu_il = sum_kn gamma_ki gamma_nl alpha_kn1
        # where K < I
        Nmax = gamma_x.shape[0]
        bxx = np.dot(gamma_x.T, np.dot(gamma_x.T, alpha_I[:Nmax, :Nmax]))
        byy = np.dot(gamma_y.T, np.dot(gamma_y.T, alpha_I[:Nmax, :Nmax]))
        bxy = np.dot(gamma_x.T, np.dot(gamma_y.T, alpha_I[:Nmax, :Nmax]))

        beta0 = (bxx + byy)[:,:,0]
        beta1 = (bxx - byy)[:,:,0]
        beta2 = (2 * bxy)[:,:,0]
        beta = np.array([beta0, beta1, beta2])

        alphaJ = Zernike(Jmax).mult_matrix

        return beta, alphaJ

    def plot(self, x, y, z=None, ep=None, **kwargs):
        if np.any(ep):
            zern = Zernike(ep)
            fig, ax = zern.plot(x, y, **kwargs)
        elif np.any(z):
            fig, ax = self.zern.plot(x, y, z=z, **kwargs)
        else:
            fig, ax = self.zern.plot(x, y, **kwargs)
        return fig, ax

    def p_to_matrices(self, p):
        """
        We have the following things:
        K^mu
        b_{ij}
        c^nu_{ik}

        mu \in (0, 2]
        nu \in (0, Nexposures]
        i \in (0, Imax]  # number of zernikes to represent
        j \in (0, Jmax]  # number of field zernikes
        k \in (0, Kmax]  # number of field corrections
        """
        kmu = p[:self.Mu]
        bij = p[self.Mu: self.Jmax * self.Imax + self.Mu]
        cnuik = p[self.Jmax * self.Imax + self.Mu: (self.Jmax * self.Imax + self.Mu) + self.Imax * self.Kmax * self.Nu]
        bij = bij.reshape(self.Imax, self.Jmax)
        cnuik = cnuik.reshape(self.Nu, self.Imax, self.Kmax)
        return kmu, bij, cnuik

    def fit(self, xtol=1e-8, ftol=1e-6, maxiter=10000, step_size=None,
            maxfun=None, verbose=False, learning_rate_decay=0,
            **kwargs):
        """
        ala scipy.optimize:
        xtol : float, optional
            Relative error in xopt acceptable for convergence.
        ftol : number, optional
            Relative error in func(xopt) acceptable for convergence.
        maxiter : int, optional
            Maximum number of iterations to perform.
        maxfun : number, optional
            Maximum number of function evaluations to make.
            TODO: Currently not implimented

        learning_rate_decay : if step_size is specified, after every update, multiply step_size by (1 - learning_rate_decay)
        """
        # TODO: incorporate several different parameter update modes
        """
        if update == 'sgd':
          dx = -learning_rate * grads[p]
        elif update == 'momentum':
          if not p in self.step_cache:
            self.step_cache[p] = np.zeros(grads[p].shape)
          dx = np.zeros_like(grads[p]) # you can remove this after
          dx = momentum * self.step_cache[p] - learning_rate * grads[p]
          self.step_cache[p] = dx
        elif update == 'rmsprop':
          decay_rate = 0.99 # you could also make this an option
          if not p in self.step_cache:
            self.step_cache[p] = np.zeros(grads[p].shape)
          dx = np.zeros_like(grads[p]) # you can remove this after
          self.step_cache[p] = self.step_cache[p] * decay_rate + (1.0 - decay_rate) * grads[p] ** 2
          dx = -(learning_rate * grads[p]) / np.sqrt(self.step_cache[p] + 1e-8)
        """
        for it in xrange(maxiter):
            if verbose: print(it, self.loss_history[-1])
            lnlike_old = self.loss_history[-1]

            self.ehat = fast_zernike.fast_calc(self.kmu, self.bij, self.cnuik, self.beta, self.alphaJ)
            self.dlogldb = fast_zernike.fast_calc_dlogldb(self.kmu, self.bij, self.cnuik, self.emunup, self.ehat, self.beta, self.alphaJ)
            self.dlogldc = fast_zernike.fast_calc_dlogldc(self.kmu, self.bij, self.cnuik, self.emunup, self.ehat, self.beta, self.alphaJ)
            self.dlogldk = fast_zernike.fast_calc_dlogldk(self.kmu, self.bij, self.cnuik, self.emunup, self.ehat, self.beta, self.alphaJ)
            lnlike = np.mean(np.square(self.emunup - self.ehat))
            if lnlike - lnlike_old > 1e-2 * lnlike_old:
                print(it, lnlike)
                return
            # apply derivatives
            self.kmus.append(self.kmu.copy())
            self.bijs.append(self.bij.copy())
            self.cnuiks.append(self.cnuik.copy())
            self.ehats.append(self.ehat.copy())
            self.logs.append([self.dlogldb.copy(), self.dlogldc.copy(), self.dlogldk.copy()])
            self.kmu -= step_size * self.dlogldk
            self.cnuik -= step_size * self.dlogldc
            self.bij -= step_size * self.dlogldb

            self.loss_history.append(lnlike)


            if type(step_size) != type(None):
                step_size *= 1 - learning_rate_decay

            # check changes
            if np.abs((lnlike - lnlike_old) / lnlike) < ftol:
                print ('ftol reached')
                return
            # if np.all(asdf < xtol):
            #     print ('xtol reached')
            #     return
        print('maxiter reached')
        return