优化稀疏矩阵中的对数熵计算

Optimize log entropy calculation in sparse matrix

本文关键字:计算 优化      更新时间:2023-10-16

我有一个 3007 x 1644 维的术语和文档矩阵。我正在尝试为每个文档中的术语频率分配权重,因此我 http://en.wikipedia.org/wiki/Latent_semantic_indexing#Term_Document_Matrix 使用此对数熵公式(请参阅最后一行中的熵公式)。

我成功地做到了这一点,但我的代码运行了>7 分钟。代码如下:

int N = mat.cols();
for(int i=1;i<=mat.rows();i++){
    double gfi = sum(mat(i,colon()))(1,1); //sum of occurrence of terms
    double g =0;
    if(gfi != 0){// to avoid divide by zero error
        for(int j = 1;j<=N;j++){
            double tfij = mat(i,j);
            double pij = gfi==0?0.0:tfij/gfi;
            pij = pij + 1; //avoid log0
            double G = (pij * log(pij))/log(N);
            g = g + G;
        }
    }
    double gi = 1 - g;
    for(int j=1;j<=N;j++){
        double tfij = mat(i,j) + 1;//avoid log0
        double aij = gi * log(tfij);
        mat(i,j) = aij;
    }
}

有人知道我如何优化它以使其更快吗?Oh and mat 是来自 amlpp 矩阵库的 RealSparseMatrix。

更新代码在具有4gb RAM和AMD Athlon II双核的Linux mint上运行

更换前运行时间:>7分钟

@Kereks回答后:4.1秒

这是一个非常幼稚的重写,删除了一些冗余:

int const N = mat.cols();
double const logN = log(N);
for (int i = 1; i <= mat.rows(); ++i)
{
    double const gfi = sum(mat(i, colon()))(1, 1);  // sum of occurrence of terms
    double g = 0;
    if (gfi != 0)
    {
        for (int j = 1; j <= N; ++j)
         {
            double const pij = mat(i, j) / gfi + 1;
            g += pij * log(pij);
        }
        g /= logN;
    }
    for (int j = 1; j <= N; ++j)
    {
        mat(i,j) = (1 - g) * log(mat(i, j) + 1);
    }
}

还要确保矩阵数据结构是理智的(例如,大步访问的平面数组;不是一堆动态分配的行)。

另外,我认为第一个+ 1有点愚蠢。你知道x -> x * log(x)在零处是连续的,极限为零,所以你应该写:

double const pij = mat(i, j) / gfi;
if (pij != 0) { g += pij + log(pij); }

事实上,您甚至可以像这样编写第一个内部for循环,避免在不需要时进行除法:

        for (int j = 1; j <= N; ++j)
        {
            if (double pij = mat(i, j))
            {
                pij /= gfi;
                g += pij * log(pij);
            }
        }