#NEWLINE# def make_gmm_funcs( num_components , D ) : #NEWLINE# #INDENT# parser = WeightsParser ( ) #NEWLINE# parser . add_shape ( 'log proportions' , num_components ) #NEWLINE# parser . add_shape ( 'means' , ( num_components , D ) ) #NEWLINE# parser . add_shape ( 'lower triangles' , ( num_components , D , D ) ) #NEWLINE# parser . add_shape ( 'log diagonals' , ( num_components , D ) ) #NEWLINE# def unpack_params( params ) : #NEWLINE# #INDENT# 'Unpacks parameter vector into the proportions, means and covariances\n        of each mixture component.  The covariance matrices are parametrized by\n        their Cholesky decompositions.' #NEWLINE# log_proportions = parser . get ( params , 'log proportions' ) #NEWLINE# normalized_log_proportions = ( log_proportions - logsumexp ( log_proportions ) ) #NEWLINE# means = parser . get ( params , 'means' ) #NEWLINE# lower_tris = np . tril ( parser . get ( params , 'lower triangles' ) , k = ( - 1 ) ) #NEWLINE# diag_chols = np . exp ( parser . get ( params , 'log diagonals' ) ) #NEWLINE# chols = ( lower_tris + np . make_diagonal ( diag_chols , axis1 = ( - 1 ) , axis2 = ( - 2 ) ) ) #NEWLINE# return ( normalized_log_proportions , means , chols ) #NEWLINE# #UNINDENT# def log_marginal_likelihood( params , data ) : #NEWLINE# #INDENT# cluster_lls = [ ] #NEWLINE# for ( log_proportion , mean , chol ) in zip ( * unpack_params ( params ) ) : #NEWLINE# #INDENT# cov = ( np . dot ( chol . T , chol ) + ( 1e-06 * np . eye ( D ) ) ) #NEWLINE# cluster_log_likelihood = ( log_proportion + mvn . logpdf ( data , mean , cov ) ) #NEWLINE# cluster_lls . append ( np . expand_dims ( cluster_log_likelihood , axis = 0 ) ) #NEWLINE# #UNINDENT# cluster_lls = np . concatenate ( cluster_lls , axis = 0 ) #NEWLINE# return np . sum ( logsumexp ( cluster_lls , axis = 0 ) ) #NEWLINE# #UNINDENT# return ( parser . num_weights , log_marginal_likelihood , unpack_params )