Пример #1
0
    def predict(self, xs):
        """ Predict the outputs and thier variance, y* and V[y*], given new
            inputs, x*.

            Arguments:
                xs: [DxN] test points for prediction (x*)

            Returns:
                Ems: array of N predictions of m*
                Vms: array of N predictions of the variance of m*, V[m*].
        """

        # Check we have trained
        D, N = self._check_prediction_inputs(xs)

        # Pre-allocate
        Ems, Vms = np.zeros(N), np.zeros(N)

        # Evaluate test kernel vectors and do a stable inversion
        ks = self.kfunc(self.x, np.atleast_2d(xs), *self.kparams)
        Kinvks = cholsolve(jitchol(self.C), ks)

        for n, xn in enumerate(xs.T):

            # Evaluate the test kernel vectors
            kss = self.kfunc(np.atleast_2d(xn).T, np.atleast_2d(xn).T,
                             *self.kparams)

            # Predict the latent function
            Ems[n] = (Kinvks[:, n].T).dot(self.m)
            Vms[n] = kss - Kinvks[:, n].T.dot(ks[:, n])

        return Ems, Vms
Пример #2
0
    def __gplearn(self, y, K, delta=None, maxit=None, verbose=False):
        """ Parameter learning for a basic GP. Called by the _learn method. """

        N = y.shape[0]

        # Make posterior GP
        C = K + np.eye(N) * self.ynoise**2
        Cchol = jitchol(C)

        # Calculate the log-marginal-likelihood
        lml = -0.5 * (logdet(Cchol) + y.T.dot(cholsolve(Cchol, y)) + N *
                      np.log(2 * np.pi))

        return y, C, lml
Пример #3
0
    def _quadpredict(self, xs):
        """ Prediction of m* and E[y*] using quadrature to evaluate E[y*]. This
            is primarily intended for the nonlinear GPs.

            Arguments:
                xs: [DxN] test points for prediction

            Returns:
                Eys: array of N predictions of E[y*]
                eEys: array of N errors on each E[y*] integral evaluation
                Ems: array of N predictions of m*
                Vms: array of N predictions of the variance of m*, V[m*].
        """

        # Check we have trained
        D, N = self._check_prediction_inputs(xs)

        # Pre-allocate
        Ems, Vms, Eys, eEys = np.zeros(N), np.zeros(N), np.zeros(N), \
            np.zeros(N)

        # Expected predicted target (to be integrated)
        def expecy(xsn, Emn, Vmn):

            gxs = self._passnlfunc(self.nlfunc, xsn)
            quad_msEf = (xsn - Emn)**2 / Vmn
            return gxs * np.exp(-0.5 * (quad_msEf + np.log(2 * np.pi * Vmn)))

        # Evaluate test kernel vectors and do a stable inversion
        ks = self.kfunc(self.x, np.atleast_2d(xs), *self.kparams)
        Kinvks = cholsolve(self.Kchol, ks)

        for n, xn in enumerate(xs.T):

            # Evaluate the test kernel vectors
            kss = self.kfunc(np.atleast_2d(xn).T, np.atleast_2d(xn).T,
                             *self.kparams)

            # Predict the latent function
            Ems[n] = (Kinvks[:, n].T).dot(self.m)
            Vms[n] = kss - Kinvks[:, n].T.dot(ks[:, n]
                                              - self.C.dot(Kinvks[:, n]))

            # Use Quadrature to get predicted target value
            st = 4 * np.sqrt(Vms[n])  # Evaluate the integral to 4 sig
            Eys[n], eEys[n] = spint.quad(expecy, a=Ems[n]-st, b=Ems[n]+st,
                                         args=(Ems[n], Vms[n]))

        return Eys, eEys, Ems, Vms
