def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ previous_message = rover.Distribution() path_map = [dict() for x in range(100)] for i, observation in enumerate(observations): current_message = rover.Distribution() for current_state in all_possible_hidden_states: if not observation: log_p_X_given_Z = 0 else: log_p_X_given_Z = Log( observation_model(current_state)[observation]) if i == 0: current_message[current_state] = log_p_X_given_Z + Log( prior_distribution[current_state]) else: max_found = -math.inf max_prev_state = None for previous_state in all_possible_hidden_states: transition_prob = Log( transition_model(previous_state) [current_state]) + previous_message[previous_state] if transition_prob > max_found: max_found = transition_prob max_prev_state = previous_state path_map[i][current_state] = max_prev_state current_message[current_state] = log_p_X_given_Z + max_found previous_message = current_message # Reconstruct the Path current_state = max(current_message, key=lambda key: current_message[key]) estimated_hidden_states = [current_state] for i in reversed(range(1, 100)): current_state = path_map[i][current_state] estimated_hidden_states.insert(0, current_state) return estimated_hidden_states
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ # TODO: Write your code here w = [None] * num_time_steps backtrack = [None] * num_time_steps estimated_hidden_states = [None] * num_time_steps for i in range(num_time_steps): w[i] = rover.Distribution() # Initialization if i == 0: for state in prior_distribution: result = prior_distribution[state] result *= observation_model(state)[observations[0]] if result != 0: w[i][state] = np.log(result) # Recursive else: backtrack[i] = {} for state in all_possible_hidden_states: p1 = 1 if observations[i] != None: p1 = observation_model(state)[observations[i]] if p1 == 0: continue p2 = -np.inf for k in w[i - 1]: if transition_model(k)[state] == 0: continue temp = np.log(transition_model(k)[state]) + w[i - 1][k] if temp > p2: p2 = temp backtrack[i][state] = k result = np.log(p1) + p2 if p2 != -np.inf and result != 0: w[i][state] = result # Backtracking n = num_time_steps - 1 estimated_hidden_states[n] = max(w[n], key=w[n].get) for i in range(1, num_time_steps): n = num_time_steps - 1 - i k = estimated_hidden_states[n + 1] estimated_hidden_states[n] = backtrack[n + 1][k] return estimated_hidden_states
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps #forward_messages[0] = prior_distribution backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps # TODO: Compute the forward messages # initialization of forward message forward_messages[0] = rover.Distribution({}) initial_observed_position = observations[0] for z0 in all_possible_hidden_states: if initial_observed_position == None: initial_prob_position_on_state = 1 else: initial_prob_position_on_state = observation_model( z0)[initial_observed_position] prior_z0 = prior_distribution[z0] if (initial_prob_position_on_state * prior_z0) != 0: forward_messages[0][z0] = initial_prob_position_on_state * prior_z0 forward_messages[0].renormalize() # when i >= 1 for i in range(1, num_time_steps): forward_messages[i] = rover.Distribution({}) observed_position = observations[i] for zi in all_possible_hidden_states: if observed_position == None: prob_position_on_state = 1 else: prob_position_on_state = observation_model( zi)[observed_position] sum = 0 for zi_minus_1 in forward_messages[i - 1]: sum = sum + forward_messages[ i - 1][zi_minus_1] * transition_model(zi_minus_1)[zi] if (prob_position_on_state * sum) != 0: # only save non-zero values forward_messages[i][zi] = prob_position_on_state * sum forward_messages[i].renormalize() # normalize forward messages # TODO: Compute the backward messages # initialization of backward message backward_messages[num_time_steps - 1] = rover.Distribution({}) for zn_minus_1 in all_possible_hidden_states: backward_messages[num_time_steps - 1][zn_minus_1] = 1 # when backward message is not the last one for i in range(1, num_time_steps): backward_messages[num_time_steps - 1 - i] = rover.Distribution({}) for zi in all_possible_hidden_states: sum = 0 for zi_plus_1 in backward_messages[num_time_steps - 1 - i + 1]: observed_position = observations[num_time_steps - 1 - i + 1] if observed_position == None: prob_position_on_next_state = 1 else: prob_position_on_next_state = observation_model( zi_plus_1)[observed_position] sum = sum + backward_messages[num_time_steps - 1 - i + 1][ zi_plus_1] * prob_position_on_next_state * transition_model( zi)[zi_plus_1] if sum != 0: backward_messages[num_time_steps - 1 - i][zi] = sum backward_messages[num_time_steps - 1 - i].renormalize() # TODO: Compute the marginals for i in range(0, num_time_steps): marginals[i] = rover.Distribution({}) sum = 0 for zi in all_possible_hidden_states: if forward_messages[i][zi] * backward_messages[i][zi] != 0: marginals[i][ zi] = forward_messages[i][zi] * backward_messages[i][zi] sum = sum + forward_messages[i][zi] * backward_messages[i][zi] for zi in marginals[i].keys(): marginals[i][zi] = marginals[i][zi] / sum return marginals
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ # TODO: Write your code here num_time_steps = len(observations) w = [None] * num_time_steps estimated_hidden_states = [None] * num_time_steps z_previous = [None] * num_time_steps # initialization w[0] = rover.Distribution({}) initial_observed_position = observations[0] for z0 in all_possible_hidden_states: if initial_observed_position == None: initial_prob_position_on_state = 1 else: initial_prob_position_on_state = observation_model( z0)[initial_observed_position] prior_z0 = prior_distribution[z0] if (initial_prob_position_on_state != 0) and (prior_z0 != 0): w[0][z0] = np.log(initial_prob_position_on_state) + np.log( prior_z0) # when i >= 1 for i in range(1, num_time_steps): w[i] = rover.Distribution({}) z_previous[i] = dict() observed_position = observations[i] for zi in all_possible_hidden_states: if observed_position == None: prob_position_on_state = 1 else: prob_position_on_state = observation_model( zi)[observed_position] max_term = -np.inf for zi_minus_1 in w[i - 1]: if transition_model(zi_minus_1)[zi] != 0: potential_max_term = np.log( transition_model(zi_minus_1)[zi]) + w[i - 1][zi_minus_1] if (potential_max_term > max_term) and (prob_position_on_state != 0): max_term = potential_max_term z_previous[i][ zi] = zi_minus_1 # keep track of which zi_minus_1 can maximize w[i][zi] if prob_position_on_state != 0: w[i][zi] = np.log(prob_position_on_state) + max_term # back track to find z0 to zn # first, find zn* (the last) max_w = -np.inf for zi in w[num_time_steps - 1]: potential_max_w = w[num_time_steps - 1][zi] if potential_max_w > max_w: max_w = potential_max_w estimated_hidden_states[num_time_steps - 1] = zi for i in range(1, num_time_steps): estimated_hidden_states[num_time_steps - 1 - i] = z_previous[ num_time_steps - i][estimated_hidden_states[num_time_steps - i]] return estimated_hidden_states
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps forward_messages[0] = prior_distribution backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps uniform = rover.Distribution() uniform.update(dict([(i, 1) for i in all_possible_hidden_states])) uniform.renormalize() allObs = [all_possible_observed_states if i is None else [i] for i in observations] # TODO: Compute the forward messages print("forward") forward_messages[0]=rover.Distribution() for i in prior_distribution: obsFactor=observation_model(i) for j in obsFactor: if j in allObs[0]: forward_messages[0][(i[0],i[1], 'stay')]=obsFactor[j] forward_messages[0].renormalize() # print(0, ". ", forward_messages[0]) for i in range(num_time_steps - 1): forward_messages[i + 1] = rover.Distribution() for j in forward_messages[i]: # states of i transTemp = rover.transition_model(j) for k in transTemp: # print(k, allObs[i+1]) obsFactor=observation_model(k) #(place): chance for l in obsFactor: if l in allObs[i+1]: forward_messages[i + 1] = addValToDic(forward_messages[i + 1], k, forward_messages[i][j] * transTemp[k]*obsFactor[l]) forward_messages[i + 1].renormalize() # print(i, ". ", forward_messages[i]) # print(i + 1, ". ", allObs[i + 1], observations[i + 1]) # print(i + 1, ". ", forward_messages[i + 1], "\n") # TODO: Compute the backward messages backward_messages[-1] = uniform print("back") # print(-1, ". ", backward_messages[-1]) for i in range(num_time_steps - 1, 0, -1): backward_messages[i - 1] = rover.Distribution() # revTrans=rover.Distribution() for j in all_possible_hidden_states: #states of i-1 transTemp = rover.transition_model(j) for k in transTemp: if k in backward_messages[i]: obsFactor=observation_model(k) for l in obsFactor: if l in allObs[i]:# backward_messages[i-1]=addValToDic(backward_messages[i-1], j, backward_messages[i][k]*transTemp[k]*obsFactor[l]) backward_messages[i - 1].renormalize() # print(i, ". ", backward_messages[i].get_mode(), backward_messages[i][backward_messages[i].get_mode()], # "message", backward_messages[i]) # print(i, ".", allObs[i], observations[i]) # print(i - 1, ". ", backward_messages[i - 1].get_mode(), # backward_messages[i - 1][backward_messages[i - 1].get_mode()], "message", backward_messages[i - 1], '\n') # TODO: Compute the marginals for i in range(num_time_steps): marginals[i] = rover.Distribution() marginals[i].update(dict( [(k, forward_messages[i][j] * backward_messages[i][k]) for j in forward_messages[i] for k in backward_messages[i] if j == k])) marginals[i].renormalize() # print(marginals[i], forward_messages[i], backward_messages[i]) return marginals
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps forward_messages[0] = prior_distribution backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps for i in range(num_time_steps): # TODO: Compute the forward messages forward_messages[i] = rover.Distribution({}) if i == 0: for z_n in prior_distribution: z0 = observations[i] forward_messages[i][z_n] = prior_distribution[z_n] * observation_model(z_n)[z0] forward_messages[i].renormalize() else: xy_n = observations[i] for z_n in all_possible_hidden_states: if xy_n == None: cond = 1 else: cond = observation_model(z_n)[xy_n] if cond != 0: prob = 0 for prev in (forward_messages[i-1]): prob += forward_messages[i-1][prev] * transition_model(prev)[z_n] if prob != 0: forward_messages[i][z_n] = cond * prob forward_messages[i].renormalize() #print(forward_messages[i], "for i = ",i) # TODO: Compute the backward messages last = num_time_steps - 1 - i backward_messages[last] = rover.Distribution({}) if i == 0: for z_n in all_possible_hidden_states: backward_messages[last][z_n] = 1 else: xy_n1 = observations[last + 1] for z_n in all_possible_hidden_states: prob = 0 for z_n1 in backward_messages[last+1]: if xy_n1 == None: cond = 1 else: cond = observation_model(z_n1)[xy_n1] prob += backward_messages[last + 1][z_n1] * transition_model(z_n)[z_n1] * cond if prob != 0: backward_messages[last][z_n] = prob backward_messages[last].renormalize() # TODO: Compute the marginals for i in range(num_time_steps): marginals[i] = rover.Distribution() for z_n in all_possible_hidden_states: alpha = forward_messages[i][z_n] beta = backward_messages[i][z_n] if alpha * beta != 0: marginals[i][z_n] = (alpha * beta) marginals[i].renormalize() #print("Marginal for is",marginals[1], "for i = 1") return marginals
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ # TODO: Write your code here # Stores all Wi's W = [None] * len(observations) map_sequence = [] # Key is Z_n+1 and value is Z_n hidden state links = [] for t in range(len(observations)): newdict = dict() links.append(dict()) # Calculate W0 p_z0 = prior_distribution W0 = rover.Distribution() log_p_xz = rover.Distribution() for hidden_state in p_z0: likelihood = observation_model(hidden_state) if (observations[0] is None): log_p_xz[hidden_state] = 0 else: log_p_xz[hidden_state] = safe_log(likelihood[observations[0]]) W0[hidden_state] = log_p_xz[hidden_state] + safe_log(p_z0[hidden_state]) #print(W0[hidden_state]) #print(len(W0)) W[0] = W0 # Calculate Wi for t in range(1, len(observations)): W_t = rover.Distribution() log_p_xz = rover.Distribution() for hidden_state in all_possible_hidden_states: likelihood = observation_model(hidden_state) if (observations[t] is None): log_p_xz[hidden_state] = 0 else: log_p_xz[hidden_state] = safe_log(likelihood[observations[t]]) max_log_prob, arg_max = get_max(hidden_state, W[t - 1]) if arg_max != None: '''print(t) print(hidden_state) print(links[t]) while True: pass''' links[t][hidden_state] = arg_max W_t[hidden_state] = log_p_xz[hidden_state] + max_log_prob # print(W_t[hidden_state]) arg_max_debug, max_value = get_mode(W_t) print("t: {} | arg: {} | max: {}".format(t, arg_max_debug, max_value)) W[t] = W_t final_dist = W[-1] max_hidden_state, max_val = get_mode(final_dist) map_sequence.append(max_hidden_state) for t in range(len(observations) - 1, 0, -1): prev = map_sequence[-1] print("T =", t) print("prev", prev) #print(prev) curr = links[t][prev] print("curr", curr) print("\n") #print(links[t]) map_sequence.append(curr) # print(curr) estimated_hidden_states = map_sequence[::-1] for d in range (1, len(links)): if links[d] == links[d-1]: print("FatalError", d) return estimated_hidden_states
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ # TODO: Write your code here num_time_steps = len(observations) forward_pass = [None] * num_time_steps w = [None] * num_time_steps max_w_zn = [None] * num_time_steps estimated_hidden_states = [None] * num_time_steps # loop through all the time_steps for i in range(num_time_steps): # create Distribution dictionaries w[i] = rover.Distribution() if i == 0: # TODO: initialize forward message to be ln(p(z0) * p( (x0,y0)| z0 )) for zn in prior_distribution: prior_z0 = prior_distribution[zn] z0 = observations[i] pcond_X0_z0 = observation_model(zn)[z0] if prior_z0 * pcond_X0_z0 != 0: w[i][zn] = np.log(prior_z0 * pcond_X0_z0) else: # TODO: Compute the forward messages xn = observations[i] max_w_zn[i] = dict() for zn in all_possible_hidden_states: # Part 2: check if observation is None if xn == None: # set conditional probability to be 1 pcond_Xn_zn = 1 else: pcond_Xn_zn = observation_model(zn)[xn] if pcond_Xn_zn != 0: # set maximum value to be -inf, and find the maximum of all values max_zn_prev = -np.inf # iterate through all the previous zn, find the max value, and save it for zn_prev in (w[i - 1]): pcond_zn_zn_prev = transition_model(zn_prev)[zn] # avoid log of 0 case if pcond_zn_zn_prev != 0: w_prev = w[i - 1][zn_prev] new_zn_prev = np.log(pcond_zn_zn_prev) + w_prev if new_zn_prev > max_zn_prev: max_zn_prev = new_zn_prev # store the maximum path to get to a certain zn from zn_prev max_w_zn[i][zn] = zn_prev # set the zn to be ln (p( (xn,yn)| zn )) + max {ln(p(zn,zn_prev)) + w(zn_prev)} w[i][zn] = np.log(pcond_Xn_zn) + max_zn_prev # loop through all the time_steps to determine optimal path for i in range(num_time_steps): end = num_time_steps - 1 - i if i == 0: # find the most probable zn at the end max_zn = -np.inf zn_star = None for zn in w[end]: zn_temp = zn max_zn_temp = w[end][zn_temp] if max_zn_temp > max_zn: max_zn = max_zn_temp zn_star = zn_temp estimated_hidden_states[end] = zn_star else: # find the path the links the old zn_star to the current time zn_star_prev = estimated_hidden_states[end + 1] estimated_hidden_states[end] = max_w_zn[end + 1][zn_star_prev] return estimated_hidden_states
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps forward_messages[0] = prior_distribution backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps poss_states = [None] * num_time_steps possible_prev_actions = ['left', 'right', 'up', 'down', 'stay'] for i in range(0, num_time_steps): poss_states[i] = [] if observations[i] == None: poss_states[i] = all_possible_hidden_states else: [x, y] = observations[i] for action in possible_prev_actions: poss_states[i].append((x, y, action)) poss_states[i].append((x - 1, y, action)) poss_states[i].append((x + 1, y, action)) poss_states[i].append((x, y + 1, action)) poss_states[i].append((x, y - 1, action)) # TODO: Compute the forward messages for i in range(0, num_time_steps): forward_messages[i] = rover.Distribution() if observations[i] == None: if i == 0: for state in poss_states[i]: forward_messages[i][state] = prior_distribution[state] * 1 else: for state in poss_states[i]: forward_messages[i][state] = 1*np.sum([forward_messages[i-1][zn1]*\ transition_model(zn1)[state] for zn1 in poss_states[i-1]]) forward_messages[i].renormalize() else: if i == 0: for state in poss_states[i]: forward_messages[i][state] = prior_distribution[ state] * observation_model(state)[observations[0]] else: for state in poss_states[i]: forward_messages[i][state] = observation_model(state)[observations[i]]*\ np.sum([forward_messages[i-1][zn1]*transition_model(zn1)[state] \ for zn1 in poss_states[i-1]]) forward_messages[i].renormalize() # TODO: Compute the backward messages for i in range(num_time_steps - 1, -1, -1): backward_messages[i] = rover.Distribution() if i == num_time_steps - 1: for state in all_possible_hidden_states: backward_messages[i][state] = 1 else: if observations[i + 1] == None: for state in poss_states[i]: backward_messages[i][state] = np.sum([backward_messages[i+1][zn1]*\ transition_model(state)[zn1] for zn1 in poss_states[i+1]]) else: for state in poss_states[i]: backward_messages[i][state] = np.sum([backward_messages[i+1][zn1]*\ observation_model(zn1)[observations[i+1]]*transition_model(state)[zn1] \ for zn1 in poss_states[i+1]]) backward_messages[i].renormalize() # TODO: Compute the marginals for i in range(0, num_time_steps): marginals[i] = rover.Distribution() # [x,y] = observations[i] # possible_states = list(transition_model([x,y,'stay']).keys()) for state in all_possible_hidden_states: marginals[i][state] = forward_messages[i][ state] * backward_messages[i][state] marginals[i].renormalize() return marginals
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ # TODO: Write your code here num_time_steps = len(observations) w = [None] * num_time_steps poss_states = [None] * num_time_steps phi = [None] * (num_time_steps - 1) possible_prev_actions = ['left', 'right', 'up', 'down', 'stay'] estimated_hidden_states = [] for i in range(0, num_time_steps): poss_states[i] = [] if observations[i] == None: poss_states[i] = all_possible_hidden_states else: [x, y] = observations[i] for action in possible_prev_actions: poss_states[i].append((x, y, action)) poss_states[i].append((x - 1, y, action)) poss_states[i].append((x + 1, y, action)) poss_states[i].append((x, y + 1, action)) poss_states[i].append((x, y - 1, action)) for i in range(0, num_time_steps): w[i] = rover.Distribution() if observations[i] == None: if i == 0: for state in poss_states[i]: w[0][state] = np.log(prior_distribution[state]) else: phi[i - 1] = dict() for state in poss_states[i]: w[i][state] = np.max([ np.log(transition_model(zn1)[state]) + w[i - 1][zn1] for zn1 in poss_states[i - 1] ]) phi[i - 1][state] = poss_states[i - 1][np.argmax([ np.log(transition_model(zn1)[state]) + w[i - 1][zn1] for zn1 in poss_states[i - 1] ])] else: if i == 0: for state in poss_states[i]: w[0][state] = np.log(prior_distribution[state]) + np.log( observation_model(state)[observations[0]]) else: phi[i - 1] = dict() for state in poss_states[i]: w[i][state] = np.log(observation_model(state)[observations[i]]) + \ np.max([np.log(transition_model(zn1)[state]) + w[i-1][zn1] for zn1 in poss_states[i-1]]) phi[i - 1][state] = poss_states[i - 1][np.argmax([ np.log(transition_model(zn1)[state]) + w[i - 1][zn1] for zn1 in poss_states[i - 1] ])] # w[i].renormalize() max_val = -1000 for key in w[-1].keys(): if w[-1][key] > max_val: max_val = w[-1][key] state_max = key estimated_hidden_states.append(state_max) for i in range(num_time_steps - 2, -1, -1): state_max_new = phi[i][state_max] estimated_hidden_states.insert(0, state_max_new) state_max = state_max_new return estimated_hidden_states
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps forward_messages[0] = prior_distribution backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps for i in range(num_time_steps): # TODO: Compute the forward messages forward_messages[i] = rover.Distribution() # Intialization if i == 0: for state in prior_distribution: result = prior_distribution[state] * observation_model(state)[ observations[0]] if result != 0: forward_messages[i][state] = result # Recursive else: for state in all_possible_hidden_states: result = 1 if observations[i] != None: result = observation_model(state)[observations[i]] subresult = 0 for k in forward_messages[i - 1]: product = transition_model(k)[state] * forward_messages[ i - 1][k] subresult += product result *= subresult if result != 0: forward_messages[i][state] = result forward_messages[i].renormalize() # TODO: Compute the backward messages n = num_time_steps - i - 1 backward_messages[n] = rover.Distribution() # Intialization if i == 0: for state in all_possible_hidden_states: backward_messages[n][state] = 1 # Recursive else: for state in all_possible_hidden_states: result = 0 subresult = 1 for k in backward_messages[n + 1]: subresult = 1 if observations[n + 1] != None: subresult = observation_model(k)[observations[n + 1]] subresult *= transition_model( state)[k] * backward_messages[n + 1][k] result += subresult if result != 0: backward_messages[n][state] = result backward_messages[n].renormalize() # TODO: Compute the marginals for i in range(num_time_steps): marginals[i] = rover.Distribution() for state in all_possible_hidden_states: result = forward_messages[i][state] * backward_messages[i][state] if result != 0: marginals[i][state] = result marginals[i].renormalize() return marginals
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) ######################################################################## ################ Compute the forward messages ########################## ######################################################################## print("Computing forward messages") """ Initialization """ forward_messages = [None] * num_time_steps forward_messages[0] = rover.Distribution() for state in all_possible_hidden_states: forward_messages[0][state] = prior_distribution[state] * ( observation_model(state) )[observations[0]] """ Perform computation: fm[n] = p((xn, yn) | zn) * sum_over_zn-1{ fm[n-1] * p(zn | zn-1) } """ for time_step in range(1, num_time_steps): print("-", end = '') curr = rover.Distribution() prev = forward_messages[time_step - 1] """ Fill in the distribution """ for curr_state in all_possible_hidden_states: """ Sum over previous time_step """ for prev_state in all_possible_hidden_states: if(observations[time_step] != None): curr[curr_state] += prev[prev_state] * ( transition_model(prev_state) )[curr_state] * ( observation_model(curr_state) )[observations[time_step]] else: curr[curr_state] += prev[prev_state] * ( transition_model(prev_state) )[curr_state] * 1.0 """ Normalize this distribution """ curr.renormalize() """ Store distribution into forward_messages """ forward_messages[time_step] = curr print(" ") ######################################################## ########### Compute the backward messages ############## ######################################################## print("Computing backward messages") """ Initialization """ backward_messages = [None] * num_time_steps backward_messages[num_time_steps - 1] = rover.Distribution() for state in all_possible_hidden_states: backward_messages[num_time_steps - 1][state] = 1.0 """ Iterate through """ for time_step in range(num_time_steps-2, -1, -1): print("-", end = '') prev = rover.Distribution() curr = backward_messages[time_step + 1] """ Iterate over zn-1 """ for prev_state in all_possible_hidden_states: for curr_state in all_possible_hidden_states: if(observations[time_step+1] != None): prev[prev_state] += curr[curr_state] * ( observation_model(curr_state) )[observations[time_step+1]] * ( transition_model(prev_state) )[curr_state] else: prev[prev_state] += curr[curr_state] * 1.0 * ( transition_model(prev_state) )[curr_state] """ Normalize new distribution """ prev.renormalize() """ Store distribution in backward_messages """ backward_messages[time_step] = prev print(" ") ############################################## ########### Compute the marginals ############ ############################################## print("Computing marginals") marginals = [None] * num_time_steps """ Compute the rest of the marginals """ for time_step in range(0, num_time_steps): marginals[time_step] = rover.Distribution() for state in all_possible_hidden_states: marginals[time_step][state] = forward_messages[time_step][state] * backward_messages[time_step][state] marginals[time_step].renormalize() return marginals
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of estimated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ num_time_steps = len(observations) estimated_hidden_states = [None] * num_time_steps """ Create vector of functions. These functions will be implemented as distributions """ W = [None] * num_time_steps B = [None] * num_time_steps W[0] = rover.Distribution() for state in all_possible_hidden_states: if(observations[0] != None): W[0][state] = log(prior_distribution[state]) + log( ( observation_model(state) )[observations[0]] ) else: W[0][state] = log(prior_distribution[state]) + 0.0 B[0] = None """ First pass through. Construct all the w equations. """ for time_step in range(1, num_time_steps): print("-", end='') W[time_step] = rover.Distribution() back_dist = rover.Distribution() for curr in all_possible_hidden_states: max_state = None max_value = -np.inf for prev in all_possible_hidden_states: new_value = log( ( transition_model(prev) )[curr] ) + W[time_step-1][prev] if(new_value > max_value): max_value = new_value max_state = prev if(observations[time_step] != None): W[time_step][curr] = log( (observation_model(curr))[observations[time_step]] ) + max_value else: W[time_step][curr] = max_value back_dist[curr] = max_state B[time_step] = back_dist print(" ") best_path_ptr = all_possible_hidden_states[0] for state in all_possible_hidden_states: if(W[num_time_steps-1][state] > W[num_time_steps-1][best_path_ptr]): best_path_ptr = state estimated_hidden_states[num_time_steps-1] = best_path_ptr best_path_ptr = B[num_time_steps-1][best_path_ptr] for time_step in range(num_time_steps-2, -1, -1): estimated_hidden_states[time_step] = best_path_ptr if(time_step == 0): break else: temp = best_path_ptr best_path_ptr = B[time_step][temp] # """ Second pass through, compute and record the argmax's """ # for time_step in range(0, num_time_steps): # max_state = all_possible_hidden_states[0] # for state in all_possible_hidden_states: # if(W[time_step][state] > W[time_step][max_state]): # max_state = state # estimated_hidden_states[time_step] = max_state return estimated_hidden_states
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ # number of timesteps num_time_steps = len(observations) #a distribution of the hidden state that represents the log probability of transition #from a factor to a variable in the factor tree/HMM chain w_z = [None] * num_time_steps #a function to keep track of the most likely previous states for each current #timestamp in the forward pass of the algorithm. A list of dicts where the key is a given #hidden state for the current timestamp, and the value is a hidden state from the #previous timestamp that has the heighest probability to lead to the hidden state #denoted by the key phi_z = [None] * num_time_steps #a function to determine the most likely sequence in the backward pass of the #algo as we backtrack the HMM chain. A list of estimated hidden states per #timestamp zTilde_max = [None] * num_time_steps #Forward pass of Viterbi Algorithm. Note: this takes a minute or two to run #so if you want to quickly get the result after running it once, just turn #the preloaded flag on. if not PRELOADED: for i in range(num_time_steps): w_z[i] = rover.Distribution() phi_z[i] = {} for current_state in all_possible_hidden_states: #Define the observation distribution and the current observation obs_distr = observation_model(current_state) observation = observations[i] #Assume the observation is missing and assign it a unit probability P_obs = 1 #If the observation exists, use the model instead to get the prob if observation is not None: P_obs = obs_distr.get(observation) #if the observation distribution didn't yield a non-zero prob for #that observation, that means the hidden state is not really possible #based on that observation, so this probability should be zero, however #since we are working in the log domain, note that log(0) is undefined #so we assign it a very small probability. #Also note, we can't skip like we do in F/B because we are taking the #sum and not the product if P_obs is None: P_obs = 1e-10 #tackle the initialization of the recurrence if (i == 0): #w_(z0) = log(p(z0)) + log(p(obs0 | z0)) prior_prob = prior_distribution[current_state] #print(prior_prob) if prior_prob != 0: w_z[i][current_state] = np.log(prior_prob) + np.log( P_obs) else: #a hash of the previous states prev_states_dict = {} previous_states = w_z[i - 1] #print("There are ",len(previous_states), "previous states") for prev_state in previous_states: #Calculate the transition probability P(zi|zi-1) trans_distr = transition_model(prev_state) P_trans = trans_distr.get(current_state) if P_trans is None: continue #Calculate the max prev state transition log probability prev_logprob = np.log(P_trans) + w_z[i - 1][prev_state] #keep track of the probabilities of the previous states prev_states_dict[prev_state] = prev_logprob #store the previous state that is most likely to have gotten us to #this current state #print ("Prev state dict:\n", prev_states_dict) max_prev_state = max(prev_states_dict, key=prev_states_dict.get) phi_z[i][current_state] = max_prev_state #Calculate w(zi) based on the recurrence relation assert (prev_states_dict[max_prev_state] == max( prev_states_dict.values())) w_z[i][current_state] = np.log(P_obs) + max( prev_states_dict.values()) save_checkpoint("viterbiDict", phi_z) save_checkpoint("viterbiW", w_z) #Backward pass of Viterbi Algorithm. #we find the most likely state hidden within the very last timestamp. if PRELOADED: phi_z = load_checkpoint("viterbiDict") w_z = load_checkpoint("viterbiW") wLast = w_z[num_time_steps - 1] argmax_zLast = max(wLast, key=wLast.get) zTilde_max[-1] = argmax_zLast #Now backtrack and find the most likely state in the previous timestamp for #that for i in range(num_time_steps - 2, -1, -1): #the state we are backtracking from #print(i) argmax_zNext = zTilde_max[i + 1] #print(argmax_zNext) #the tagged state in the previous timestamp that is most likely to have led #to the next hidden state. max_state = phi_z[i + 1].get(argmax_zNext) #print ("Max leading state:\n", max_state) zTilde_max[i] = max_state #print (phi_z) estimated_hidden_states = zTilde_max #print(len(estimated_hidden_states)) #print(estimated_hidden_states) return estimated_hidden_states
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forwardMessages = [None] * num_time_steps forwardMessages[0] = prior_distribution backMessages = [None] * num_time_steps marginals = [None] * num_time_steps # TODO: Compute the forward messages # initialize forwardMessages[0] = rover.Distribution({}) for z0 in all_possible_hidden_states: initialPos = 1 if observations[0] == None else observation_model(z0)[observations[0]] prior_z0 = prior_distribution[z0] mes = initialPos * prior_distribution[z0] if (mes) != 0: forwardMessages[0][z0] = mes forwardMessages[0].renormalize() # for all other alpha_i's for i in range(1, num_time_steps): forwardMessages[i] = rover.Distribution({}) observedPosition = observations[i] for zi in all_possible_hidden_states: probPosition_cur = 1 if observedPosition == None else observation_model(zi)[observedPosition] prob = 0 for zi_minus_1 in forwardMessages[i-1]: prob += forwardMessages[i-1][zi_minus_1] * transition_model(zi_minus_1)[zi] if (probPosition_cur * prob) != 0: # only save non-zero values forwardMessages[i][zi] = probPosition_cur * prob forwardMessages[i].renormalize() # normalize forward messages # TODO: Compute the backward messages # initialization of backward message backMessages[num_time_steps-1] = rover.Distribution({}) for zn_minus_1 in all_possible_hidden_states: backMessages[num_time_steps-1][zn_minus_1] = 1 # fill the rest for i in range(1, num_time_steps): backMessages[num_time_steps-1-i] = rover.Distribution({}) for zi in all_possible_hidden_states: prob = 0 for zi_plus_1 in backMessages[num_time_steps-1-i+1]: observedPosition = observations[num_time_steps-1-i+1] probPosition_next = 1 if observedPosition == None else observation_model(zi_plus_1)[observedPosition] prob += backMessages[num_time_steps-1-i+1][zi_plus_1] * probPosition_next * transition_model(zi)[zi_plus_1] if prob != 0: backMessages[num_time_steps-1-i][zi] = prob backMessages[num_time_steps-1-i].renormalize() # TODO: Compute the marginals for i in range (0, num_time_steps): marginals[i] = rover.Distribution({}) prob = 0 for zi in all_possible_hidden_states: if forwardMessages[i][zi] * backMessages[i][zi] != 0: marginals[i][zi] = forwardMessages[i][zi] * backMessages[i][zi] prob += forwardMessages[i][zi] * backMessages[i][zi] for zi in marginals[i].keys(): marginals[i][zi] /= prob return marginals
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps #Compute the forward messages for i in range(num_time_steps): forward_messages[i] = rover.Distribution() for state in all_possible_hidden_states: innerSum = 0 #The observation probability distribution obs_distr = observation_model(state) #The observation itself observation = observations[i] #The probability of observation, given a hidden state. #Assume the observation is missing, assigning it unit probability P_obs_given_hidden = 1 #if the observation exists, get it from the distribution model if observation is not None: P_obs_given_hidden = obs_distr.get(observation) #If the observation didn't exist, the inferred hidden state wouldn't #be possible based on this and as such we ignore it if P_obs_given_hidden is None: continue #Handle the initialization of the recurrence relation. if i == 0: #alpha(z0) = P(z0) * P(obs|z0) if prior_distribution[state] is not None: forward_messages[0][ state] = prior_distribution[state] * P_obs_given_hidden else: for previous_state in (forward_messages[i - 1]): alpha_prev = (forward_messages[i - 1])[previous_state] P_trans = transition_model(previous_state)[state] if (P_trans == 0): continue innerSum = innerSum + (alpha_prev * P_trans) forward_messages[i][state] = P_obs_given_hidden * innerSum forward_messages[i].renormalize() #Compute the backward messages for i in range(num_time_steps - 1, -1, -1): backward_messages[i] = rover.Distribution() #Initialize the B(zn-1) for the recurrence relation if i == num_time_steps - 1: for state in all_possible_hidden_states: backward_messages[i][state] = 1 else: for next_state in (backward_messages[i + 1]): #The observation probability distribution obs_distr = observation_model(next_state) #The observation itself observation = observations[i + 1] #The probability of observation, given a hidden state. #Assume the observation is missing, assigning it unit probability obs_prob = 1 #if the observation exists, get it from the distribution model if observation is not None: obs_prob = obs_distr.get(observation) #If the observation didn't exist, the inferred hidden state wouldn't #be possible based on this and as such we ignore it if (obs_prob is None): continue prod = backward_messages[i + 1][next_state] * obs_prob for state in all_possible_hidden_states: trans_prob = transition_model(state)[next_state] if (trans_prob == 0): continue backward_messages[i][state] += (prod * trans_prob) backward_messages[i].renormalize() #Compute the marginals for i in range(num_time_steps): marginals[i] = rover.Distribution() for z_i in all_possible_hidden_states: prod = forward_messages[i][z_i] * backward_messages[i][z_i] if prod == 0: #report only non-zero probabilities in the distribution continue marginals[i][z_i] = prod marginals[i].renormalize() return marginals
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps # TODO: Compute the forward messages alpha_0 = rover.Distribution() # initial forward message for z in prior_distribution: alpha_0[z] = prior_distribution[z] * observation_model(z)[ observations[0]] # alpha(z_0) = p(z_0)*p((x_0, y_0)|z_0) alpha_0.renormalize() forward_messages[0] = alpha_0 # compute all the other forward messages (alphas) for i in range(num_time_steps - 1): curr_observation = observations[i + 1] alpha = rover.Distribution( ) # initialize the current forward message before filling in the values # go through all values for z_n to fill it in for the current forward message for z_n in all_possible_hidden_states: # account for possibilility of missing data if curr_observation == None: cond_prob = 1 else: cond_prob = observation_model(z_n)[curr_observation] # if the condition probability isn't 0, we need to calculate the value for alpha(z_n), otherwise we can skip it and automatically set the value to 0 if cond_prob != 0: prev_sum = sum(forward_messages[i][prev_z] * transition_model(prev_z)[z_n] for prev_z in forward_messages[i]) alpha[ z_n] = cond_prob * prev_sum # alpha(z_n) = p((x_n, y_n)|z_n)*sum of alpha(z_{n - 1})*p(z_n|z_{n - 1}) over all possible z_{n - 1} values, calculated in previous line else: alpha[z_n] = 0 alpha.renormalize( ) # renormalize the values into a probability distribution, in order to prevent integer underflow forward_messages[i + 1] = alpha # save the alpha value for this timestep # TODO: Compute the backward messages beta_n = rover.Distribution( ) # initial backwards message (for final state) # we don't have information, so just set everything to be 1 in order not to bias the messages that build upon this for state in all_possible_hidden_states: beta_n[state] = 1 beta_n.renormalize() backward_messages[num_time_steps - 1] = beta_n # compute other backwards messages for i in reversed(range(num_time_steps - 1)): curr_observation = observations[i + 1] beta = rover.Distribution( ) # initialize the current backwards message before filling in its values # go through all values of z_{n - 1} to fill in for the current backwards message for prev_z in all_possible_hidden_states: trans_model = transition_model( prev_z ) # used to find conditional probabilities of the next state conditioned on z_{n - 1}, precomputed to reduce runtime # if current observation is none, we need to replace the p((x_n, y_n)|z_n) factor with 1, as we don't have information and don't want to bias the predictions # otherwise, we can include that factor in our calculation if curr_observation == None: # beta(z_{n - 1}) = sum of beta(z_n)*p(z_n|z_{n - 1}) over all possible z_n values from the last backwards message beta[prev_z] = sum(backward_messages[i + 1][z_n] * trans_model[z_n] for z_n in backward_messages[i + 1]) else: # beta(z_{n - 1}) = sum of beta(z_n)*p((x_n, y_n)|z_n)*p(z_n|z_{n - 1}) over all possible z_n values from the last backwards message beta[prev_z] = sum(backward_messages[i + 1][z_n] * observation_model(z_n)[curr_observation] * trans_model[z_n] for z_n in backward_messages[i + 1]) beta.renormalize( ) # renormalize the values into a probability distribution to prevent integer underflow backward_messages[i] = beta # save the beta value for this timestep # TODO: Compute the marginals # to compute the marginals, we need to compute every gamma(z_n) and then normalize it for i in range(num_time_steps): alpha = forward_messages[i] beta = backward_messages[i] gamma = rover.Distribution() for state in all_possible_hidden_states: gamma[state] = alpha[state] * beta[ state] # gamma(z_n) = alpha(z_n)*beta(z_n), for each possible state gamma.renormalize( ) # renormalize to make sure it is a probability distribution marginals[ i] = gamma # save the marginal distribution for this timestep return marginals
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps # forward_messages[0] = prior_distribution backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps # first compute the forward and backward messages # loop through all the time_steps for i in range(num_time_steps): # create Distribution dictionaries end = num_time_steps - 1 - i forward_messages[i] = rover.Distribution({}) backward_messages[end] = rover.Distribution({}) # Initialization if i == 0: # TODO: initialize forward message to be p(z0) * p( (x0,y0)| z0 ) for zn in prior_distribution: prior_z0 = prior_distribution[zn] z0 = observations[i] pcond_X0_z0 = observation_model(zn)[z0] if pcond_X0_z0 != 0: forward_messages[i][zn] = prior_z0 * pcond_X0_z0 # renormalize forward message forward_messages[i].renormalize() # TODO: initialize the backward message to be 1 at state all states for zn in all_possible_hidden_states: backward_messages[end][zn] = 1 # Forward/Backward Messages else: # TODO: Compute the forward messages xn = observations[i] for zn in all_possible_hidden_states: # Part 2: check if observation is None if xn == None: # set conditional probability to be 1 pcond_Xn_zn = 1 else: pcond_Xn_zn = observation_model(zn)[xn] if pcond_Xn_zn != 0: sum = 0 for zn_prev in (forward_messages[i - 1]): forward_prev = forward_messages[i - 1][zn_prev] pcond_zn_zn_prev = transition_model(zn_prev)[zn] sum += forward_prev * pcond_zn_zn_prev if sum != 0: forward_messages[i][zn] = pcond_Xn_zn * sum # renormalize forward message forward_messages[i].renormalize() # TODO: Compute the backward messages # end denotes the current state (n) while end+1 denotes the state after it (n_aft) xn_aft = observations[end + 1] for zn in all_possible_hidden_states: sum = 0 for zn_aft in backward_messages[end + 1]: # Part 2: check if observation is None if xn_aft == None: # set conditional probability to be 1 if so pcond_Xn_aft_zn_aft = 1 else: pcond_Xn_aft_zn_aft = observation_model(zn_aft)[xn_aft] beta_zn_aft = backward_messages[end + 1][zn_aft] pcond_zn_aft_zn = transition_model(zn)[zn_aft] sum += beta_zn_aft * pcond_zn_aft_zn * pcond_Xn_aft_zn_aft if sum != 0: backward_messages[end][zn] = sum # TODO: Compute the marginals # loop through all the time_steps for i in range(num_time_steps): # create Distribution dictionaries marginals[i] = rover.Distribution() # calculate the numerator and denominator (normalization factor) sum_alpha_beta = 0 for zn in all_possible_hidden_states: alpha = forward_messages[i][zn] beta = backward_messages[i][zn] if alpha * beta != 0: marginals[i][zn] = (alpha * beta) sum_alpha_beta += forward_messages[i][zn] * backward_messages[i][zn] # check if non-zero probability (for normalization) if sum_alpha_beta != 0: # normalize each zn for zn in marginals[i].keys(): marginals[i][zn] = marginals[i][zn] / sum_alpha_beta # print(marginals) return marginals
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ # TODO: Write your code here logpxcondz = rover.Distribution() w1 = rover.Distribution() for z1 in prior_distribution: likelihood = observation_model(z1) if (observations[0] is not None): logpxcondz[z1] = logarithm(likelihood[observations[0]]) w1[z1] = logpxcondz[z1] + logarithm(prior_distribution[z1]) W = [None] * len(observations) W[0] = w1 parent = [] for i in range(len(observations)): parent.append({}) print("CALCULATING W VALUES") for n in range(1, len(observations)): wn = rover.Distribution() logpxcondz = rover.Distribution() for hidden_state in all_possible_hidden_states: pxcondz = observation_model(hidden_state) if (observations[n] is not None): logpxcondz[hidden_state] = logarithm(pxcondz[observations[n]]) max_log_prob, MLprev = mle_past(hidden_state, W[n - 1]) if MLprev is not None: parent[n][hidden_state] = MLprev wn[hidden_state] = logpxcondz[hidden_state] + max_log_prob W[n] = wn end = W[-1] most_likely_state, max_log_prob = mlstate(end) state_sequence = [] state_sequence.append(most_likely_state) for n in range(len(observations) - 1, 0, -1): past = state_sequence[-1] present = parent[n][past] state_sequence.append(present) print("Time step = {} | Joint(t) = {}".format(n, present)) estimated_hidden_states = state_sequence[::-1] return estimated_hidden_states
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps forward_messages[0] = prior_distribution backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps # TODO: Compute the forward messages #forward messages are a distribution #update distribution based on observation and transition model #print(observations) '''copy = prior_distribution #copy is alpha distribution print(copy) print(observations) for state in copy: observed_given_hidden = observation_model(state) for obsstate in observed_given_hidden: copy[state] = copy[state]*observed_given_hidden[obsstate]''' alpha_z0 = prior_distribution for state in prior_distribution: likelihood_function = observation_model(state) #p(xi, yi| z0) p_obs_given_hidden = likelihood_function[observations[0]] #p(first observation | z0) alpha_z0[state] = prior_distribution[state]*p_obs_given_hidden #p(first observation|z0) * p(z0) proportional to p(z0|x0,y0) alpha_z0.renormalize() forward_messages[0] = alpha_z0 for i in range(1,num_time_steps): alpha_zi_1 = forward_messages[i-1] #just want the shapes to match previous timestep distribution xi_yi = observations[i] alpha_zi = rover.Distribution() #print(xi_yi) for zi in all_possible_hidden_states: sum = 0 likelihood_function = observation_model(zi) #p(xn,yn|zi) if xi_yi is not None: p_obs_given_hidden = likelihood_function[xi_yi] #p(xi,yi|zi) were xi,yi is our observation else: p_obs_given_hidden = 1 for zi_1 in alpha_zi_1: nextgivenprev = transition_model(zi_1) sum += alpha_zi_1[zi_1]*nextgivenprev[zi] if p_obs_given_hidden*sum>0.0: alpha_zi[zi] = p_obs_given_hidden * sum #print(alpha_zi) alpha_zi.renormalize() sum = 0 for key in alpha_zi: sum += alpha_zi[key] #print(sum) forward_messages[i] = alpha_zi # TODO: Compute the backward messages #Initialize the last beta beta_zN_1 = prior_distribution for state in all_possible_hidden_states: beta_zN_1[state] = 1 beta_zN_1.renormalize() backward_messages[-1] = beta_zN_1 #Recursively go back for other betas beta_zn_1 = beta_zN_1 print("PRINTING BETA VALUES NOW") for n in range(num_time_steps-2, -1, -1): beta_zn = backward_messages[n+1] beta_zn_1 = rover.Distribution() xn_yn = observations[n + 1] #print(xn_yn) for zn_1 in all_possible_hidden_states: sum = 0 nextgivenprev = transition_model(zn_1) for zn in beta_zn: likelihood_function = observation_model(zn) if xn_yn is not None: p_obs_given_hidden = likelihood_function[xn_yn] else: p_obs_given_hidden = 1 sum += beta_zn[zn]*p_obs_given_hidden*nextgivenprev[zn] if sum > 0.0: beta_zn_1[zn_1] = sum #print(beta_zn_1) beta_zn_1.renormalize() backward_messages[n] = beta_zn_1 # TODO: Compute the marginals print("PRINTING MARGINALS") for i in range(num_time_steps): print(i) alpha_zi = forward_messages[i] beta_zi = backward_messages[i] gamma_zi = rover.Distribution() for state in all_possible_hidden_states: if alpha_zi[state]*beta_zi[state] > 0: gamma_zi[state] = alpha_zi[state]*beta_zi[state] gamma_zi.renormalize() marginals[i] = gamma_zi print(marginals[i]) #print(marginals[i].get_mode()) return marginals
def forward_backward(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ all_possible_hidden_states: a list of possible hidden states all_possible_observed_states: a list of possible observed states prior_distribution: a distribution over states transition_model: a function that takes a hidden state and returns a Distribution for the next state observation_model: a function that takes a hidden state and returns a Distribution for the observation from that hidden state observations: a list of observations, one per hidden state (a missing observation is encoded as None) Output ------ A list of marginal distributions at each time step; each distribution should be encoded as a Distribution (see the Distribution class in rover.py), and the i-th Distribution should correspond to time step i """ num_time_steps = len(observations) forward_messages = [None] * num_time_steps backward_messages = [None] * num_time_steps marginals = [None] * num_time_steps # Compute the forward messages forward_prev = rover.Distribution() for i, observation in enumerate(observations): forward_curr = rover.Distribution() for current_state in all_possible_hidden_states: if i == 0: previous_f_sum = prior_distribution[current_state] else: previous_f_sum = sum(forward_prev[previous_state] * transition_model(previous_state)[current_state] \ for previous_state in all_possible_hidden_states) if not observation: forward_curr[current_state] = previous_f_sum else: forward_curr[current_state] = observation_model( current_state)[observation] * previous_f_sum forward_curr.renormalize() forward_messages[i] = forward_curr forward_prev = forward_curr # Compute the backward messages backward_prev = rover.Distribution() for i, observation_i_plus in enumerate( reversed(observations[1:] + [(None, )])): backward_curr = rover.Distribution() for current_state in all_possible_hidden_states: if i == 0: backward_curr[current_state] = 1 else: if not observation_i_plus: backward_curr[current_state] = sum(transition_model(current_state)[next_state] \ * backward_prev[next_state] for next_state in all_possible_hidden_states) else: backward_curr[current_state] = sum(transition_model(current_state)[next_state] \ * observation_model(next_state)[observation_i_plus] \ * backward_prev[next_state] for next_state in all_possible_hidden_states) backward_curr.renormalize() backward_messages[len(backward_messages) - i - 1] = backward_curr backward_prev = backward_curr # Compute the marginals for i in range(len(observations)): marginal = rover.Distribution() for state in all_possible_hidden_states: marginal[state] = forward_messages[i][state] * backward_messages[ i][state] marginal.renormalize() marginals[i] = marginal return marginals
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ # TODO: Write your code here num_time_steps = len(observations) estimated_hidden_states = [None] * num_time_steps w = [None] * num_time_steps max_path = [None] * num_time_steps #Initialization w[0] = rover.Distribution() for z_n in prior_distribution: z0 = observations[0] p_z0 = prior_distribution[z_n] p_given_z0 = observation_model(z_n)[z0] if p_z0 * p_given_z0 != 0: w[0][z_n] = np.log(p_z0*p_given_z0) for i in range(1,num_time_steps): w[i] = rover.Distribution() xy_n = observations[i] max_path[i] = dict() for z_n in all_possible_hidden_states: if xy_n == None: p_x_given_z = 1 else: p_x_given_z = observation_model(z_n)[xy_n] if p_x_given_z != 0: max_val = -100000000.00 for prev in (w[i-1]): p_z_given_prev = transition_model(prev)[z_n] if p_z_given_prev != 0: temp_val = np.log(p_z_given_prev) + w[i-1][prev] if temp_val > max_val: max_path[i][z_n] = prev max_val = temp_val w[i][z_n] = np.log(p_x_given_z) + max_val #back track to find estimaded states for i in range(num_time_steps): last = num_time_steps - 1 - i if i == 0: max_z = None max_val = -100000000.00 for z_n in w[last]: temp = w[last][z_n] if temp > max_val: max_val = temp max_z = z_n estimated_hidden_states[last] = max_z else: estimated_hidden_states[last] = max_path[last+1][estimated_hidden_states[last+1]] return estimated_hidden_states
def Viterbi(all_possible_hidden_states, all_possible_observed_states, prior_distribution, transition_model, observation_model, observations): """ Inputs ------ See the list inputs for the function forward_backward() above. Output ------ A list of esitmated hidden states, each state is encoded as a tuple (<x>, <y>, <action>) """ num_time_steps = len(observations) maxLastState = [] maxLast = -100000000 allObs = [all_possible_observed_states if i is None else [i] for i in observations] w = [None] * num_time_steps estimated_hidden_states = [rover.Distribution()] * num_time_steps w[0] = rover.Distribution() # assume stay for i in prior_distribution: obsFactor=observation_model(i) for j in obsFactor: if j in allObs[0]: w[0][i]=["no previous", np.log(prior_distribution[i])*np.log(obsFactor[j])] for i in range(num_time_steps- 1): w[i + 1] = rover.Distribution() trans = rover.Distribution() for j in w[i]: tempTrans = transition_model(j) for k in tempTrans: #of n+1 # print(w[i][j]) maybeMax=np.log(tempTrans[k]) + w[i][j][1] if k in w[i + 1]: newMax = np.maximum(maybeMax, w[i + 1][k][1]) if newMax != w[i + 1][k][1]: trans[k] = [j, newMax] #newMax= np.maximum(np.log(tempTrans[k]) + w[i][j][1], w[i + 1][k][1]) else: trans[k] = [j, maybeMax] for j in trans: obsFactor=observation_model(j) for k in obsFactor: if k in allObs[i+1]: w[i + 1][j] = [trans[j][0], trans[j][1] + np.log(obsFactor[k])] # print(i, w[i], "transitions") # print (i+1,observations[i+1],w[i+1], "\n") # for i in range(100): # print(i, ". ", w[i]) for i in w[-1]: if w[-1][i][1] > maxLast: maxLast = w[-1][i][1] maxLastState = i estimated_hidden_states[-1] = maxLastState for i in range(num_time_steps - 2, -1, -1): estimated_hidden_states[i] = w[i + 1][estimated_hidden_states[i + 1]][0] # print (estimated_hidden_states[-1]) # TODO: Write your code here return estimated_hidden_states