def m_step(self): '''Perform the M-step. This step updates self.mixture_weights self.component_distributions ''' # test if the sum of the summed expected_component_counts is roughly equal to the total amount of observations sum_obs_counts = log_add_list(self.expected_component_counts.values()) print("Sum of expected component counts: {}".format(exp(sum_obs_counts)))
def m_step(self): '''Perform the M-step. This step updates self.mixture_weights self.component_distributions ''' sum_obs_counts = log_add_list(self.expected_component_counts.values()) for i in range(self.num_components): self.mixture_weights[i] = self.expected_component_counts[i] - sum_obs_counts self.component_distributions[i] = GeometricDistribution(exp(self.expected_component_counts[i] - (log_add(self.expected_component_counts[i], self.expected_observation_counts[i])))) self.expected_component_counts[i] = -float("inf") self.expected_observation_counts[i] = -float("inf")
def m_step(self): '''Perform the M-step. This step updates self.mixture_weights self.component_distributions ''' # test if the sum of the summed expected_component_counts is roughly equal to the total amount of observations sum_obs_counts = log_add_list(self.expected_component_counts.values()) print("Sum of expected component counts: {}".format(exp(sum_obs_counts))) for i in range(self.num_components): self.mixture_weights[i] = self.expected_component_counts[i] - sum_obs_counts self.component_distributions[i] = GeometricDistribution(exp(self.expected_component_counts[i] - (log_add(self.expected_component_counts[i], self.expected_observation_counts[i])))) self.expected_component_counts[i] = -float("inf") self.expected_observation_counts[i] = -float("inf")
def e_step(self, observation): '''Perform the E-step on a single obervation. That is, compute the posterior of mixture components and add the expected occurrence of each component to the running totals self.log_likelihood , self.expected_component_counts , and self.expected_observation_counts :param observation: The observation ''' # Compute the joint probabilities p(x, c) joint_logprobs = list() for component in range(self.num_components): comp_dist = self.component_distributions[component] logprob = self.mixture_weights[component] + comp_dist.log_prob(observation) joint_logprobs.append(logprob) # Marginal probability p(x) = p(x, c_1) + ... + p(x, c_n) marginal_logprob = log_add_list(joint_logprobs) # Update log likelihood: log p(x_1, x_2, ...) = log p(x_1) + log p(x_2) + ... self.log_likelihood += marginal_logprob # Responsibilities are the posteriors p(c | x) = p(x, c) / p(x) # So log p(c | x) = log p(x, c) - log p(x) logresponsibilities = list() for component in range(self.num_components): dist = self.component_distributions[component] logresp = joint_logprobs[component] - marginal_logprob logresponsibilities.append(logresp) # Update the expected component count and expected observation counts for component in range(self.num_components): # log( expected observation counts ) logresp = logresponsibilities[component] self.expected_component_counts[component] = log_add(self.expected_component_counts[component], logresp) # Compute the log( expected observation counts) # log (exp obs count) # = log( exp_obs_count + val * exp(logresp)) # = log( exp_obs_count + exp( log(val) + logresp ) ) # = log_add( log(exp_obs_count), log(val) + logresp ) if observation > 0: exp_obs = self.expected_observation_counts[component] self.expected_observation_counts[component] = log_add(exp_obs, log(observation) + logresp)
def m_step(self): '''Perform the M-step. This step updates self.mixture_weights self.component_distributions ''' # test if the sum of the summed expected_component_counts is roughly equal to the total amount of observations sum_obs_counts = log_add_list(self.expected_component_counts.values()) print("Sum of expected component counts: {}".format(exp(sum_obs_counts))) # TODO: Implement this. # TODO: Make sure to reset the data structures you use for counting after you have # TODO: updated all parameters, namely self.expected_component_counts and self.expected_observation_counts for component in range(self.num_components): # log_new_weight # = log( exp( log_exp_count ) / exp( sum_obs_counts ) ) ) # = log( exp( log_exp_count )) - log( exp(sum_obs_counts) ) # = log_exp_count - sum_obs_counts log_exp_count = self.expected_component_counts[component] self.mixture_weights[component] = log_exp_count - sum_obs_counts # log_new_param # = log( exp( log_exp_count) / (exp(log_exp_count) + exp(log_exp_sum))) # = log_exp_count - (log( exp(log_exp_count) + exp(log_exp_sum) ) # = log_exp_count - log_add( log_exp_count + log_exp_sum ) log_exp_sum = self.expected_observation_counts[component] logparam = log_exp_count - log_add(log_exp_count, log_exp_sum) self.component_distributions[component] = GeometricDistribution(exp(logparam)) # Reset for component in range(self.num_components): self.expected_component_counts[component] = -float("inf") self.expected_observation_counts[component] = -float("inf")