【问题标题】:C++ PCA - Calculating covariance MATRIXC++ PCA - 计算协方差矩阵
【发布时间】:2014-04-25 19:30:22
【问题描述】:

我正在尝试在 C++ 中计算向量的协方差(矩阵)...

我进行了以下操作:

std::vector<std::vector<double> > data = { {2.5, 2.4}, {0.5, 0.7} };

然后我计算并减去平均值,得到以下结果:

data = { {0.05, -0.05}, {-0.1, 0.1} }

据我所知,下一步是转置矩阵,将原点相乘,求和,最后除以维度 X - 1..

我写了以下内容:

void cover(std::vector<std::vector<double> > &d)
{
    double cov = 0.0; 

    for(unsigned i=0; (i < d.size()); i++)
    {
        for(unsigned j=0; (j < d[i].size()); j++)
        {
            cov += d[i][j] * d[j][i] / (d[i].size() - 1);
            std::cout << cov << " ";
        }
        std::cout << std::endl;
    }
}

其中d 是从每个点中减去平均值后的向量 这给了我结果:

0.0025, 0.0075 
0.0125, 0.0225

与matlab相比:

2.0000    1.7000
1.7000    1.4450

有人知道我哪里出错了吗?

谢谢

【问题讨论】:

  • 如果你用铅笔和纸完成算法中的步骤,你会得到 Matlab 的结果吗?如果不是,请修复算法。如果是,请逐步调试,看看程序的结果何时与铅笔和纸上的结果不同。
  • 为什么不使用矩阵代数库,例如 Eigen?代码会更短更容易。无论如何,您可能需要一个库来计算特征向量。

标签: c++ matrix linear-algebra covariance


【解决方案1】:

此声明:

据我所知,下一步是转置矩阵,将原点相乘,求和,最后除以维度 X - 1..

还有这个实现:

cov += d[i][j] * d[j][i] / (d[i].size() - 1);

不要说同样的话。基于here的定义:

void outer_product(vector<double> row, vector<double> col, vector<vector<double>>& dst) {
    for(unsigned i = 0; i < row.size(); i++) {
        for(unsigned j = 0; j < col.size(); i++) {
            dst[i][j] = row[i] * col[j];
        }
    }
}

//computes row[i] - val for all i;
void subtract(vector<double> row, double val, vector<double>& dst) {
    for(unsigned i = 0; i < row.size(); i++) {
        dst[i] = row[i] - val;
    }
}

//computes m[i][j] + m2[i][j]
void add(vector<vector<double>> m, vector<vector<double>> m2, vector<vector<double>>& dst) {
    for(unsigned i = 0; i < m.size(); i++) {
        for(unsigned j = 0; j < m[i].size(); j++) { 
            dst[i][j] = m[i][j] + m2[i][j];
        }
    }
}

double mean(std::vector<double> &data) {
    double mean = 0.0;

    for(unsigned i=0; (i < data.size());i++) {
        mean += data[i];
    }

    mean /= data.size();
    return mean;
}

void scale(vector<vector<double>> & d, double alpha) {
    for(unsigned i = 0; i < d.size(); i++) {
        for(unsigned j = 0; j < d[i].size(); j++) {
            d[i][j] *= alpha;
        }
    }
}

因此,鉴于这些定义,我们可以计算协方差矩阵的值。

void compute_covariance_matrix(vector<vector<double>> & d, vector<vector<double>> & dst) {
    for(unsigned i = 0; i < d.size(); i++) {
        double y_bar = mean(d[i]);
        vector<double> d_d_bar(d[i].size());
        subtract(d[i], y_bar, d_d_bar);
        vector<vector<double>> t(d.size());
        outer_product(d_d_bar, d_d_bar, t);
        add(dst, t, dst);
    } 
    scale(dst, 1/(d.size() - 1));
}

【讨论】:

  • @aacomar - 嘿,谢谢,但这不起作用。我不明白你为什么这样做cov = (cov + d..?
  • 您指定操作的顺序是取总和,然后最后除以维度 X - 1。按照您的方式,总和更新为 after 除法.而且我知道这不是唯一必要的修复,算法本身不起作用。
  • 啊,这个问题可能与 stackoverflow.com/questions/3307082/… 重复。检查那里,看看它是否回答了你的问题。
  • 如果你看这里:github.com/liyanghua/Principal-component-analysis-/blob/master/… 这就是我正在做的事情。我只是不明白为什么我会得到如此错误的结果。
  • 啊,那是完全不同的野兽。我会修正我的答案以与之相对应。
【解决方案2】:

我认为可能是 outer_product 中的 For 循环是错误的:

void outer_product(vector<double> row, vector<double> col, vector<vector<double>>& dst) {
for(unsigned i = 0; i < row.size(); i++) {
    for(unsigned j = 0; j < col.size(); i++) {
        dst[i][j] = row[i] * col[j];
    }
}

我会改变i++ -> j++

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-13
    • 2015-03-31
    • 2011-05-23
    • 1970-01-01
    • 2011-09-18
    • 2018-08-25
    • 2011-11-25
    • 2012-11-22
    相关资源
    最近更新 更多