Пример #4
0
    def predict(self, xs):
        """ Prediction of m* (the posterior mean of the latent function) and
            E[y*] at test points, x*, using the unscented transform to evaluate
            E[y*].

            Arguments:
                xs: [DxN] test points for prediction

            Returns:
                Eys: array of N predictions of E[y*]
                Vms: array of N predictions of the variance of y*, V[y*].
                Ems: array of N predictions of m*
                Vms: array of N predictions of the variance of m*, V[m*].
        """

        # Check we have trained and the inputs
        D, N = self._check_prediction_inputs(xs)

        # Evaluate test kernel vectors and do a stable inversion
        ks = self.kfunc(self.x, np.atleast_2d(xs), *self.kparams)
        Kinvks = cholsolve(self.Kchol, ks)

        # Pre-allocate
        Ems, Vms, Eys, Vys = np.zeros(N), np.zeros(N), np.zeros(N), np.zeros(N)

        for n, xn in enumerate(xs.T):

            # Evaluate the test kernel vectors
            kss = self.kfunc(
                np.atleast_2d(xn).T,
                np.atleast_2d(xn).T, *self.kparams)

            # Predict the latent function
            Ems[n] = (Kinvks[:, n].T).dot(self.m)
            Vms[n] = kss - Kinvks[:,
                                  n].T.dot(ks[:, n] - self.C.dot(Kinvks[:, n]))

            # Use the UT to predict the target value
            Ms = self.__makesigmas1D(Vms[n])
            Ms += Ems[n]
            Ys = self._passnlfunc(self.nlfunc, Ms)

            Eys[n] = (self.W * Ys).sum()
            Vys[n] = (self.W * (Ys - Eys[n])**2).sum()

        return Eys, Vys, Ems, Vms
Пример #5
0
    def predict(self, xs):
        """ Prediction of m* (the posterior mean of the latent function) and
            E[y*] at test points, x*, using the unscented transform to evaluate
            E[y*].

            Arguments:
                xs: [DxN] test points for prediction

            Returns:
                Eys: array of N predictions of E[y*]
                Vms: array of N predictions of the variance of y*, V[y*].
                Ems: array of N predictions of m*
                Vms: array of N predictions of the variance of m*, V[m*].
        """

        # Check we have trained and the inputs
        D, N = self._check_prediction_inputs(xs)

        # Evaluate test kernel vectors and do a stable inversion
        ks = self.kfunc(self.x, np.atleast_2d(xs), *self.kparams)
        Kinvks = cholsolve(self.Kchol, ks)

        # Pre-allocate
        Ems, Vms, Eys, Vys = np.zeros(N), np.zeros(N), np.zeros(N), np.zeros(N)

        for n, xn in enumerate(xs.T):

            # Evaluate the test kernel vectors
            kss = self.kfunc(np.atleast_2d(xn).T, np.atleast_2d(xn).T,
                             *self.kparams)

            # Predict the latent function
            Ems[n] = (Kinvks[:, n].T).dot(self.m)
            Vms[n] = kss - Kinvks[:, n].T.dot(ks[:, n]
                                              - self.C.dot(Kinvks[:, n]))

            # Use the UT to predict the target value
            Ms = self.__makesigmas1D(Vms[n])
            Ms += Ems[n]
            Ys = self._passnlfunc(self.nlfunc, Ms)

            Eys[n] = (self.W * Ys).sum()
            Vys[n] = (self.W * (Ys - Eys[n])**2).sum()

        return Eys, Vys, Ems, Vms
Пример #6
0
    def __taylin(self, y, K, delta=1e-6, maxit=200, rate=0.75, maxsteps=25,
                 verbose=False):
        """ Posterior parameter learning using 1st order Taylor series
            expansion of the nonlinear forward model.

            Arguments:
                y: N array of training outputs (dimensionality of 1)
                K: the [NxN] covariance matrix with the current hyper parameter
                    estimates.
                delta: [optional] the convergence threshold for the objective
                    function (free energy).
                dparams: [optional] the convergence threshold for the
                    hyperparameter values.
                maxit: [optional] maximum number of iterations for learning the
                    posterior parameters.
                rate: [optional] the learning rate of the line search used in
                    each of the Gauss-Newton style iterations for the posterior
                    mean.
                maxsteps: [optional] the maximum number of line-search steps.
                verbose: [optional] whether or not to display current learning
                    progress to the terminal.

            Returns:
                The final objective function value (free energy), and the
                posterior mean (m) and Covariance (C).
        """

        # Establish some parameters
        N = y.shape[0]
        m = np.zeros(N)

        # Make sigma points in latent space
        Kchol = jitchol(K)

        # Bootstrap iterations
        obj = np.finfo(float).min
        endcond = "maxit"

        # Pre-allocate
        a = np.zeros(N)
        H = np.zeros((N, N))

        for i in range(maxit):

            # Store old values in case of divergence, and for "line search"
            objo, mo, ao, Ho = obj, m.copy(), a.copy(), H.copy()

            # Taylor series linearisation
            gm = self._passnlfunc(self.nlfunc, mo)
            a = self._passnlfunc(self.dnlfunc, mo)

            # Kalmain gain
            AK = (a * K).T
            AKAsig = a * AK
            AKAsig[np.diag_indices(N)] += self.ynoise**2
            H = cholsolve(jitchol(AKAsig), AK).T

            # Do a bit of a heuristic line search for best step length
            for j in range(maxsteps):

                step = rate**j
                m = (1 - step) * mo + step * H.dot(y - gm + a * mo)

                # MAP objective
                ygm = y - self._passnlfunc(self.nlfunc, m)
                obj = -0.5 * (m.T.dot(cholsolve(Kchol, m))
                              + (ygm**2).sum()/self.ynoise**2)

                if obj >= objo:
                    break

            dobj = abs((objo - obj) / obj)

            # Divergence, use previous result
            if (obj < objo) & (dobj > delta):
                m, obj, a, H = mo, objo, ao, Ho  # recover old values
                endcond = "diverge"
                break

            # Convergence, use latest result
            if dobj <= delta:
                endcond = "converge"
                break

        if verbose is True:
            print("iters: {}, endcond = {}, MAP = {}, "
                  "delta = {:.2e}".format(i, endcond, obj, dobj))

        # Useful equations for Free energy
        C = K - H.dot((a * K).T)
        gm = self._passnlfunc(self.nlfunc, m)

        # Calculate Free Energy
        Feng = -0.5 * (N * np.log(np.pi * 2 * self.ynoise**2)
                       + ((y - gm)**2).sum() / self.ynoise**2
                       + m.T.dot(cholsolve(Kchol, m)) - logdet(C, dochol=True)
                       + logdet(Kchol))

        return m, C, Feng
