コード例 #1
0
ファイル: sattherthwaite.py プロジェクト: nicholst/BLMM
def dS2deta(nparams, nlevels, L, XtX, XtZ, ZtZ, ZtX, D, sigma2):

    # Number of voxels
    nv = D.shape[0]

    # Calculate X'V^{-1}X=X'(I+ZDZ')^{-1}X=X'X-X'Z(I+DZ'Z)^{-1}DZ'X
    XtiVX = XtX - XtZ @ np.linalg.inv(np.eye(D.shape[1]) + D @ ZtZ) @ D @ ZtX

    # New empty array for differentiating S^2 wrt gamma.
    dS2deta = np.zeros((nv, 1+np.int32(np.sum(nparams*(nparams+1)/2)),1))

    # Work out indices for each start of each component of vector 
    # i.e. [dS2/dsigm2, dS2/vechD1,...dS2/vechDr]
    DerivInds = np.int32(np.cumsum(nparams*(nparams+1)/2) + 1)
    DerivInds = np.insert(DerivInds,0,1)

    # Work of derivative wrt to sigma^2
    dS2dsigma2 = L @ np.linalg.inv(XtiVX) @ L.transpose()

    # Add to dS2deta
    dS2deta[:,0:1] = dS2dsigma2.reshape(dS2deta[:,0:1].shape)

    # Now we need to work out ds2dVech(Dk)
    for k in np.arange(len(nparams)):

        # Initialize an empty zeros matrix
        dS2dvechDk = np.zeros((np.int32(nparams[k]*(nparams[k]+1)/2),1))#...

        for j in np.arange(nlevels[k]):

            # Get the indices for this level and factor.
            Ikj = faclev_indices2D(k, j, nlevels, nparams)
                    
            # Work out Z_(k,j)'Z
            ZkjtZ = ZtZ[:,Ikj,:]

            # Work out Z_(k,j)'X
            ZkjtX = ZtX[:,Ikj,:]

            # Work out Z_(k,j)'V^{-1}X
            ZkjtiVX = ZkjtX - ZkjtZ @ np.linalg.inv(np.eye(D.shape[1]) + D @ ZtZ) @ D @ ZtX

            # Work out the term to put into the kronecker product
            # K = Z_(k,j)'V^{-1}X(X'V^{-1})^{-1}L'
            K = ZkjtiVX @ np.linalg.inv(XtiVX) @ L.transpose()
            
            # Sum terms
            dS2dvechDk = dS2dvechDk + mat2vech3D(kron3D(K,K.transpose(0,2,1)))

        # Multiply by sigma^2
        dS2dvechDk = np.einsum('i,ijk->ijk',sigma2,dS2dvechDk)

        # Add to dS2deta
        dS2deta[:,DerivInds[k]:DerivInds[k+1]] = dS2dvechDk.reshape(dS2deta[:,DerivInds[k]:DerivInds[k+1]].shape)

    return(dS2deta)
コード例 #2
0
ファイル: tools3d.py プロジェクト: nicholst/BLMM
def get_covdldDk1Dk23D(k1,
                       k2,
                       nlevels,
                       nparams,
                       ZtZ,
                       DinvIplusZtZD,
                       invDupMatdict,
                       vec=False):

    # Sum of R_(k1, k2, i, j) kron R_(k1, k2, i, j) over i and j
    for i in np.arange(nlevels[k1]):

        for j in np.arange(nlevels[k2]):

            # Get the indices for the k1th factor jth level
            Ik1i = faclev_indices2D(k1, i, nlevels, nparams)
            Ik2j = faclev_indices2D(k2, j, nlevels, nparams)

            # Work out R_(k1, k2, i, j)
            Rk1k2ij = ZtZ[np.ix_(np.arange(ZtZ.shape[0]), Ik1i, Ik2j)] - (
                ZtZ[:, Ik1i, :] @ DinvIplusZtZD @ ZtZ[:, :, Ik2j])

            # Work out Rk1k2ij kron Rk1k2ij
            RkRt = kron3D(Rk1k2ij, Rk1k2ij)

            # Add together
            if (i == 0) and (j == 0):

                RkRtSum = RkRt

            else:

                RkRtSum = RkRtSum + RkRt

    # Multiply by duplication matrices and save
    if not vec:
        covdldDk1dldk2 = 1 / 2 * invDupMatdict[k1] @ RkRtSum @ invDupMatdict[
            k2].transpose()
    else:
        covdldDk1dldk2 = 1 / 2 * RkRtSum

    # Return the result
    return (covdldDk1dldk2)
