def expectedEmissionStats( self, t, ys, alphas, betas, conditionOnY=True ): # E[ x_t * x_t^T ], E[ y_t * x_t^T ] and E[ y_t * y_t^T ] # Find the expected sufficient statistic for N( y_t, x_t | Y ) J_x, h_x, _ = np.add( alphas[ t ], betas[ t ] ) if( conditionOnY == False ): J11 = self.J1Emiss J12 = -self._hy J22 = self.Jy + J_x D = J11.shape[ 0 ] J = np.block( [ [ J11, J12 ], [ J12.T, J22 ] ] ) h = np.hstack( ( np.zeros( D ), h_x ) ) # This is a block matrix with block E[ y_t * y_t^T ], E[ y_t * x_t^T ] # and E[ x_t * x_t^T ] E, _ = Normal.expectedSufficientStats( nat_params=( -0.5 * J, h ) ) Eyt_yt, Eyt_xt, Ext_xt = toBlocks( E, D ) else: Ext_xt, E_xt = Normal.expectedSufficientStats( nat_params=( -0.5 * J_x, h_x ) ) Eyt_yt = np.einsum( 'mi,mj->ij', ys[ :, t ], ys[ :, t ] ) Eyt_xt = np.einsum( 'mi,j->ij', ys[ :, t ], E_xt ) return Eyt_yt, Eyt_xt, Ext_xt
def expectedTransitionStatsBlock( self, t, alphas, betas, ys=None, u=None ): # E[ x_t * x_t^T ], E[ x_t+1 * x_t^T ] and E[ x_t+1 * x_t+1^T ] # Find the natural parameters for P( x_t+1, x_t | Y ) J11, J12, J22, h1, h2, _ = self.childParentJoint( t, alphas, betas, ys=ys, u=u ) J = np.block( [ [ J11, J12 ], [ J12.T, J22 ] ] ) h = np.hstack( ( h1, h2 ) ) # The first expected sufficient statistic for N( x_t+1, x_t | Y ) will # be a block matrix with blocks E[ x_t+1 * x_t+1^T ], E[ x_t+1 * x_t^T ] # and E[ x_t * x_t^T ] E, _ = Normal.expectedSufficientStats( nat_params=( -0.5 * J, h ) ) D = h1.shape[ 0 ] Ext1_xt1, Ext1_xt, Ext_xt = toBlocks( E, D ) return Ext1_xt1, Ext1_xt, Ext_xt
def expectedInitialStats( self, alphas, betas ): # E[ x_0 * x_0 ], E[ x_0 ] J, h, _ = np.add( alphas[ 0 ], betas[ 0 ] ) return Normal.expectedSufficientStats( nat_params=( -0.5 * J, h ) )