c++ - 为什么 Armadillo 无法学习高斯混合模型并提示 'no existing means' 尽管随机子集播种?

标签 c++ machine-learning gaussian armadillo

问题总结:

我有一个 [5 x 72580] 矩阵。我正在尝试使用以 random_subset 作为初始播种模式的 gmm_diag.learn() 方法将高斯混合模型 (GMM) 拟合到此数据。为什么 Armadillo 会显示“gmm_diag::learn(): no existing means”而无法学习模型?


问题详情:

我正在研究一种机器学习算法,其目的是根据作者的笔迹来识别作者。我正在使用监督学习通过 GMM 训练我们的模型。

所有训练数据都是从 XML 文件中读取的。计算完特征后,将它们的值存储到链表中。在此之后,列表中的元素数量被计算并用于在运行时初始化 Armadillo mat(rix) 变量,如下所示:

int totFeatureVectors = CountPointClusterElements(TRAINING_CLUSTER_LIST_INDEX);
printf("\n%d elements added to list\n",totFeatureVectors);

mat F = mat(NUM_POINT_BASED_FEATURES, totFeatureVectors, fill::zeros);

此处 TRAINING_CLUSTER_LIST_INDEX 和 NUM_POINT_BASED_FEATURES 是一对可配置的项目级常量;对于我的程序 NUM_POINT_BASED_FEATURES = 5 和 totFeatureVectors = 72580。因此变量 F 是一个 [5 x 72580] double 值的维矩阵。初始化后,我将链表中的特征值读取到 F 中,如下所示:

int rowInd=0, colInd=0;
PointClusterElement *iterator = allClusterPointsList;
while(iterator!=NULL)
{
    F(rowInd,colInd)=iterator->pointSample.speed;
    rowInd += 1;
    F(rowInd,colInd)=iterator->pointSample.dirn.cosComponent;
    rowInd += 1;
    F(rowInd,colInd)=iterator->pointSample.dirn.sinComponent;
    rowInd += 1;
    F(rowInd,colInd)=iterator->pointSample.curv.cosComponent;
    rowInd += 1;
    F(rowInd,colInd)=iterator->pointSample.curv.sinComponent;
    rowInd += 1;
    if(rowInd==NUM_POINT_BASED_FEATURES)
    {
        rowInd=0;
        colInd += 1;
    }
    iterator=iterator->nextClusterElement;
}

将特征值分配给 F 中的位置是以列为主的方式进行的,即 F 的每一列代表分配后的特征向量。我什至将 F 的值写入文本文件以验证是否已正确设置所有特征值,是的,它发生时没有任何问题

FILE *fp = fopen(PROGRAM_DATA_OUTPUT_PATH,"w");
if(fp!=NULL)
{
    int r,c;
    for(c=0; c<totFeatureVectors; c++)
    {
        for(r=0; r<NUM_POINT_BASED_FEATURES; r++)
        {
            fprintf(fp,"%lf\t",F(r,c));
        }
        fprintf(fp,"\n");
    }
}
fclose(fp);

到目前为止,还不错。但是在此之后,当我声明一个 gmm_diag 变量并尝试使用其 learn() 方法使 GMM 适合 F 时,程序显示警告“gmm_diag::learn(): no existing means”并退出,因此无法学习GMM(这里的 VARIANCE_FLOORING_FACTOR = 0.001)

gmm_diag writerModel;
bool result = writerModel.learn(F, 20, maha_dist, random_subset, 100, 100, VARIANCE_FLOORING_FACTOR, true);
writerModel.dcovs.print("covariances:\n");
writerModel.hefts.print("weights:\n");
writerModel.means.print("means:\n");
if(result==true)
{
    printf("\nModel learnt");
}
else if(result==false)
{
    printf("\nModel not learnt");
}

我在我的 IDE 上打开了 learn() 方法,据我所知,只有当初始播种模式为 keep_existing 时才会显示此错误(警告)消息。我提到的源文件位于/usr/include/armadillo_bits/gmm_diag_meat.hpp

我的问题是 - 为什么即使我使用 random_subset 模式完成播种也会发生这种情况?我究竟应该如何继续让我的模型学习?不确定我在这里遗漏了什么...... http://arma.sourceforge.net/docs.html#gmm_diag 提供的文档和代码示例没有太大帮助(这里的短程序即使没有初始化 GMM 的方法也能工作)。代码如下