Пример #7
0
    def __taylin(self,
                 y,
                 K,
                 delta=1e-6,
                 maxit=200,
                 rate=0.75,
                 maxsteps=25,
                 verbose=False):
        """ Posterior parameter learning using 1st order Taylor series
            expansion of the nonlinear forward model.

            Arguments:
                y: N array of training outputs (dimensionality of 1)
                K: the [NxN] covariance matrix with the current hyper parameter
                    estimates.
                delta: [optional] the convergence threshold for the objective
                    function (free energy).
                dparams: [optional] the convergence threshold for the
                    hyperparameter values.
                maxit: [optional] maximum number of iterations for learning the
                    posterior parameters.
                rate: [optional] the learning rate of the line search used in
                    each of the Gauss-Newton style iterations for the posterior
                    mean.
                maxsteps: [optional] the maximum number of line-search steps.
                verbose: [optional] whether or not to display current learning
                    progress to the terminal.

            Returns:
                The final objective function value (free energy), and the
                posterior mean (m) and Covariance (C).
        """

        # Establish some parameters
        N = y.shape[0]
        m = np.random.randn(N) / 100.0

        # Make sigma points in latent space
        Kchol = jitchol(K)

        # Bootstrap iterations
        obj = np.finfo(float).min
        endcond = "maxit"

        # Pre-allocate
        a = np.zeros(N)
        H = np.zeros((N, N))

        for i in range(maxit):

            # Store old values in case of divergence, and for "line search"
            objo, mo, ao, Ho = obj, m.copy(), a.copy(), H.copy()

            # Taylor series linearisation
            gm = self._passnlfunc(self.nlfunc, mo)
            a = self._passnlfunc(self.dnlfunc, mo)

            # Kalmain gain
            AK = (a * K).T
            AKAsig = a * AK
            AKAsig[np.diag_indices(N)] += self.ynoise**2
            H = cholsolve(jitchol(AKAsig), AK).T

            # Do a bit of a heuristic line search for best step length
            for j in range(maxsteps):

                step = rate**j
                m = (1 - step) * mo + step * H.dot(y - gm + a * mo)

                # MAP objective
                ygm = y - self._passnlfunc(self.nlfunc, m)
                obj = -0.5 * (m.T.dot(cholsolve(Kchol, m)) +
                              (ygm**2).sum() / self.ynoise**2)

                if obj >= objo:
                    break

            dobj = abs((objo - obj) / obj)

            # Divergence, use previous result
            if (obj < objo) & (dobj > delta):
                m, obj, a, H = mo, objo, ao, Ho  # recover old values
                endcond = "diverge"
                break

            # Convergence, use latest result
            if dobj <= delta:
                endcond = "converge"
                break

        if verbose is True:
            print("iters: {}, endcond = {}, MAP = {}, "
                  "delta = {:.2e}".format(i, endcond, obj, dobj))

        # Useful equations for Free energy
        C = K - H.dot((a * K).T)
        gm = self._passnlfunc(self.nlfunc, m)

        # Calculate Free Energy
        Feng = -0.5 * (N * np.log(np.pi * 2 * self.ynoise**2) +
                       ((y - gm)**2).sum() / self.ynoise**2 +
                       m.T.dot(cholsolve(Kchol, m)) - logdet(C, dochol=True) +
                       logdet(Kchol))

        return m, C, Feng
