예제 #1
0
def estimate_mixture_params(EmissionParameters, curr_counts_orig, curr_nr_of_counts_orig, curr_state, rand_sample_size, max_nr_iter, nr_of_iter=20, stop_crit=1.0, nr_of_init=10, verbosity=1):
	'''
	This function estimates thedirichlet multinomial mixture parameters
	'''
	#1) Copy old parameters and use it as initialisation for the first iteration

	alphas_list = []
	mixtures_list = []
	lls_list = []
	curr_counts = deepcopy(curr_counts_orig)
	curr_nr_of_counts = deepcopy(curr_nr_of_counts_orig)

	if len(curr_counts.shape) == 1:
		curr_counts = np.expand_dims(curr_counts, axis=1)

	if np.sum(np.sum(curr_counts, axis=0) > 0) > 0:
		curr_nr_of_counts = curr_nr_of_counts[:, np.sum(curr_counts, axis=0) >0]
		curr_counts = curr_counts[:, np.sum(curr_counts, axis=0) >0]

	#Test for fitting distributions only on diag events
	curr_nr_of_counts = curr_nr_of_counts[:, np.sum(curr_counts, axis=0) > 10]
	curr_counts = curr_counts[:, np.sum(curr_counts, axis=0) > 10]

	tracks_per_rep = EmissionParameters['Diag_event_params']['alpha'][curr_state].shape[0]
	NrOfReplicates = curr_counts.shape[0] / tracks_per_rep
	
	noncon = np.sum(curr_counts[[tracks_per_rep - 1 + (tracks_per_rep * i) for i in range(NrOfReplicates)],:], axis=0)
	conv = np.sum(curr_counts, axis=0) - noncon
	ratio = conv / np.float64(conv + noncon)
	rat_ix = ((ratio > 0.05) * (ratio < 0.95)) > 0
	rat_ix = ((ratio < 0.95)) > 0
	curr_nr_of_counts = curr_nr_of_counts[:, rat_ix]
	curr_counts = curr_counts[:, rat_ix]
	#end test

	if len(curr_counts.shape) == 1:
		curr_counts = np.expand_dims(curr_counts, axis=1)

	#Save old lls mixtures and alphas
	mixtures = deepcopy(EmissionParameters['Diag_event_params']['mix_comp'][curr_state])
	OldAlpha = deepcopy(EmissionParameters['Diag_event_params']['alpha'][curr_state])
	#pdb.set_trace()
	scored_counts = score_counts(curr_counts, curr_state, EmissionParameters) 
	scored_counts += np.tile(np.log(mixtures[:, np.newaxis]), (1, scored_counts.shape[1]))
	ll = np.sum(np.sum(logsumexp(scored_counts, axis=0) + np.log(curr_nr_of_counts)))

	alphas_list.append(deepcopy(EmissionParameters['Diag_event_params']['alpha'][curr_state]))
	mixtures_list.append(deepcopy(EmissionParameters['Diag_event_params']['mix_comp'][curr_state]))
	lls_list.append(ll)
 	
	for curr_init in range(nr_of_init):
		#compute the curr mixture, ll and alpha
		#initialiste the parameters
		old_ll = 0
		if curr_init == 0:
			OldAlpha = deepcopy(EmissionParameters['Diag_event_params']['alpha'][curr_state])
			mixtures = deepcopy(mixtures)
		else:
			OldAlpha = np.random.uniform(low=0.0001, high=0.1, size=OldAlpha.shape)
			for i in range(OldAlpha.shape[1]):
				OldAlpha[np.random.randint(OldAlpha.shape[0]-1), i] = np.random.random() * 10.0
				OldAlpha[-2, i] = np.random.random() * 1.0
				OldAlpha[-1, i] = np.random.random() * 10.0
			mixtures = np.random.uniform(low=0.0001, high=1.0, size=mixtures.shape)
			mixtures /= np.sum(mixtures)
		if EmissionParameters['Diag_event_params']['nr_mix_comp'] == 1:
			#Case that only one mixture component is given
			EmissionParameters['Diag_event_params']['alpha'][curr_state][:, 0] = diag_event_model.estimate_multinomial_parameters(curr_counts, curr_nr_of_counts, EmissionParameters, OldAlpha[:])
			#compute ll
			scored_counts = score_counts(curr_counts, curr_state, EmissionParameters) 
			scored_counts += np.tile(np.log(mixtures[:, np.newaxis]), (1, scored_counts.shape[1]))
			ll = np.sum(np.sum(logsumexp(scored_counts, axis=0) + np.log(curr_nr_of_counts)))

			alphas_list.append(deepcopy(EmissionParameters['Diag_event_params']['alpha'][curr_state]))
			mixtures_list.append(deepcopy(EmissionParameters['Diag_event_params']['mix_comp'][curr_state]))
			lls_list.append(ll)
		else:
			zero_ix = []
			for iter_nr in range(max_nr_iter):
				print('em-iteration ' + str(iter_nr))

				scored_counts = score_counts(curr_counts, curr_state, EmissionParameters) 
				scored_counts += np.tile(np.log(mixtures[:, np.newaxis]), (1, scored_counts.shape[1]))
				# 2) Compute the mixture components
				#compute the normalisation factor
				normalised_likelihood = logsumexp(scored_counts, axis=0) 

				old_ll = ll
				ll = np.sum(np.sum(logsumexp(scored_counts, axis=0) + np.log(curr_nr_of_counts)))

				if np.abs(old_ll - ll) < stop_crit:
					#Check if convergence has been reached
					if len(zero_ix) == 0:
						break

				normalised_scores = scored_counts - np.tile(normalised_likelihood, (scored_counts.shape[0], 1))
				un_norm_mixtures = logsumexp(normalised_scores, b=np.tile(curr_nr_of_counts, (scored_counts.shape[0], 1)), axis = 1)
				
				mixtures = np.exp(un_norm_mixtures - logsumexp(un_norm_mixtures))
				
				# 3) Compute for eachcount the most likely mixture component
				curr_weights = np.exp(normalised_scores)
				curr_weights = (curr_weights == np.tile(np.max(curr_weights, axis=0), (curr_weights.shape[0], 1))) *1.0

				zero_mix = np.sum(curr_weights,axis=1) == 0
				zero_ix = np.where(zero_mix)[0].tolist()
			   
				EmissionParameters['Diag_event_params']['mix_comp'][curr_state] = mixtures
				
				#Get number of positions that are used. (In case there are fewer entries that rand_sample_size in counts)
				rand_size = min(rand_sample_size, curr_counts.shape[1])
				for i in zero_ix:
					random_ix = np.random.choice(curr_counts.shape[1], rand_size, p=(curr_nr_of_counts[0, :] / np.float(np.sum(curr_nr_of_counts[0, :]))))
					curr_counts = np.hstack([curr_counts, curr_counts[:, random_ix]])
					curr_nr_of_counts = np.hstack([curr_nr_of_counts, np.ones((1, rand_size))])
					temp_array = np.zeros((normalised_scores.shape[0], rand_size))
					temp_array[i, :] = i
					normalised_scores = np.hstack([normalised_scores, temp_array])
					temp_array = np.zeros((curr_weights.shape[0], rand_size))
					temp_array[i, :] = 1
					curr_weights = np.hstack([curr_weights, temp_array])

				# 4) Compute the dirichlet-multinomial parameters
				for curr_mix_comp in range(EmissionParameters['Diag_event_params']['nr_mix_comp']):
					local_counts = curr_counts
					local_nr_counts = curr_nr_of_counts * curr_weights[curr_mix_comp, :]
					local_counts = local_counts[:, local_nr_counts[0, :] > 0]
					local_nr_counts = local_nr_counts[0, local_nr_counts[0, :] > 0]
					if len(local_counts.shape) == 1:
						local_counts = np.expand_dims(local_counts, axis=1)
					curr_alpha = diag_event_model.estimate_multinomial_parameters(local_counts, local_nr_counts, EmissionParameters, OldAlpha[:, curr_mix_comp])
					
					if curr_mix_comp in zero_ix:
						OldAlpha[:, curr_mix_comp] = np.random.uniform(low=0.0001, high=0.1, size=OldAlpha[:, curr_mix_comp].shape)
						OldAlpha[np.random.randint(OldAlpha.shape[0]), curr_mix_comp] = np.random.random() * 10.0
						OldAlpha[-2, curr_mix_comp] = np.random.random() * 1.0
						OldAlpha[-1, curr_mix_comp] = np.random.random() * 10.0
					else:
						OldAlpha[:, curr_mix_comp] = curr_alpha
				
				if (len(zero_ix) > 0) and (iter_nr + 2 < max_nr_iter):
					#Treat the case where some mixtures have prob zero
					mixtures[zero_ix] = np.mean(mixtures)
					mixtures /= np.sum(mixtures)
					EmissionParameters['Diag_event_params']['mix_comp'][curr_state] = deepcopy(mixtures)
				EmissionParameters['Diag_event_params']['alpha'][curr_state] = deepcopy(OldAlpha)
				# Check if convergence has been achieved.
			
			alphas_list.append(deepcopy(OldAlpha))
			mixtures[zero_ix] = np.min(mixtures[mixtures > 0])
			mixtures /= np.sum(mixtures)
			mixtures_list.append(deepcopy(mixtures))
			lls_list.append(ll)

	#select which alpha had the highest ll
	max_ll_pos = np.argmax(np.array(lls_list))
	
	alpha = alphas_list[max_ll_pos]
	mixtures = mixtures_list[max_ll_pos]

	return alpha, mixtures
