예제 #1
0
 def calc_local_params(self, Data, LP, **kwargs):
   ''' Calculate local parameters for each data item and each component.    
       This is part of the E-step.
       
       Args
       -------
       Data : bnpy data object with Data.nObs observations
       LP : local param dict with fields
             E_log_soft_ev : Data.nObs x K array
                 E_log_soft_ev[n,k] = log p(data obs n | comp k)
       
       Returns
       -------
       LP : local param dict with fields
             resp : Data.nObs x K array whose rows sum to one
             resp[n,k] = posterior responsibility that comp. k has for data n                
   '''
   lpr = LP['E_log_soft_ev']
   lpr += self.Elogw
   # Calculate exp in numerically stable manner (first subtract the max)
   #  perform this in-place so no new allocations occur
   NumericUtil.inplaceExpAndNormalizeRows(lpr)
   LP['resp'] = lpr
   assert np.allclose(lpr.sum(axis=1), 1)
   return LP
예제 #2
0
def calcLocalParams(Data, LP, Elogbeta=None, nnzPerRowLP=None, **kwargs):
    ''' Compute local parameters for each data item.

    Parameters
    -------
    Data : bnpy.data.DataObj subclass

    LP : dict
        Local parameters as key-value string/array pairs
        * E_log_soft_ev : 2D array, N x K
            E_log_soft_ev[n,k] = log p(data obs n | comp k)

    Returns
    -------
    LP : dict
        Local parameters, with updated fields
        * resp : 2D array, size N x K array
            Posterior responsibility each comp has for each item
            resp[n, k] = p(z[n] = k | x[n])
    '''
    lpr = LP['E_log_soft_ev']
    lpr += Elogbeta
    K = LP['E_log_soft_ev'].shape[1]
    if nnzPerRowLP and (nnzPerRowLP > 0 and nnzPerRowLP < K):
        # SPARSE Assignments
        LP['spR'] = sparsifyLogResp(lpr, nnzPerRow=nnzPerRowLP)
        assert np.all(np.isfinite(LP['spR'].data))
        LP['nnzPerRow'] = nnzPerRowLP
    else:
        # DENSE Assignments
        # Calculate exp in numerically stable manner (first subtract the max)
        #  perform this in-place so no new allocations occur
        NumericUtil.inplaceExpAndNormalizeRows(lpr)
        LP['resp'] = lpr
    return LP
예제 #3
0
    def calc_local_params(self, Data, LP, nnzPerRowLP=0, **kwargs):
        ''' Compute local parameters for each data item and component.

        Parameters
        -------
        Data : bnpy.data.DataObj subclass

        LP : dict
            Local parameters as key-value string/array pairs
            * E_log_soft_ev : 2D array, N x K
                E_log_soft_ev[n,k] = log p(data obs n | comp k)

        Returns
        -------
        LP : dict
            Local parameters, with updated fields
            * resp : 2D array, size N x K array
                Posterior responsibility each comp has for each item
                resp[n, k] = p(z[n] = k | x[n])
        '''
        lpr = LP['E_log_soft_ev']
        K = lpr.shape[1]
        if self.inferType.count('EM') > 0:
            # Using point estimates, for EM algorithm
            lpr += np.log(self.w + 1e-100)
            if nnzPerRowLP and (nnzPerRowLP > 0 and nnzPerRowLP < K):
                # SPARSE Assignments
                LP['nnzPerRow'] = nnzPerRowLP
                LP['spR'] = sparsifyLogResp(lpr, nnzPerRow=nnzPerRowLP)
                assert np.all(np.isfinite(LP['spR'].data))
            else:
                lprPerItem = logsumexp(lpr, axis=1)
                lpr -= lprPerItem[:, np.newaxis]
                np.exp(lpr, out=lpr)
                LP['resp'] = lpr
                LP['evidence'] = lprPerItem.sum()
        else:
            # Full Bayesian approach, for VB or GS algorithms
            lpr += self.Elogw
            if nnzPerRowLP and (nnzPerRowLP > 0 and nnzPerRowLP < K):
                # SPARSE Assignments
                LP['nnzPerRow'] = nnzPerRowLP
                LP['spR'] = sparsifyLogResp(lpr, nnzPerRow=nnzPerRowLP)
                assert np.all(np.isfinite(LP['spR'].data))
            else:
                # DENSE Assignments
                # Calculate exp in numerically safe way,
                # in-place so no new allocations occur
                NumericUtil.inplaceExpAndNormalizeRows(lpr)
                LP['resp'] = lpr
                assert np.allclose(lpr.sum(axis=1), 1)
        return LP
def restrictedLocalStep_DPMixtureModel(Dslice=None,
                                       sumRespVec=None,
                                       LPkwargs=dict(),
                                       xObsModel=None,
                                       xPiVec=None,
                                       xInitSS=None,
                                       doBuildOnInit=False,
                                       nUpdateSteps=50,
                                       convThr=0.1,
                                       xPiPrior=1.0,
                                       logFunc=None,
                                       **kwargs):
    ''' Perform restricted local step on provided dataset.

    Returns
    -------
    xLPslice : dict with updated local parameters
        Obeys restriction that sum(resp, axis=1) equals sumRespVec
    '''
    if xInitSS is None:
        xWholeSS = None
    else:
        xWholeSS = xInitSS.copy()
    for step in range(nUpdateSteps):
        # Compute conditional likelihoods for every data atom
        xLPslice = xObsModel.calc_local_params(Dslice, **LPkwargs)
        assert 'E_log_soft_ev' in xLPslice
        xresp = xLPslice['E_log_soft_ev']
        xresp += np.log(xPiVec)[np.newaxis, :]
        # Calculate exp in numerically stable manner (first subtract the max)
        #  perform this in-place so no new allocations occur
        NumericUtil.inplaceExpAndNormalizeRows(xresp)
        # Enforce sum restriction
        xresp *= sumRespVec[:, np.newaxis]
        np.maximum(xresp, 1e-100, out=xresp)

        isLastStep = step == nUpdateSteps - 1
        if not isLastStep:
            xSS = xObsModel.calcSummaryStats(Dslice, None, dict(resp=xresp))
            # Increment
            if doBuildOnInit:
                xSS.setUIDs(xWholeSS.uids)
                xWholeSS += xSS
            else:
                xWholeSS = xSS
            # Global step
            xObsModel.update_global_params(xWholeSS)
            Nvec = xWholeSS.getCountVec()
            xPiVec = Nvec + xPiPrior
            # Decrement stats
            if doBuildOnInit:
                xWholeSS -= xSS
            # Assess early stopping
            if step > 0:
                thr = np.sum(np.abs(prevCountVec - xSS.getCountVec()))
                if thr < convThr:
                    break
            prevCountVec = xSS.getCountVec()
    if logFunc:
        msg = "restrictedLocalStep_DPMixtureModel"
        msg += " stopped after %3d of %d iters. thr=%.4f" % (step,
                                                             nUpdateSteps, thr)
        logFunc(msg)
    xLPslice['resp'] = xresp
    del xLPslice['E_log_soft_ev']  # delete since we did inplace ops on it
    return xLPslice