CResultSet* CMulticlassModel::argmax(
		SGVector< float64_t > w,
		int32_t feat_idx,
		bool const training)
{
	CDotFeatures* df = (CDotFeatures*) m_features;
	int32_t feats_dim   = df->get_dim_feature_space();

	if ( training )
	{
		CMulticlassSOLabels* ml = (CMulticlassSOLabels*) m_labels;
		m_num_classes = ml->get_num_classes();
	}
	else
	{
		REQUIRE(m_num_classes > 0, "The model needs to be trained before "
				"using it for prediction\n");
	}

	int32_t dim = get_dim();
	ASSERT(dim == w.vlen)

	// Find the class that gives the maximum score

	float64_t score = 0, ypred = 0;
	float64_t max_score = -CMath::INFTY;

	for ( int32_t c = 0 ; c < m_num_classes ; ++c )
	{
		score = df->dense_dot(feat_idx, w.vector+c*feats_dim, feats_dim);
		if ( training )
			score += delta_loss(feat_idx, c);

		if ( score > max_score )
		{
			max_score = score;
			ypred = c;
		}
	}

	// Build the CResultSet object to return
	CResultSet* ret = new CResultSet();
	SG_REF(ret);
	CRealNumber* y  = new CRealNumber(ypred);
	SG_REF(y);

	ret->psi_pred = get_joint_feature_vector(feat_idx, y);
	ret->score    = max_score;
	ret->argmax   = y;
	if ( training )
	{
		ret->delta     = CStructuredModel::delta_loss(feat_idx, y);
		ret->psi_truth = CStructuredModel::get_joint_feature_vector(
					feat_idx, feat_idx);
		ret->score    -= SGVector< float64_t >::dot(w.vector,
					ret->psi_truth.vector, dim);
	}

	return ret;
}
Exemple #2
0
bool CGMM::train(CFeatures* data)
{
	ASSERT(m_n != 0);
	if (m_components)
		cleanup();

	/** init features with data if necessary and assure type is correct */
	if (data)
	{
		if (!data->has_property(FP_DOT))
				SG_ERROR("Specified features are not of type CDotFeatures\n");		
		set_features(data);
	}

	CDotFeatures* dotdata = (CDotFeatures *) data;
	int32_t num_vectors = dotdata->get_num_vectors();
	int32_t num_dim = dotdata->get_dim_feature_space();

	CEuclidianDistance* dist = new CEuclidianDistance();
	CKMeans* init_k_means = new CKMeans(m_n, dist);
	init_k_means->train(dotdata);
	float64_t* init_means;
	int32_t init_mean_dim;
	int32_t init_mean_size;
	init_k_means->get_cluster_centers(&init_means, &init_mean_dim, &init_mean_size);

	float64_t* init_cov;
	int32_t init_cov_rows;
	int32_t init_cov_cols;
	dotdata->get_cov(&init_cov, &init_cov_rows, &init_cov_cols);

	m_coefficients = new float64_t[m_coef_size];
	m_components = new CGaussian*[m_n];

	for (int i=0; i<m_n; i++)
	{
		m_coefficients[i] = 1.0/m_coef_size;
		m_components[i] = new CGaussian(&(init_means[i*init_mean_dim]), init_mean_dim,
								init_cov, init_cov_rows, init_cov_cols);
	}

	/** question of faster vs. less memory using */
	float64_t* pdfs = new float64_t[num_vectors*m_n];
	float64_t* T = new float64_t[num_vectors*m_n];
	int32_t iter = 0;
	float64_t e_log_likelihood_change = m_minimal_change + 1;
	float64_t e_log_likelihood_old = 0;
	float64_t e_log_likelihood_new = -FLT_MAX;

	while (iter<m_max_iter && e_log_likelihood_change>m_minimal_change)
	{
		e_log_likelihood_old = e_log_likelihood_new;
		e_log_likelihood_new = 0;

		/** Precomputing likelihoods */
		float64_t* point;
		int32_t point_len;

		for (int i=0; i<num_vectors; i++)
		{
			dotdata->get_feature_vector(&point, &point_len, i);
			for (int j=0; j<m_n; j++)
				pdfs[i*m_n+j] = m_components[j]->compute_PDF(point, point_len);
			delete[] point;
		}

		for (int i=0; i<num_vectors; i++)
		{
			float64_t sum = 0;

			for (int j=0; j<m_n; j++)
				sum += m_coefficients[j]*pdfs[i*m_n+j];

			for (int j=0; j<m_n; j++)
			{
				T[i*m_n+j] = (m_coefficients[j]*pdfs[i*m_n+j])/sum;
				e_log_likelihood_new += T[i*m_n+j]*CMath::log(m_coefficients[j]*pdfs[i*m_n+j]);
			}
		}

		/** Not sure if getting the abs value is a good idea */
		e_log_likelihood_change = CMath::abs(e_log_likelihood_new - e_log_likelihood_old);

		/** Updates */
		float64_t T_sum;
		float64_t* mean_sum;
		float64_t* cov_sum;

		for (int i=0; i<m_n; i++)
		{
			T_sum = 0;
			mean_sum = new float64_t[num_dim];
			memset(mean_sum, 0, num_dim*sizeof(float64_t));

			for (int j=0; j<num_vectors; j++)
			{
				T_sum += T[j*m_n+i];
				dotdata->get_feature_vector(&point, &point_len, j);
				CMath::add<float64_t>(mean_sum, T[j*m_n+i], point, 1, mean_sum, point_len);
				delete[] point;
			}

			m_coefficients[i] = T_sum/num_vectors;

			for (int j=0; j<num_dim; j++)
				mean_sum[j] /= T_sum;
			
			m_components[i]->set_mean(mean_sum, num_dim);

			cov_sum = new float64_t[num_dim*num_dim];
			memset(cov_sum, 0, num_dim*num_dim*sizeof(float64_t));

			for (int j=0; j<num_vectors; j++)
			{
				dotdata->get_feature_vector(&point, &point_len, j);	
				CMath::add<float64_t>(point, 1, point, -1, mean_sum, point_len);
				cblas_dger(CblasRowMajor, num_dim, num_dim, T[j*m_n+i], point, 1, point,
                    1, (double*) cov_sum, num_dim);
				delete[] point;
			}

			for (int j=0; j<num_dim*num_dim; j++)
				cov_sum[j] /= T_sum;

			m_components[i]->set_cov(cov_sum, num_dim, num_dim);

			delete[] mean_sum;
			delete[] cov_sum;
		}
		iter++;
	}

	delete[] pdfs;
	delete[] T;
	return true;
}