コード例 #3
0
ファイル: tools3d.py プロジェクト: nicholst/BLMM
def get_covdldDkdsigma23D(k,
                          sigma2,
                          nlevels,
                          nparams,
                          ZtZ,
                          DinvIplusZtZD,
                          invDupMatdict,
                          vec=False):

    # Number of voxels
    nv = DinvIplusZtZD.shape[0]

    # Sum of R_(k, j) over j
    RkSum = np.zeros((nv, nparams[k], nparams[k]))

    for j in np.arange(nlevels[k]):

        # Get the indices for the kth factor jth level
        Ikj = faclev_indices2D(k, j, nlevels, nparams)

        # Work out R_(k, j)
        Rkj = ZtZ[np.ix_(np.arange(ZtZ.shape[0]), Ikj, Ikj)] - forceSym3D(
            ZtZ[:, Ikj, :] @ DinvIplusZtZD @ ZtZ[:, :, Ikj])

        # Add together
        RkSum = RkSum + Rkj

    # Multiply by duplication matrices and
    if not vec:
        covdldDdldsigma2 = np.einsum('i,ijk->ijk', 1 / (2 * sigma2),
                                     invDupMatdict[k] @ mat2vec3D(RkSum))
    else:
        covdldDdldsigma2 = np.einsum('i,ijk->ijk', 1 / (2 * sigma2),
                                     mat2vec3D(RkSum))

    return (covdldDdldsigma2)
コード例 #4
0
ファイル: tools3d.py プロジェクト: nicholst/BLMM
def get_dldDk3D(k,
                nlevels,
                nparams,
                ZtZ,
                Zte,
                sigma2,
                DinvIplusZtZD,
                reml=False,
                ZtX=0,
                XtX=0):

    # Number of voxels
    nv = Zte.shape[0]

    # Initalize the derivative to zeros
    dldDk = np.zeros((nv, nparams[k], nparams[k]))

    # For each level j we need to add a term
    for j in np.arange(nlevels[k]):

        # Get the indices for the kth factor jth level
        Ikj = faclev_indices2D(k, j, nlevels, nparams)

        # Get (the kj^th columns of Z)^T multiplied by Z
        Z_kjtZ = ZtZ[:, Ikj, :]
        Z_kjte = Zte[:, Ikj, :]

        # Get the first term of the derivative
        Z_kjtVinve = Z_kjte - (Z_kjtZ @ DinvIplusZtZD @ Zte)
        firstterm = np.einsum(
            'i,ijk->ijk', 1 / sigma2,
            forceSym3D(Z_kjtVinve @ Z_kjtVinve.transpose((0, 2, 1))))

        # Get (the kj^th columns of Z)^T multiplied by (the kj^th columns of Z)
        Z_kjtZ_kj = ZtZ[np.ix_(np.arange(ZtZ.shape[0]), Ikj, Ikj)]
        secondterm = forceSym3D(Z_kjtZ_kj) - forceSym3D(
            Z_kjtZ @ DinvIplusZtZD @ Z_kjtZ.transpose((0, 2, 1)))

        if j == 0:

            # Start a running sum over j
            dldDk = firstterm - secondterm

        else:

            # Add these to the running sum
            dldDk = dldDk + firstterm - secondterm

    if reml == True:

        invXtinvVX = np.linalg.inv(XtX - ZtX.transpose(
            (0, 2, 1)) @ DinvIplusZtZD @ ZtX)

        # For each level j we need to add a term
        for j in np.arange(nlevels[k]):

            # Get the indices for the kth factor jth level
            Ikj = faclev_indices2D(k, j, nlevels, nparams)

            Z_kjtZ = ZtZ[:, Ikj, :]
            Z_kjtX = ZtX[:, Ikj, :]

            Z_kjtinvVX = Z_kjtX - Z_kjtZ @ DinvIplusZtZD @ ZtX

            dldDk = dldDk + 0.5 * Z_kjtinvVX @ invXtinvVX @ Z_kjtinvVX.transpose(
                (0, 2, 1))

    # Halve the sum (the coefficient of a half was not included in the above)
    dldDk = forceSym3D(dldDk / 2)

    # Store it in the dictionary
    return (dldDk)
