<s> '''<STR_LIT>''' <EOL> import numpy as np <EOL> import OptimizerForHDPFullVarModel as OptimHDP <EOL> from . . AllocModel import AllocModel <EOL> from bnpy . suffstats import SuffStatBag <EOL> from ... util import NumericUtil <EOL> from ... util import digamma , gammaln <EOL> from ... util import EPS , np2flatstr <EOL> import logging <EOL> Log = logging . getLogger ( '<STR_LIT>' ) <EOL> class HDPRelAssortModel ( AllocModel ) : <EOL> def __init__ ( self , inferType , priorDict = None ) : <EOL> if inferType == "<STR_LIT>" : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> self . inferType = inferType <EOL> self . K = <NUM_LIT:0> <EOL> self . set_prior ( priorDict ) <EOL> self . epsilon = <NUM_LIT> <EOL> def set_prior ( self , PriorParamDict ) : <EOL> self . alpha0 = PriorParamDict [ '<STR_LIT>' ] <EOL> self . gamma = PriorParamDict [ '<STR_LIT>' ] <EOL> def set_helper_params ( self ) : <EOL> '''<STR_LIT>''' <EOL> E = OptimHDP . _calcExpectations ( self . U1 , self . U0 ) <EOL> self . Ebeta = E [ '<STR_LIT>' ] <EOL> self . Elogv = E [ '<STR_LIT>' ] <EOL> self . Elog1mv = E [ '<STR_LIT>' ] <EOL> self . ElogEps1 = np . log ( self . epsilon ) <EOL> self . ElogEps0 = np . log ( <NUM_LIT:1> - self . epsilon ) <EOL> self . ElogTheta = digamma ( self . theta ) - digamma ( np . sum ( self . theta , axis = <NUM_LIT:1> ) ) [ : , np . newaxis ] <EOL> def get_keys_for_memoized_local_params ( self ) : <EOL> '''<STR_LIT>''' <EOL> return [ '<STR_LIT>' ] <EOL> def calc_local_params ( self , Data , LP , <EOL> nCoordAscentItersLP = <NUM_LIT:20> , <EOL> convThrLP = <NUM_LIT> , doOnlySomeDocsLP = False , ** kwargs ) : <EOL> '''<STR_LIT>''' <EOL> LP [ '<STR_LIT>' ] = np . zeros ( ( Data . nEdgeTotal , self . K ) ) <EOL> LP [ '<STR_LIT>' ] = np . zeros ( Data . nEdgeTotal ) <EOL> LP [ '<STR_LIT>' ] = np . zeros ( ( Data . nEdgeTotal , self . K ) ) <EOL> LP [ '<STR_LIT>' ] = np . zeros ( ( Data . nEdgeTotal , self . K ) ) <EOL> E_logPiSumD = np . sum ( self . ElogTheta , axis = <NUM_LIT:1> ) <EOL> E_logEdgeLik = LP [ '<STR_LIT>' ] <EOL> E_logEdgeEps = LP [ '<STR_LIT>' ] <EOL> for e in xrange ( Data . nEdgeTotal ) : <EOL> row_id = Data . edges [ e , <NUM_LIT:0> ] <EOL> col_id = Data . edges [ e , <NUM_LIT:1> ] <EOL> LP [ '<STR_LIT>' ] [ e , : ] = self . ElogTheta [ row_id , : self . K ] + self . ElogTheta [ col_id , : self . K ] + E_logEdgeLik [ e , : ] <EOL> LP [ '<STR_LIT>' ] [ e ] = np . sum ( np . exp ( self . ElogTheta [ row_id , : self . K ] + self . ElogTheta [ col_id , : self . K ] + E_logEdgeEps [ e ] ) + np . exp ( self . ElogTheta [ row_id , : self . K ] + self . ElogTheta [ col_id , : self . K ] ) * ( np . exp ( E_logEdgeLik [ e , : ] ) - np . exp ( E_logEdgeEps [ e ] ) ) ) <EOL> LP [ '<STR_LIT>' ] [ e , : ] = self . ElogTheta [ row_id , : self . K ] <EOL> LP [ '<STR_LIT>' ] [ e , : ] = self . ElogTheta [ col_id , : self . K ] <EOL> expEloglik = LP [ '<STR_LIT>' ] <EOL> expEloglik -= expEloglik . max ( axis = <NUM_LIT:1> ) [ : , np . newaxis ] <EOL> NumericUtil . inplaceExpAndNormalizeRows ( expEloglik ) <EOL> LP [ '<STR_LIT>' ] = expEloglik <EOL> LP [ '<STR_LIT>' ] = E_logPiSumD <EOL> LP [ '<STR_LIT>' ] = np . sum ( self . ElogTheta , axis = <NUM_LIT:0> ) <EOL> LP [ '<STR_LIT>' ] = np . sum ( LP [ '<STR_LIT>' ] , axis = <NUM_LIT:1> ) <EOL> LP [ '<STR_LIT>' ] = np . sum ( LP [ '<STR_LIT>' ] , axis = <NUM_LIT:1> ) <EOL> return LP <EOL> def calc_ElogPi ( self , LP ) : <EOL> '''<STR_LIT>''' <EOL> alph = LP [ '<STR_LIT>' ] <EOL> LP [ '<STR_LIT>' ] = digamma ( alph ) - digamma ( alph . sum ( axis = <NUM_LIT:1> ) ) [ : , np . newaxis ] <EOL> return LP <EOL> def get_edge_variational ( self , Data , LP ) : <EOL> '''<STR_LIT>''' <EOL> ev = LP [ '<STR_LIT>' ] <EOL> K = ev . shape [ <NUM_LIT:1> ] <EOL> ev [ : ] = LP [ '<STR_LIT>' ] <EOL> ElogPi = LP [ '<STR_LIT>' ] [ : , : K ] <EOL> for d in xrange ( Data . nDoc ) : <EOL> ev [ Data . doc_range [ d , <NUM_LIT:0> ] : Data . doc_range [ d , <NUM_LIT:1> ] , : ] += ElogPi [ d , : ] <EOL> NumericUtil . inplaceExpAndNormalizeRows ( ev ) <EOL> assert np . allclose ( LP [ '<STR_LIT>' ] . sum ( axis = <NUM_LIT:1> ) , <NUM_LIT:1> ) <EOL> return LP <EOL> def get_global_suff_stats ( self , Data , LP , doPrecompEntropy = False , <EOL> doPrecompMergeEntropy = False , <EOL> mPairIDs = None ) : <EOL> '''<STR_LIT>''' <EOL> E , K = LP [ '<STR_LIT>' ] . shape <EOL> N = Data . nNodeTotal <EOL> SS = SuffStatBag ( K = K , D = N ) <EOL> node_ss = np . zeros ( ( N , K ) ) <EOL> node_z_ss = np . zeros ( ( N , K ) ) <EOL> node_offset = np . zeros ( ( E , K ) ) <EOL> ev = LP [ '<STR_LIT>' ] <EOL> edgeEps = LP [ '<STR_LIT>' ] <EOL> for e in xrange ( E ) : <EOL> ii = Data . edges [ e , <NUM_LIT:0> ] <EOL> jj = Data . edges [ e , <NUM_LIT:1> ] <EOL> node_ss [ ii , : ] += ev [ e ] <EOL> node_ss [ jj , : ] += ev [ e ] <EOL> node_z_ss [ ii , : ] += LP [ '<STR_LIT>' ] [ e ] <EOL> SS . setField ( '<STR_LIT>' , N , dims = None ) <EOL> SS . setField ( '<STR_LIT>' , E , dims = None ) <EOL> SS . setField ( '<STR_LIT>' , node_ss , dims = ( '<STR_LIT:D>' , '<STR_LIT>' ) ) <EOL> SS . setField ( '<STR_LIT>' , node_z_ss , dims = ( '<STR_LIT:D>' , '<STR_LIT>' ) ) <EOL> SS . setField ( '<STR_LIT>' , LP [ '<STR_LIT>' ] [ : self . K ] , dims = '<STR_LIT>' ) <EOL> SS . setField ( '<STR_LIT>' , LP [ '<STR_LIT>' ] [ - <NUM_LIT:1> ] , dims = None ) <EOL> return SS <EOL> def update_global_params_VB ( self , SS , ** kwargs ) : <EOL> '''<STR_LIT>''' <EOL> self . K = SS . K <EOL> u = self . _estimate_u ( SS ) <EOL> self . U1 = u [ : self . K ] <EOL> self . U0 = u [ self . K : ] <EOL> theta = self . _estimate_theta ( SS ) <EOL> self . theta = theta <EOL> self . set_helper_params ( ) <EOL> def update_global_params_soVB ( self , SS , rho , ** kwargs ) : <EOL> assert self . K == SS . K <EOL> u = self . _estimate_u ( SS ) <EOL> self . U1 = rho * u [ : self . K ] + ( <NUM_LIT:1> - rho ) * self . U1 <EOL> self . U0 = rho * u [ self . K : ] + ( <NUM_LIT:1> - rho ) * self . U0 <EOL> self . set_helper_params ( ) <EOL> def _estimate_theta ( self , SS , ** kwargs ) : <EOL> '''<STR_LIT>''' <EOL> theta = np . zeros ( ( SS . nNodeTotal , SS . K ) ) <EOL> theta += SS . node_ss + SS . node_z_ss + ( self . alpha0 * self . Ebeta ) <EOL> return theta <EOL> def _estimate_u ( self , SS , ** kwargs ) : <EOL> '''<STR_LIT>''' <EOL> if hasattr ( self , '<STR_LIT>' ) and self . U1 . size == self . K : <EOL> initU = np . hstack ( [ self . U1 , self . U0 ] ) <EOL> else : <EOL> initU = np . hstack ( [ np . ones ( self . K ) , self . alpha0 * np . ones ( self . K ) ] ) <EOL> sumLogPi = np . hstack ( [ SS . sumLogPiActive , SS . sumLogPiUnused ] ) <EOL> try : <EOL> u , fofu , Info = OptimHDP . estimate_u_multiple_tries ( sumLogPi = sumLogPi , <EOL> nDoc = SS . nDoc , <EOL> gamma = self . gamma , alpha0 = self . alpha0 , <EOL> initU = initU ) <EOL> except ValueError as error : <EOL> if str ( error ) . count ( '<STR_LIT>' ) == <NUM_LIT:0> : <EOL> raise error <EOL> if hasattr ( self , '<STR_LIT>' ) and self . U1 . size == self . K : <EOL> Log . error ( '<STR_LIT>' + str ( error ) ) <EOL> return <EOL> else : <EOL> Log . error ( '<STR_LIT>' + str ( error ) ) <EOL> u = initU <EOL> return u <EOL> def set_global_params ( self , hmodel = None , <EOL> U1 = None , U0 = None , <EOL> K = <NUM_LIT:0> , beta = None , topic_prior = None , <EOL> Ebeta = None , EbetaLeftover = None , theta = None , ** kwargs ) : <EOL> if hmodel is not None : <EOL> self . K = hmodel . allocModel . K <EOL> self . U1 = hmodel . allocModel . U1 <EOL> self . U0 = hmodel . allocModel . U0 <EOL> self . set_helper_params ( ) <EOL> return <EOL> if U1 is not None and U0 is not None : <EOL> self . U1 = U1 <EOL> self . U0 = U0 <EOL> self . K = U1 . size <EOL> self . set_helper_params ( ) <EOL> return <EOL> if Ebeta is not None and EbetaLeftover is not None : <EOL> Ebeta = np . squeeze ( Ebeta ) <EOL> EbetaLeftover = np . squeeze ( EbetaLeftover ) <EOL> beta = np . hstack ( [ Ebeta , EbetaLeftover ] ) <EOL> self . K = beta . size - <NUM_LIT:1> <EOL> elif beta is not None : <EOL> assert beta . size == K <EOL> beta = np . hstack ( [ beta , np . min ( beta ) / <NUM_LIT> ] ) <EOL> beta = beta / np . sum ( beta ) <EOL> self . K = beta . size - <NUM_LIT:1> <EOL> else : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> assert beta . size == self . K + <NUM_LIT:1> <EOL> assert abs ( np . sum ( beta ) - <NUM_LIT:1.0> ) < <NUM_LIT> <EOL> vMean = OptimHDP . beta2v ( beta ) <EOL> vMass = np . maximum ( <NUM_LIT:1.> / vMean , self . alpha0 / ( <NUM_LIT:1.> - vMean ) ) <EOL> self . U1 = vMass * vMean <EOL> self . U0 = vMass * ( <NUM_LIT:1> - vMean ) <EOL> assert np . all ( self . U1 >= <NUM_LIT:1.0> - <NUM_LIT> ) <EOL> assert np . all ( self . U0 >= self . alpha0 - <NUM_LIT> ) <EOL> assert self . U1 . size == self . K <EOL> assert self . U0 . size == self . K <EOL> if theta is not None and beta is not None : <EOL> self . theta = theta <EOL> else : <EOL> self . theta = np . ones ( ( self . nNodeTotal , self . K + <NUM_LIT:1> ) ) <EOL> self . set_helper_params ( ) <EOL> def calc_evidence ( self , Data , SS , LP ) : <EOL> '''<STR_LIT>''' <EOL> E_logpV = self . E_logpV ( ) <EOL> E_logqV = self . E_logqV ( ) <EOL> E_logpPi = self . E_logpPi ( SS ) <EOL> E_logqPi = self . E_logqPi ( LP ) <EOL> E_logpZ = self . E_logpZ ( Data , LP ) <EOL> E_logqZ = self . E_logqZ ( Data , LP ) <EOL> elbo = E_logpPi - E_logqPi + E_logpZ - E_logqZ + E_logpV - E_logqV <EOL> return elbo <EOL> def E_logpZ ( self , Data , LP ) : <EOL> '''<STR_LIT>''' <EOL> E_pi_i_sum = np . sum ( LP [ '<STR_LIT>' ] , axis = <NUM_LIT:1> ) <EOL> E_pi_j_sum = np . sum ( LP [ '<STR_LIT>' ] , axis = <NUM_LIT:1> ) <EOL> E_logpZ = ( LP [ '<STR_LIT>' ] + np . exp ( LP [ '<STR_LIT>' ] + LP [ '<STR_LIT>' ] [ : , np . newaxis ] ) * ( np . exp ( E_pi_j_sum [ : , np . newaxis ] ) - np . exp ( LP [ '<STR_LIT>' ] ) ) ) * LP [ '<STR_LIT>' ] <EOL> E_logpZ += ( LP [ '<STR_LIT>' ] + np . exp ( LP [ '<STR_LIT>' ] + LP [ '<STR_LIT>' ] [ : , np . newaxis ] ) * ( np . exp ( E_pi_i_sum [ : , np . newaxis ] ) - np . exp ( LP [ '<STR_LIT>' ] ) ) ) * LP [ '<STR_LIT>' ] <EOL> return np . sum ( E_logpZ ) <EOL> def E_logqZ ( self , Data , LP ) : <EOL> '''<STR_LIT>''' <EOL> E_logqZ = np . sum ( LP [ '<STR_LIT>' ] , axis = <NUM_LIT:1> ) + np . sum ( LP [ '<STR_LIT>' ] , axis = <NUM_LIT:1> ) + LP [ '<STR_LIT>' ] * ( <NUM_LIT:1> - np . sum ( LP [ '<STR_LIT>' ] , axis = <NUM_LIT:1> ) ) + np . sum ( LP [ '<STR_LIT>' ] * LP [ '<STR_LIT>' ] - np . log ( LP [ '<STR_LIT>' ] [ : , np . newaxis ] ) ) <EOL> return np . sum ( E_logqZ ) <EOL> def E_logqZ_memo_terms_for_merge ( self , Data , LP , mPairIDs = None ) : <EOL> '''<STR_LIT>''' <EOL> wv = LP [ '<STR_LIT>' ] <EOL> wv += EPS <EOL> if mPairIDs is None : <EOL> ElogqZMat = NumericUtil . calcRlogRdotv_allpairs ( wv , Data . word_count ) <EOL> else : <EOL> ElogqZMat = NumericUtil . calcRlogRdotv_specificpairs ( wv , <EOL> Data . word_count , mPairIDs ) <EOL> return ElogqZMat <EOL> def E_logpPi ( self , SS ) : <EOL> '''<STR_LIT>''' <EOL> K = SS . K <EOL> kvec = K + <NUM_LIT:1> - np . arange ( <NUM_LIT:1> , K + <NUM_LIT:1> ) <EOL> logDirNormC = gammaln ( self . gamma ) + ( K + <NUM_LIT:1> ) * np . log ( self . gamma ) <EOL> logDirNormC += np . sum ( self . Elogv ) + np . inner ( kvec , self . Elog1mv ) <EOL> sumLogPi = np . hstack ( [ SS . sumLogPiActive , SS . sumLogPiUnused ] ) <EOL> logDirPDF = np . inner ( self . gamma * self . Ebeta - <NUM_LIT:1.> , sumLogPi ) <EOL> return ( SS . nNodeTotal * logDirNormC ) + logDirPDF <EOL> def E_logqPi ( self , LP ) : <EOL> '''<STR_LIT>''' <EOL> alph = self . theta <EOL> logDirNormC = gammaln ( alph . sum ( axis = <NUM_LIT:1> ) ) - np . sum ( gammaln ( alph ) , axis = <NUM_LIT:1> ) <EOL> logDirPDF = np . sum ( ( alph - <NUM_LIT:1.> ) * self . ElogTheta ) <EOL> return np . sum ( logDirNormC ) + logDirPDF <EOL> def E_logqPi_Memoized_from_LP ( self , LP ) : <EOL> '''<STR_LIT>''' <EOL> alph = LP [ '<STR_LIT>' ] <EOL> logDirNormC = np . sum ( gammaln ( alph . sum ( axis = <NUM_LIT:1> ) ) ) <EOL> piEntropyVec = np . sum ( ( alph - <NUM_LIT:1.> ) * LP [ '<STR_LIT>' ] , axis = <NUM_LIT:0> ) - np . sum ( gammaln ( alph ) , axis = <NUM_LIT:0> ) <EOL> return logDirNormC , piEntropyVec [ : - <NUM_LIT:1> ] , piEntropyVec [ - <NUM_LIT:1> ] <EOL> def E_logpV ( self ) : <EOL> logBetaNormC = gammaln ( self . alpha0 + <NUM_LIT:1.> ) - gammaln ( self . alpha0 ) <EOL> logBetaPDF = ( self . alpha0 - <NUM_LIT:1.> ) * np . sum ( self . Elog1mv ) <EOL> return self . K * logBetaNormC + logBetaPDF <EOL> def E_logqV ( self ) : <EOL> logBetaNormC = gammaln ( self . U1 + self . U0 ) - gammaln ( self . U0 ) - gammaln ( self . U1 ) <EOL> logBetaPDF = np . inner ( self . U1 - <NUM_LIT:1.> , self . Elogv ) + np . inner ( self . U0 - <NUM_LIT:1.> , self . Elog1mv ) <EOL> return np . sum ( logBetaNormC ) + logBetaPDF <EOL> def memo_elbo_terms_for_merge ( self , LP ) : <EOL> '''<STR_LIT>''' <EOL> CMat = LP [ "<STR_LIT>" ] <EOL> alph = LP [ "<STR_LIT>" ] <EOL> digammaPerDocSum = digamma ( alph . sum ( axis = <NUM_LIT:1> ) ) [ : , np . newaxis ] <EOL> alph = alph [ : , : - <NUM_LIT:1> ] <EOL> ElogpZMat = np . zeros ( ( self . K , self . K ) ) <EOL> sumLogPiMat = np . zeros ( ( self . K , self . K ) ) <EOL> ElogqPiMat = np . zeros ( ( self . K , self . K ) ) <EOL> for jj in range ( self . K ) : <EOL> M = self . K - jj - <NUM_LIT:1> <EOL> mergeAlph = alph [ : , jj ] [ : , np . newaxis ] + alph [ : , jj + <NUM_LIT:1> : ] <EOL> mergeElogPi = digamma ( mergeAlph ) - digammaPerDocSum <EOL> assert mergeElogPi . shape [ <NUM_LIT:1> ] == M <EOL> mergeCMat = CMat [ : , jj ] [ : , np . newaxis ] + CMat [ : , jj + <NUM_LIT:1> : ] <EOL> ElogpZMat [ jj , jj + <NUM_LIT:1> : ] = np . sum ( mergeCMat * mergeElogPi , axis = <NUM_LIT:0> ) <EOL> sumLogPiMat [ jj , jj + <NUM_LIT:1> : ] = np . sum ( mergeElogPi , axis = <NUM_LIT:0> ) <EOL> curElogqPiMat = np . sum ( ( mergeAlph - <NUM_LIT:1.> ) * mergeElogPi , axis = <NUM_LIT:0> ) - np . sum ( gammaln ( mergeAlph ) , axis = <NUM_LIT:0> ) <EOL> assert curElogqPiMat . size == M <EOL> ElogqPiMat [ jj , jj + <NUM_LIT:1> : ] = curElogqPiMat <EOL> return ElogpZMat , sumLogPiMat , ElogqPiMat <EOL> def get_info_string ( self ) : <EOL> '''<STR_LIT>''' <EOL> s = '<STR_LIT>' <EOL> return s % ( self . K , self . alpha0 , self . gamma ) <EOL> def to_dict ( self ) : <EOL> return dict ( U1 = self . U1 , U0 = self . U0 ) <EOL> def from_dict ( self , Dict ) : <EOL> self . inferType = Dict [ '<STR_LIT>' ] <EOL> self . K = Dict [ '<STR_LIT>' ] <EOL> self . U1 = Dict [ '<STR_LIT>' ] <EOL> self . U0 = Dict [ '<STR_LIT>' ] <EOL> self . set_helper_params ( ) <EOL> def get_prior_dict ( self ) : <EOL> return dict ( K = self . K , alpha0 = self . alpha0 , gamma = self . gamma ) </s>
