Пример #1
0
    def gradient(self):
        ranefs = self.mm.random_effects
        y, P = self.mm.y, self.P
        Py = P * y

        PVis = [P * rf.V_i for rf in ranefs]
        return 0.5 * np.array([-1 * np.trace(PVi) + matrix.item(y.T * PVi * Py) for PVi in PVis])
Пример #2
0
    def average_information_matrix(self):
        y = self.mm.y
        P = self.P
        Py = P * y
        
        varmats = [x.V_i for x in self.mm.random_effects]
        nrf = len(varmats)

        def is_residual(idx):
            return idx == nrf - 1

        residual_variance = self.parameters[-1]
             
        mat = np.zeros((nrf, nrf))

        for i, V_i in enumerate(varmats):
            for j, V_j in enumerate(varmats):
                if j < i: 
                    continue
                
                element = 1/2 * y.T * P * V_i * P * V_j * P * y
                element = matrix.item(element)
                mat[i, j] = element
                mat[j, i] = element


        return 1*np.matrix(mat)
Пример #3
0
 def hessian_element(self, PV_i, PV_j):
     "Second derivative of REML function w.r.t two variance components"
     y, P = self.mm.y, self.P
     PViPVj = PV_i * PV_j
     a = 0.5 * np.trace(PViPVj)
     b = y.T * PViPVj * P * y
     return matrix.item(a - b)
Пример #4
0
    def loglikelihood(self):
        n = self.mm.nobs()

        y, X, beta = self.mm.y, self.mm.X, self.beta
        resid = y - X * beta
        llik = -0.5 * (n*l2pi + logdet(self.V) + resid.T * self.Vinv * resid)
        return matrix.item(llik)
Пример #5
0
    def loglikelihood(self):
        "Full loglikelihood of the model"
        n = self.mm.nobs()

        y, X, beta = self.mm.y, self.mm.X, self.beta
        resid = y - X * beta
        llik = -0.5 * (n*l2pi + logdet(self.V) + resid.T * self.Vinv * resid)
        return matrix.item(llik)
Пример #6
0
def full_loglikelihood(y, V, X, beta, Vinv=None):
    """
    Returns the full loglikelihood of a mixed model

    Ref: SAS documentation for PROC MIXED
    """
    if Vinv is None:
        Vinv = makeVinv(V)
    n = X.shape[0]
    fixefresids = y - X * beta
    llik = -0.5 * (n * l2pi + logdet(V) + fixefresids.T * Vinv * fixefresids)
    return matrix.item(llik)
Пример #7
0
def full_loglikelihood(y, V, X, beta, Vinv=None):
    """
    Returns the full loglikelihood of a mixed model

    Ref: SAS documentation for PROC MIXED
    """
    if Vinv is None:
        Vinv = makeVinv(V)
    n = X.shape[0]
    fixefresids = y - X * beta
    llik = -0.5 * (n * l2pi + logdet(V) + fixefresids.T * Vinv * fixefresids)
    return matrix.item(llik)
Пример #8
0
    def expectation_maximization(self):
        "Performs a round of Expectation-Maximization ML"
        resid, Vinv = self.resid, self.Vinv

        n = self.mm.nobs()
        coefficients = np.array([
            matrix.item(resid.T * Vinv * rf.V_i * Vinv * resid - np.trace(Vinv * rf.V_i))
                        for rf in self.mm.random_effects])

        levelsizes = np.array([x.nlevels for x in self.mm.random_effects])

        delta = (self.parameters ** 2 / levelsizes) * coefficients
        return self.parameters + delta
Пример #9
0
    def hessian_element(self, V_i, V_j):
        """
        Second derivative of the full loglikelihood with regard to two 
        variance components

        :param V_i: variance-covariance matrix of the first component
        :param V_i: matrix
        :param V_j: variance-covariance matrix of the second component
        :param V_j: matrix

        :returns: derivative
        :rtype: float 
        """

        resid, Vinv = self.resid, self.Vinv
        term1 = 0.5 * np.trace(Vinv * V_i * Vinv * V_j)
        term2 = resid.T * Vinv * V_i * Vinv * V_j * Vinv * resid

        return matrix.item(term1 - term2)
Пример #10
0
    def loglikelihood(self):
        """
        Returns the restricted loglikelihood for mixed model variance component
        estimation.

        References:

        Harville. 'Maximum Likelihood Approaches to Variance Component
        Estimation and to Related Problems' Journal of the American Statistical
        Association. (1977) (72):258
        """
        y, V, X, P, Vinv = self.mm.y, self.V, self.mm.X, self.P, self.Vinv
        n = X.shape[0]

        rank = np.linalg.matrix_rank(X)
        llik_restricted = -0.5 * (logdet(V.todense())
                                  + logdet(X.transpose() * Vinv * X)
                                  + y.T * P * y
                                  + (n - rank) * l2pi)
        return matrix.item(llik_restricted)
