我应该使用啥类型的稀疏向量?

Posted

技术标签:

【中文标题】我应该使用啥类型的稀疏向量?【英文标题】:What type of sparse vector should I use?我应该使用什么类型的稀疏向量? 【发布时间】:2019-04-23 20:47:04 【问题描述】:

数据

我有N 不同(排序的)索引向量(std::vector<unsigned int>)。索引在 [0; L-1]。以下是关于此数据的两条经验法则:

只有大约 0.1% 到 10% 的可能索引存在于任何地方 如果在给定向量中找到索引,则很可能会在其他向量中再次找到多次。

因此,带有N=10 向量和L = 200 的可能数据集可能是

45, 110, 119, 145, 170
9, 45, 110, 145, 178, 170
45, 145
45, 178, 183
45, 53, 110, 170
9, 119, 123, 179
9, 45, 119, 130, 131, 170, 190, 199
9, 45, 110, 170, 199
31, 45, 145
9, 178, 183

目标

我想计算每个索引的频率。我会做类似的事情

std::vector<double> computeFrequencies(std::vector<std::vector<unsigned int>>& data)

    assert(data.size() == N);

    std::vector<double> frequencies(L);
    for (unsigned Ni = 0 ; Ni < N ; Ni++)
    
        for (unsigned i = 0 ; i < data[Ni].size() ; i++)
        
            assert(data[Ni][i] < L)
            frequencies[data[Ni][i]]++;
        
    

    for (unsigned i = 0 ; i < L; i++)
    
        frequencies[i] /= (double) N;
    

    return(frequencies);    

然后我将再次循环通过函数computeFrequencies 返回的对象一次。

for (unsigned i = 0 ; i < L; i++)

    foo(frequencies[i]);

问题

对象frequencies 包含很多零,因此我应该使用稀疏向量。不过,我对稀疏矩阵的了解不多。我应该使用什么类型的稀疏向量?

我正在考虑使用boost::numeric::ublas::coordinate_matrix&lt;double&gt;&lt;double&gt;,因为当我遍历所有N 向量时,我会不断添加新的非零值,我认为坐标矩阵可以很好地处理这个问题。请注意,一般来说,对于这个函数,我更担心 RAM 的使用而不是计算时间。

【问题讨论】:

由于您的操作系统在实际写入内存页面之前可能不会支持任何分配实际内存页面(至少 Linux 的默认设置),我想说不要担心。如果您想分配一个 TB 并且只写入几 GB,并且您写入的内容实际上适合内存,那么不要担心虚拟内存大小。除非您真正使用它,否则它不花钱。 如果您只使用几 GB 的内存,那真的不值得大惊小怪,因为内存和计算之间的权衡通常是非常现实的。非常紧凑的结构往往更占用 CPU。非常稀疏的结构很容易访问。不过,如果您的结构非常稀疏,std::map 是一种选择。 【参考方案1】:

看起来稀疏向量表示不太适合您的问题。

按照您的描述完成任务:

    将已排序的向量合并为一个已排序的向量。此处不时弹出如何进行高效的 K 路合并:merging N sorted files using K way merge 遍历新向量并计算每个条目的重复次数(很容易,因为它们都会在一起)以获取您的频率和foo 它们。

您甚至可以同时执行这两个步骤,完全避免将数据复制到新结构中。

【讨论】:

以上是关于我应该使用啥类型的稀疏向量?的主要内容,如果未能解决你的问题,请参考以下文章

在 Pyspark ML 中的稀疏向量数据类型列上创建 Python 转换器

spark 类标签的稀疏 特征向量

向量、矩阵和数组数据类型有啥区别?

R中的向量和列表数据类型有啥区别?

OpenCV大型阵列类型Mat类

matlab中sparse函数要求数据是啥类型的?