int main(int argc, char** argv) {

int totFeatureVectors = CountPointClusterElements(TRAINING_CLUSTER_LIST_INDEX);
printf("\n%d elements added to list\n",totFeatureVectors);

mat F = mat(NUM_POINT_BASED_FEATURES, totFeatureVectors, fill::zeros);
int rowInd=0, colInd=0;
PointClusterElement *iterator = allClusterPointsList;
while(iterator!=NULL)
{
    F(rowInd,colInd)=iterator->pointSample.speed;
    rowInd += 1;
    F(rowInd,colInd)=iterator->pointSample.dirn.cosComponent;
    rowInd += 1;
    F(rowInd,colInd)=iterator->pointSample.dirn.sinComponent;
    rowInd += 1;
    F(rowInd,colInd)=iterator->pointSample.curv.cosComponent;
    rowInd += 1;
    F(rowInd,colInd)=iterator->pointSample.curv.sinComponent;
    rowInd += 1;
    if(rowInd==NUM_POINT_BASED_FEATURES)
    {
        rowInd=0;
        colInd += 1;
    }
    iterator=iterator->nextClusterElement;
}

FILE *fp = fopen(PROGRAM_DATA_OUTPUT_PATH,"w");
if(fp!=NULL)
{
    int r,c;
    for(c=0; c<totFeatureVectors; c++)
    {
        for(r=0; r<NUM_POINT_BASED_FEATURES; r++)
        {
            fprintf(fp,"%lf\t",F(r,c));
        }
        fprintf(fp,"\n");
    }
}
fclose(fp);

gmm_diag writerModel;
bool result = writerModel.learn(F, 20, maha_dist, random_subset, 100, 100, VARIANCE_FLOORING_FACTOR, true);
writerModel.dcovs.print("covariances:\n");
writerModel.hefts.print("weights:\n");
writerModel.means.print("means:\n");
if(result==true)
{
    printf("\nModel learnt");
}
else if(result==false)
{
    printf("\nModel not learnt");
}

getchar();
return 0;}

技术细节:

该程序正在使用 Netbeans 8.0.2 IDE 的 Ubuntu 14.04 操作系统上运行。该项目是一个C/C++应用程序

任何帮助将不胜感激!提前致谢 ~席德

最佳答案

您需要先尝试最简单的情况,以缩小错误的位置。你的代码当然不简单,而且它也不可重现(除了你没有人拥有所有的功能)。

以下简单代码有效,这表明该错误存在于您代码中的其他地方。

我怀疑您的代码正在某处覆盖内存,导致数据和/或代码损坏。该错误可能是指针不正确或指针使用不正确。

#include <fstream>
#include <armadillo>

using namespace std;
using namespace arma;

int main(int argc, char** argv) {

  mat F(5,72580, fill::randu);

  gmm_diag model;

  bool result = model.learn(F, 20, maha_dist, random_subset, 100, 100, 0.001, true);

  model.hefts.print("hefts:");
  model.means.print("means:");
  model.dcovs.print("dcovs:");

  return 0;
  }

以上代码的输出:

gmm_diag::learn(): generating initial means
gmm_diag::learn(): k-means: iteration:    1   delta: 0.343504
gmm_diag::learn(): k-means: iteration:    2   delta: 0.0528804
...
gmm_diag::learn(): k-means: iteration:  100   delta: 3.02294e-06
gmm_diag::learn(): generating initial covariances
gmm_diag::learn(): EM: iteration:    1   avg_log_p: -0.624274
gmm_diag::learn(): EM: iteration:    2   avg_log_p: -0.586567
...
gmm_diag::learn(): EM: iteration:  100   avg_log_p: -0.472182
hefts:
   0.0915   0.0335   0.0308   ...
means:
   0.4677   0.1230   0.8582   ...
   ...
dcovs:
   0.0474   0.0059   0.0080   ...
   ...

关于c++ - 为什么 Armadillo 无法学习高斯混合模型并提示 'no existing means' 尽管随机子集播种?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32524041/

相关文章:

c - 如何在局部敏感哈希中将 vector 哈希到桶中(使用杰卡德距离)?

image - 如何制作参数化高斯模糊?

Python:两个高斯与 np.convolve 卷积的结果函数的大小

c++ - 如何转发声明要在 unique_ptr 的标准容器中使用的类

c++ - 为什么我可以在没有前向声明的情况下调用函数模板?

c++ - C 中的 neo4j-client,语句中的原始类型编码(即 int)

R:XGBoost 和特征哈希。 MError不断增加

matlab - Matlab 中的逻辑回归梯度下降

matlab - 稀疏 GP 回归的初始种子

c++ - 删除控制台/cmd 提示符上闪烁的下划线