Пример #8
0
    def __statlin(self, y, K, delta=1e-6, maxit=200, rate=0.75, maxsteps=25,
                  verbose=False):
        """ Posterior parameter learning using the unscented transform and
            statistical linearisation.

            Arguments:
                y: N array of training outputs (dimensionality of 1)
                K: the [NxN] covariance matrix with the current hyper parameter
                    estimates.
                delta: [optional] the convergence threshold for the objective
                    function (free energy).
                dparams: [optional] the convergence threshold for the
                    hyperparameter values.
                maxit: [optional] maximum number of iterations for learning the
                    posterior parameters.
                rate: [optional] the learning rate of the line search used in
                    each of the Gauss-Newton style iterations for the posterior
                    mean.
                maxsteps: [optional] the maximum number of line-search steps.
                verbose: [optional] whether or not to display current learning
                    progress to the terminal.

            Returns:
                The final objective function value (free energy), and the
                posterior mean (m) and Covariance (C).
        """

        # Establish some parameters
        N = y.shape[0]
        m = np.zeros(N)

        # Make sigma points in latent space
        C = K.copy()
        Kchol = jitchol(K)
        Ms = self.__makesigmas1D(K)

        # Bootstrap iterations
        obj = np.finfo(float).min
        endcond = "maxit"
        ybar = y.copy()

        for i in range(maxit):

            # Store old values in case of divergence, and for "line search"
            objo, mo, ybaro = obj, m.copy(), ybar.copy()

            # Sigma points in obs. space and sigma point stats
            Ys = self._passnlfunc(self.nlfunc, m[:, np.newaxis] + Ms)
            ybar = (self.W * Ys).sum(axis=1)
            Sym = (self.W * (Ys - ybar[:, np.newaxis]) * Ms).sum(axis=1)

            # Statistical linearisation
            a = Sym / C.diagonal()

            # Kalmain gain
            AK = (a * K).T
            AKAsig = a * AK
            AKAsig[np.diag_indices(N)] += self.ynoise**2
            H = cholsolve(jitchol(AKAsig), AK).T

            # Do a bit of a heuristic line search for best step length
            for j in range(maxsteps):

                step = rate**j
                m = (1 - step) * mo + step * H.dot(y - ybar + a * mo)

                # MAP objective
                ygm = y - self._passnlfunc(self.nlfunc, m)
                obj = -0.5 * (m.T.dot(cholsolve(Kchol, m))
                              + (ygm**2).sum()/self.ynoise**2)

                if obj >= objo:
                    break

            dobj = abs((objo - obj) / obj)

            # Divergence, use previous result
            if (obj < objo) & (dobj > delta):
                m, ybar, obj = mo, ybaro, objo  # recover old values
                endcond = "diverge"
                break

            # Make posterior C if m has not diverged
            C = K - H.dot(AK)
            Ms = self.__makesigmas1D(C)

            # Convergence, use latest result
            if dobj <= delta:
                endcond = "converge"
                break

        if verbose is True:
            print("iters: {}, endcond = {}, MAP = {}, "
                  "delta = {:.2e}".format(i, endcond, obj, dobj))

        # Calculate Free Energy
        Feng = -0.5 * (N * np.log(np.pi * 2 * self.ynoise**2)
                       + ((y - ybar)**2).sum() / self.ynoise**2
                       + m.T.dot(cholsolve(Kchol, m)) - logdet(C, dochol=True)
                       + logdet(Kchol))

        return m, C, Feng
Пример #9
0
plt.legend(loc=3, fontsize=18)
plt.autoscale(tight=True)
ax.set_yticklabels(ax.get_yticks(), size=16)
ax.set_xticklabels(ax.get_xticks(), size=16)
plt.grid(True)

#plt.savefig('test.pdf', bbox_inches='tight')
#plt.show()

#true Latent function evaluation
#k_C,k_B, k_S, k_l
Kfu = lfmkernels.kern_ode_Kfu(xt[:, np.newaxis], xt[:, np.newaxis], k_C, k_B,
                              k_S, k_l)
