VLFeat kmeans C API解释

时间:2015-02-10 17:39:14

标签: c++ c k-means vlfeat

我正在尝试使用VLFeat's kmeans implementation in C,但我很难理解它是如何运作的。

注意:我在C ++程序中使用C API,因此我在这里发布的任何代码都是C ++。此外,我正在使用Eigean标头库,因此这些Matrix数据类型来自这里。

示例和API中不清楚的事情是:

  1. 数据必须采用何种格式? kmeans库函数似乎需要一维数组,可以从矩阵的背景中获取。但是,这个矩阵需要是列主要还是行主要?也就是说,函数如何知道区分数据维度和不同的数据向量?
  2. 如何实际访问群集中心信息?我运行了一个测试,我宣布我想要5个集群,但是使用上面链接中的示例代码,我只返回1.
  3. 代码:

    int numData = 1000;
    int dims = 10;
    // Use float data and the L1 distance for clustering
    VlKMeans * kmeans = vl_kmeans_new (VL_TYPE_FLOAT,  VlDistanceL1) ;
    // Use Lloyd algorithm
    vl_kmeans_set_algorithm (kmeans, VlKMeansLloyd) ;
    // Initialize the cluster centers by randomly sampling the data
    Matrix<float, 1000,10, RowMajor> data = buildData(numData, dims);
    vl_kmeans_init_centers_with_rand_data (kmeans, data.data(), dims, numData, 5);
    // Run at most 100 iterations of cluster refinement using Lloyd algorithm
    vl_kmeans_set_max_num_iterations (kmeans, 100) ;
    vl_kmeans_refine_centers (kmeans, &data, numData) ;
    // Obtain the energy of the solution
    energy = vl_kmeans_get_energy(kmeans) ;
    // Obtain the cluster centers
    centers = (double*)vl_kmeans_get_centers(kmeans);
    cout << *centers << endl;
    

    示例输出:center = 0.0376879(标量)

    如何获得所有中心?我尝试使用数组存储中心,但它不接受该类型。

    我也尝试了以下内容,假设我可能只是错误地访问了中心信息:

    cout << centers[0]<< endl;
    cout << centers[1]<< endl;
    cout << centers[2]<< endl;
    cout << centers[3]<< endl;
    cout << centers[4]<< endl;
    cout << centers[5]<< endl;
    cout << centers[6]<< endl;
    cout << centers[7]<< endl;
    cout << centers[8]<< endl;
    

    但是对于索引0-4(给定5个聚类中心),我应该只有非零值。我实际上期望为更高的指数抛出异常。如果这是正确的方法,有人可以向我解释这些其他值(指数5-8)来自哪些?

    我确定还有其他令人困惑的部分,但我还没有解决它们,因为我一直被困在这两个非常重要的部分上(我的意思是什么是kmeans,如果你不能正确聚类到启动)。

    提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

  

数据必须采用何种格式?

manual说:

所有算法都支持floatdouble数据,并且可以使用l1或l2距离进行群集

您在创建kmeans句柄时指定,例如:

VlKMeans *kmeans = vl_kmeans_new(VL_TYPE_FLOAT, VlDistanceL2);
  

这个矩阵需要是列主要还是行主要?

必须在row major,即:data + dimension * i是第i个中心。

  

如何实际访问群集中心信息?

vl_kmeans_get_centers。例如,如果您使用float - s:

/* no need to cast here since get centers returns a `void *` */
const float *centers = vl_kmeans_get_centers(kmeans);

(请参阅此answer有关演员表)

此数组的总大小(以字节为单位)为sizeof(float) * dimension * numCenters。如果您想打印中心,可以这样做:

int i, j;
for (i = 0; i < numCenters; i++) {
  printf("center # %d:\n", i);
  for (j = 0; j < dimension; j++) {
    printf("    coord[%d] = %f\n", j, centers[dimension * i + j]);
  }
}