我有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;
}
}
Run Code Online (Sandbox Code Playgroud)
任何人都有想法如何优化它以使其更快?哦,mat是来自amlpp矩阵库的RealSparseMatrix.
UPDATE 代码在Linux上运行,具有4GB RAM和AMD Athlon II双核
更改前的运行时间:> 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);
}
}
Run Code Online (Sandbox Code Playgroud)
还要确保矩阵数据结构是合理的(例如,在步幅中访问的平面数组; 不是一堆动态分配的行).
另外,我认为第+ 1一个有点傻.你知道x -> x * log(x)在零极限为0时连续为零,所以你应该写:
double const pij = mat(i, j) / gfi;
if (pij != 0) { g += pij + log(pij); }
Run Code Online (Sandbox Code Playgroud)
实际上,您甚至可以for像这样编写第一个内部循环,避免在不需要时进行除法:
for (int j = 1; j <= N; ++j)
{
if (double pij = mat(i, j))
{
pij /= gfi;
g += pij * log(pij);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
313 次 |
| 最近记录: |