コード例 #5
0
ファイル: tools3d.py プロジェクト: nicholst/BLMM
def initDk3D(k, ZtZ, Zte, sigma2, nlevels, nparams, invDupMatdict):

    # Small check on sigma2
    if len(sigma2.shape) > 1:

        sigma2 = sigma2.reshape(sigma2.shape[0])

    # Initalize D to zeros
    invSig2ZteetZminusZtZ = np.zeros((Zte.shape[0], nparams[k], nparams[k]))

    # First we work out the derivative we require.
    for j in np.arange(nlevels[k]):

        Ikj = faclev_indices2D(k, j, nlevels, nparams)

        # Work out Z_(k, j)'Z_(k, j)
        ZkjtZkj = ZtZ[np.ix_(np.arange(ZtZ.shape[0]), Ikj, Ikj)]

        # Work out Z_(k,j)'e
        Zkjte = Zte[:, Ikj, :]

        if j == 0:

            # Add first \sigma^{-2}Z'ee'Z - Z_(k,j)'Z_(k,j)
            invSig2ZteetZminusZtZ = np.einsum(
                'i,ijk->ijk', 1 / sigma2,
                (Zkjte @ Zkjte.transpose(0, 2, 1))) - ZkjtZkj

        else:

            # Add next \sigma^{-2}Z'ee'Z - Z_(k,j)'Z_(k,j)
            invSig2ZteetZminusZtZ = invSig2ZteetZminusZtZ + np.einsum(
                'i,ijk->ijk', 1 / sigma2,
                (Zkjte @ Zkjte.transpose(0, 2, 1))) - ZkjtZkj

    # Second we need to work out the double sum of Z_(k,j)'Z_(k,j)
    for j in np.arange(nlevels[k]):

        for i in np.arange(nlevels[k]):

            Iki = faclev_indices2D(k, i, nlevels, nparams)
            Ikj = faclev_indices2D(k, j, nlevels, nparams)

            # Work out Z_(k, j)'Z_(k, j)
            ZkitZkj = ZtZ[np.ix_(np.arange(ZtZ.shape[0]), Iki, Ikj)]

            if j == 0 and i == 0:

                # Add first Z_(k,j)'Z_(k,j) kron Z_(k,j)'Z_(k,j)
                ZtZkronZtZ = kron3D(ZkitZkj, ZkitZkj.transpose(0, 2, 1))

            else:

                # Add next Z_(k,j)'Z_(k,j) kron Z_(k,j)'Z_(k,j)
                ZtZkronZtZ = ZtZkronZtZ + kron3D(ZkitZkj,
                                                 ZkitZkj.transpose(0, 2, 1))

    # Work out information matrix
    infoMat = invDupMatdict[k] @ ZtZkronZtZ @ invDupMatdict[k].transpose()

    # Work out the final term.
    Dkest = vech2mat3D(
        np.linalg.inv(infoMat) @ mat2vech3D(invSig2ZteetZminusZtZ))

    return (Dkest)