Kff = lfmkernels.kern_ode(xt[:, np.newaxis], xt[:, np.newaxis], k_C, k_B, k_S,
                          k_l)
Kffinvfs = cholsolve(jitchol(Kff), ft[:, np.newaxis])
#True mean of u(t)
mu = np.dot(Kfu.T, Kffinvfs)

#estimated latent function u(t)
Kuu = lfmkernels.kern_ode_Kuu(xt[:, np.newaxis], gp.kparams[3])
Kfu = lfmkernels.kern_ode_Kfu(xt[:, np.newaxis], xt[:, np.newaxis],
                              *gp.kparams)
KffinvKfu = cholsolve(gp.Kchol, Kfu)

mus = (KffinvKfu.T).dot(gp.m)
Vms = np.diag(Kuu - KffinvKfu.T.dot(Kfu - gp.C.dot(KffinvKfu)))

plt.figure(figsize=(11, 6))
ax = plt.subplot(111)
plt.plot(xt, mu * k_S, label='True process, $u_{true}$')
Пример #10
0
    def __statlin(self,
                  y,
                  K,
                  delta=1e-6,
                  maxit=200,
                  rate=0.75,
                  maxsteps=25,
                  verbose=False):
        """ Posterior parameter learning using the unscented transform and
            statistical linearisation.

            Arguments:
                y: N array of training outputs (dimensionality of 1)
                K: the [NxN] covariance matrix with the current hyper parameter
                    estimates.
                delta: [optional] the convergence threshold for the objective
                    function (free energy).
                dparams: [optional] the convergence threshold for the
                    hyperparameter values.
                maxit: [optional] maximum number of iterations for learning the
                    posterior parameters.
                rate: [optional] the learning rate of the line search used in
                    each of the Gauss-Newton style iterations for the posterior
                    mean.
                maxsteps: [optional] the maximum number of line-search steps.
                verbose: [optional] whether or not to display current learning
                    progress to the terminal.

            Returns:
                The final objective function value (free energy), and the
                posterior mean (m) and Covariance (C).
        """

        # Establish some parameters
        N = y.shape[0]
        m = np.random.randn(N) / 100.0

        # Make sigma points in latent space
        C = K.copy()
        Kchol = jitchol(K)
        Ms = self.__makesigmas1D(K)

        # Bootstrap iterations
        obj = np.finfo(float).min
        endcond = "maxit"
        ybar = y.copy()

        for i in range(maxit):

            # Store old values in case of divergence, and for "line search"
            objo, mo, ybaro = obj, m.copy(), ybar.copy()

            # Sigma points in obs. space and sigma point stats
            Ys = self._passnlfunc(self.nlfunc, m[:, np.newaxis] + Ms)
            ybar = (self.W * Ys).sum(axis=1)
            Sym = (self.W * (Ys - ybar[:, np.newaxis]) * Ms).sum(axis=1)

            # Statistical linearisation
            a = Sym / C.diagonal()

            # Kalmain gain
            AK = (a * K).T
            AKAsig = a * AK
            AKAsig[np.diag_indices(N)] += self.ynoise**2
            H = cholsolve(jitchol(AKAsig), AK).T

            # Do a bit of a heuristic line search for best step length
            for j in range(maxsteps):

                step = rate**j
                m = (1 - step) * mo + step * H.dot(y - ybar + a * mo)

                # MAP objective
                ygm = y - self._passnlfunc(self.nlfunc, m)
                obj = -0.5 * (m.T.dot(cholsolve(Kchol, m)) +
                              (ygm**2).sum() / self.ynoise**2)

                if obj >= objo:
                    break

            dobj = abs((objo - obj) / obj)

            # Divergence, use previous result
            if (obj < objo) & (dobj > delta):
                m, ybar, obj = mo, ybaro, objo  # recover old values
                endcond = "diverge"
                break

            # Make posterior C if m has not diverged
            C = K - H.dot(AK)
            Ms = self.__makesigmas1D(C)

            # Convergence, use latest result
            if dobj <= delta:
                endcond = "converge"
                break

        if verbose is True:
            print("iters: {}, endcond = {}, MAP = {}, "
                  "delta = {:.2e}".format(i, endcond, obj, dobj))

        # Calculate Free Energy
        Feng = -0.5 * (N * np.log(np.pi * 2 * self.ynoise**2) +
                       ((y - ybar)**2).sum() / self.ynoise**2 +
                       m.T.dot(cholsolve(Kchol, m)) - logdet(C, dochol=True) +
                       logdet(Kchol))

        return m, C, Feng