示例#1
0
void ForwardBacktracker::forward_pass(uint start, uint end, uint seq_len, MDArray<eMISMASK> & mismask, bool multiply_by_parents) {
	// Set variables used in the forward algorithm
	uint slice_count = end - start;

	// Setup the forward array and the scales
	scales.clear();
	scales.reserve(slice_count);
	forward.set_shape(vec(slice_count, hidden_node_size));

	transition_matrices.clear();
	transition_matrices.reserve(slice_count);

	// Fill out the forward array
	for(uint i=0, l=start; i < slice_count; i++, l++) {
		DiscreteNode *node;
		MDArray<double> *cpd;
		vector<Node*> *nodes;

		// For the first slice in the network
		if(l==0 || i==0) {
			// Get the appropriate hidden node
			if(l==0) {
				node = hd_0;
				cpd = cpd_0;
			}
			else {
				node = hd_1;
				cpd = cpd_1;
			}

			// Get the values of the parents of the hidden node
			// (and remove the value of the hidden node)
			vector<double> dpv;
			vector<uint> ipv;

			node->parentmap.get(l, dpv);
			dpv.pop_back();
			toint(dpv, ipv);

			// Get the transition probability and store it in the forward array
			MDArray<double> *cpd_sliced = &cpd->get_view(ipv);
			forward.set(i, *cpd_sliced);

			// Store the transition matrix from a posible backtrack
			transition_matrices.push_back(cpd_sliced);
		}
		// For the remaining slices
		else {
			// Get the appropriate hidden node
			node = hd_1;

			// Get the values of the parents of the hidden node
			// (and remove the value of the hidden node)
			vector<double> dpv;
			vector<uint> ipv;

			node->parentmap.get(l, dpv);
			dpv.pop_back();
			dpv.erase(dpv.begin());
			toint(dpv, ipv);

			MDArray<double> *cpd_sliced = &cpd_1_swaped.get_view(ipv);

			// Store the transition matrix from a posible backtrack
			transition_matrices.push_back(cpd_sliced);

			// Multiply transitions probabilities P(HD_l = g | HD_{l-1} = h ) by the
			// forward values forward[i-1, g] and sum over node values of g

			// TODO: This can probably be done faster
			for(uint j=0; j < hidden_node_size; j++ ) {
				// Sum over the previous hidden value
				double sum = 0;
				for(uint k=0; k < hidden_node_size; k++ ) {
					sum += forward.get(i-1, k) * cpd_sliced->get(k, j);
				}
				forward.set(i, j, sum);
			}
		}

		// Multiply the forward value by the probability of the parents
		if(multiply_by_parents) {
			if(l==0)
				nodes = &nodes_0;
			else
				nodes = &nodes_1;

			for(vector<uint>::iterator parent=node->parents_1.begin(); parent < node->parents_1.end(); parent++) {
				double parent_likelihood = exp( (*nodes)[(*parent)]->get_slice_log_likelihood(l) );
				forward.get_view(i).multiply_inplace(parent_likelihood);
			}
		}

		// Multiply the forward values by the probability of the observed children
		// Note that the value of the hidden node is preserved in prev_node_value
		for(vector<Node*>::iterator child=node->children_1.begin(); child < node->children_1.end(); child++) {

			if (mismask.get(l, (*child)->node_index) == MOCAPY_OBSERVED) {
				// Get the original value of the hidden node
			 	vector<double> dpv;
				node->parentmap.get(l, dpv);

				// Multiply the forward vector with the likelihood values of the child
				for(uint j=0; j < hidden_node_size; j++ ) {
					node->parentmap.set(l, j);
					forward.get(i,j) *= exp( (*child)->get_slice_log_likelihood(l) );
				}

				// Restore the original value of the hidden node
				node->parentmap.set(l, dpv.back());
			}
		}

		// If the is the end slice but not the end of the DBN, take the next hidden value into account
		if(l==end-1 && l!=seq_len-1) {
			// The next node can only be hd_1
			vector<double> dpv;
			vector<uint> ipv;

			hd_1->parentmap.get(l+1, dpv);
			uint next_hidden_value = (uint)dpv.back();
			dpv.pop_back();
			dpv.erase(dpv.begin());
			toint(dpv, ipv);

			MDArray<double> * cpd_1_sliced = &cpd_1_swaped.get_view(ipv);

			// Multiply the forward vector with the probability of the transition to the next hidden state
			for(uint j=0; j < hidden_node_size; j++ ) {
				forward.get(i,j) *= cpd_1_sliced->get(j, next_hidden_value);
			}
		}

		// Scale forward to be a probability distribution (this is
		// allowed according to BSA sec. 3.6 (p. 78)
		vector<double> *column_i = (&(&forward.get_view(i))->get_values());
		double scale = 0;

		// Sum column i
		for(uint j=0; j < hidden_node_size; j++ ) {scale += (*column_i)[j];}

		// Normalise column i by it's sum
                bool observedNan=false;
		for(uint j=0; j < hidden_node_size; j++ ) {
                     (*column_i)[j] /= scale;
                     if (isnan((*column_i)[j])) 
                          observedNan = true;
                }

                if (observedNan) {
                     for(uint j=0; j < hidden_node_size; j++ ) {
                          (*column_i)[j] = 1.0/hidden_node_size;
                     }
                }

		// Save the scale
		scales.push_back(scale);
	}
}