예제 #2
0
def Parallel_estimate_single_mixture_params(args):
	'''
	This function estimates thedirichlet multinomial mixture parameters
	'''

	stop_crit, rand_sample_size, max_nr_iter, curr_init, EmissionParameters, curr_state, curr_counts, curr_nr_of_counts = args
	#compute the curr mixture, ll and alpha
	#initialiste the parameters
	old_ll = 0
	ll = -10

	OldAlpha = deepcopy(EmissionParameters['Diag_event_params']['alpha'][curr_state])
	mixtures = deepcopy(EmissionParameters['Diag_event_params']['mix_comp'][curr_state])

	if curr_init > 0:
		OldAlpha = np.random.uniform(low=0.0001, high=0.1, size=OldAlpha.shape)
		for i in range(OldAlpha.shape[1]):
			OldAlpha[np.random.randint(OldAlpha.shape[0]-1), i] = np.random.random() * 10.0
			OldAlpha[-2, i] = np.random.random() * 1.0
			OldAlpha[-1, i] = np.random.random() * 10.0
		mixtures = np.random.uniform(low=0.0001, high=1.0, size=mixtures.shape)
		mixtures /= np.sum(mixtures)
	if EmissionParameters['Diag_event_params']['nr_mix_comp'] == 1:
		#Case that only one mixture component is given
		EmissionParameters['Diag_event_params']['alpha'][curr_state][:, 0] = diag_event_model.estimate_multinomial_parameters(curr_counts, curr_nr_of_counts, EmissionParameters, OldAlpha[:])
		#compute ll
		scored_counts = score_counts(curr_counts, curr_state, EmissionParameters) 
		scored_counts += np.tile(np.log(mixtures[:, np.newaxis]), (1, scored_counts.shape[1]))
		ll = np.sum(np.sum(logsumexp(scored_counts, axis=0) + np.log(curr_nr_of_counts)))

		OldAlpha = deepcopy(EmissionParameters['Diag_event_params']['alpha'][curr_state])
		mixtures = deepcopy(EmissionParameters['Diag_event_params']['mix_comp'][curr_state])

	else:
		zero_ix = []
		for iter_nr in range(max_nr_iter):
			print('em-iteration ' + str(iter_nr))	

			scored_counts = score_counts(curr_counts, curr_state, EmissionParameters) 
			scored_counts += np.tile(np.log(mixtures[:, np.newaxis]), (1, scored_counts.shape[1]))
			# 2) Compute the mixture components
			#compute the normalisation factor
			normalised_likelihood = logsumexp(scored_counts, axis=0) 

			old_ll = ll
			ll = np.sum(np.sum(logsumexp(scored_counts, axis=0) + np.log(curr_nr_of_counts)))

			if np.abs(old_ll - ll) < stop_crit:
				if len(zero_ix) == 0:
					break

			normalised_scores = scored_counts - np.tile(normalised_likelihood, (scored_counts.shape[0], 1))
			un_norm_mixtures = logsumexp(normalised_scores, b=np.tile(curr_nr_of_counts, (scored_counts.shape[0], 1)), axis = 1)
			
			mixtures = np.exp(un_norm_mixtures - logsumexp(un_norm_mixtures))
			
			# 3) Compute for eachcount the most likely mixture component
			curr_weights = np.exp(normalised_scores)
			curr_weights = (curr_weights == np.tile(np.max(curr_weights, axis=0), (curr_weights.shape[0], 1))) *1.0

			zero_mix = np.sum(curr_weights,axis=1) == 0
			zero_ix = np.where(zero_mix)[0].tolist()
		   
			EmissionParameters['Diag_event_params']['mix_comp'][curr_state] = mixtures
			#Get number of positions that are used. (In case there are fewer entries that rand_sample_size in counts)
			rand_size = min(rand_sample_size, curr_counts.shape[1])
			for i in zero_ix:
				random_ix = np.random.choice(curr_counts.shape[1], rand_size, p=(curr_nr_of_counts[0, :] / np.float(np.sum(curr_nr_of_counts[0, :]))))
				curr_counts = np.hstack([curr_counts, curr_counts[:, random_ix]])
				curr_nr_of_counts = np.hstack([curr_nr_of_counts, np.ones((1, rand_size))])
				temp_array = np.zeros((normalised_scores.shape[0], rand_size))
				temp_array[i, :] = i
				normalised_scores = np.hstack([normalised_scores, temp_array])
				temp_array = np.zeros((curr_weights.shape[0], rand_size))
				temp_array[i, :] = 1
				curr_weights = np.hstack([curr_weights, temp_array])

			# 4) Compute the dirichlet-multinomial parameters
			for curr_mix_comp in range(EmissionParameters['Diag_event_params']['nr_mix_comp']):
				local_counts = curr_counts
				local_nr_counts = curr_nr_of_counts * curr_weights[curr_mix_comp, :]
				local_counts = local_counts[:, local_nr_counts[0, :] > 0]
				local_nr_counts = local_nr_counts[0, local_nr_counts[0, :] > 0]
				if len(local_counts.shape) == 1:
					local_counts = np.expand_dims(local_counts, axis=1)
				curr_alpha = diag_event_model.estimate_multinomial_parameters(local_counts, local_nr_counts, EmissionParameters, OldAlpha[:, curr_mix_comp])
				
				if curr_mix_comp in zero_ix:
					OldAlpha[:, curr_mix_comp] = np.random.uniform(low=0.0001, high=0.1, size=OldAlpha[:, curr_mix_comp].shape)
					OldAlpha[np.random.randint(OldAlpha.shape[0]), curr_mix_comp] = np.random.random() * 10.0
					OldAlpha[-2, curr_mix_comp] = np.random.random() * 1.0
					OldAlpha[-1, curr_mix_comp] = np.random.random() * 10.0
				else:
					OldAlpha[:, curr_mix_comp] = curr_alpha

			if (len(zero_ix) > 0) and (iter_nr + 2 < max_nr_iter):
				#Treat the case where some mixtures have prob zero
				mixtures[zero_ix] = np.mean(mixtures)
				mixtures /= np.sum(mixtures)
				EmissionParameters['Diag_event_params']['mix_comp'][curr_state] = deepcopy(mixtures)
			EmissionParameters['Diag_event_params']['alpha'][curr_state] = deepcopy(OldAlpha)
			# Check if convergence has been achieved.
		
		mixtures[zero_ix] = np.min(mixtures[mixtures > 0])
		mixtures /= np.sum(mixtures)
	
	return [deepcopy(OldAlpha), mixtures, ll]