Пример #11
0
    def loglikelihood(self):
        """
        Returns the restricted loglikelihood for mixed model variance component
        estimation.

        References:

        Harville. 'Maximum Likelihood Approaches to Variance Component
        Estimation and to Related Problems' Journal of the American Statistical
        Association. (1977) (72):258
        """
        y, V, X, P, Vinv = self.mm.y, self.V, self.mm.X, self.P, self.Vinv
        n = X.shape[0]

        rank = np.linalg.matrix_rank(X)
        llik_restricted = -0.5 * (logdet(V.todense())
                                  + logdet(X.transpose() * Vinv * X)
                                  + y.T * P * y
                                  + (n - rank) * l2pi)
        return matrix.item(llik_restricted)
Пример #12
0
    def average_information_matrix(self):
        y = self.mm.y
        P = self.P
        Py = P * y
        
        varmats = [x.V_i for x in self.mm.random_effects]
        nrf = len(varmats)
             
        mat = np.zeros((nrf, nrf))

        for i, V_i in enumerate(varmats):
            for j, V_j in enumerate(varmats):
                if j < i: 
                    continue
                
                element = 0.5 * y.T * P * V_i * P * V_j * Py
                element = matrix.item(element)
                mat[i, j] = element
                mat[j, i] = element


        return np.matrix(mat)
Пример #13
0
def minque(mm, starts=None, value=0, maxiter=200, tol=1e-4,
           verbose=False, return_after=1e300, return_vcs=False):
    """ 
    MINQUE (MInimum Norm Quadratic Unbiansed Estimation). Only used for 
    historical purposes or getting starting variance components for another
    maximization scheme.

    MINQUE gets variance component estimates by solving the equation Cz=t

    For d random effects 
    z is a vector of variance compnents
    C is a dxd matrix with element  C_ij trace(P * V_i * P * V_j)
    t is a column vector with row element i = y' * P * V_i * P * y

    M = I_n - (1/n) * ONES_n * ONES_n'
    (Ones_n is a row vector of all ones)


    Useful reference: 
    J.W. Keele & W.R. Harvey (1988) "Estimation of components of variance and
    covariance by symmetric difference squaredand minimum norm quadratic 
    unbiased estimation: a comparison" Journal of Animal Science
    Vol 67. No.2 p348-356
    doi:10.2134/jas1989.672348x
    """
    d = len(mm.random_effects)  # the number of random effects
    if verbose:
        print('Maximizing model by MINQUE')

    if starts is not None:
        weights = np.array(starts)

    elif value == 0:
        # MINQUE(0)
        weights = np.zeros(d)
        weights[-1] = 1

    elif value == 1:
        # MINQUE(1)
        weights = np.ones(d)

    vcs = np.var(mm.y - mm.X * mm.beta) * weights
    n = mm.nobs()

    y = mm.y

    if verbose:
        print(vcs)
    for i in range(maxiter):

        if i + 1 > return_after:
            return vcs

        V = mm._makeV(vcs=vcs.tolist())
        Vinv = makeVinv(V)
        P = makeP(mm.X, Vinv)

        t = [matrix.item(y.T * P * ranef.V_i * P * y)
             for ranef in mm.random_effects]
        t = np.matrix(t).T

        # Make C
        C = []
        for ranef_i in mm.random_effects:
            row = [np.trace(P * ranef_i.V_i * P * ranef_j.V_i)
                   for ranef_j in mm.random_effects]
            C.append(row)
        C = np.matrix(C)
        new_vcs = scipy.linalg.solve(C, t).T[0]

        delta = (new_vcs / new_vcs.sum()) - (vcs / vcs.sum())
        llik = restricted_loglikelihood(mm.y, V, mm.X, P, Vinv)

        if all(delta < tol):
            if return_vcs:
                return new_vcs
            mle = MLEResult(new_vcs, llik, 'MINQUE')
            return mle

        if verbose:
            print((i, llik, vcs))
        vcs = new_vcs
        weights = vcs
Пример #14
0
        def get_coef(rf):
            V_i = rf.V_i
            PVi = P * V_i

            return matrix.item(y.T * PVi * Py - np.trace(PVi))
Пример #15
0
 def element(PVi):
     return 0.5 * np.trace(PVi) + matrix.item(y.T * PVi * Py)
Пример #16
0
 def coef(rf):
     "gets the coefficients for em estimation"
     VinvV_i = Vinv * rf.V_i 
     c1 = resid.T * VinvV_i * Vinvresid - np.trace(VinvV_i)
     return matrix.item(c1)
Пример #17
0
    def hessian_element(self, V_i, V_j):
        resid, Vinv = self.resid, self.Vinv
        term1 = 0.5 * np.trace(Vinv * V_i * Vinv * V_j)
        term2 = resid.T * Vinv * V_i * Vinv * V_j * Vinv * resid

        return matrix.item(term1 - term2)
Пример #18
0
        def get_coef(rf):
            V_i = rf.V_i
            PVi = P * V_i

            return matrix.item(y.T * PVi * Py - np.trace(PVi))
Пример #19
0
 def hessian_element(self, PV_i, PV_j):
     y, P = self.mm.y, self.P
     PViPVj = PV_i * PV_j
     a = 0.5 * np.trace(PViPVj)
     b = y.T * PViPVj * P * y
     return matrix.item(a - b)