Scipy基础稀疏矩阵

2023年 9月 16日 67.5k 0

稀疏矩阵是一种特殊的矩阵,其非零元素数目远远少于零元素数目,并且非零元素分布没有规律。这种矩阵在实际应用中经常出现,例如在物理学、图形学和网络通信等领域。

稀疏矩阵其实也可以和一般的矩阵一样处理,之所以要把它区分开来进行特殊处理,是因为:一方面稀疏矩阵的存储空间开销通常比稠密矩阵要小得多,可以节省存储空间;另一方面,在计算稀疏矩阵时,可以利用其特殊的结构,采用专门的算法,提高计算效率和准确性。因此,稀疏矩阵在Scipy库中被单独作为一个模块,以便被更好地处理和应用。

1. 主要功能

稀疏矩阵子模块(scipy.sparse)的主要功能包括:

类别 说明
稀疏数组类 支持各种格式的稀疏数组
稀疏矩阵类 支持各种格式的稀疏矩阵
稀疏矩阵工具 构建,保存,加载以及识别稀疏矩阵的各种函数
其他 包含压缩稀疏图例程,稀疏线性代数等子模块,以及一些异常处理方法

这里有个需要注意的地方是稀疏数组和稀疏矩阵的区别。这两个类别中的很多函数名称也类似,比如:bsr_arraybsr_matrixcoo_arraycoo_matrix等等。

只要区别在于:***_matrix类的函数是一种基于Compressed Sparse Row(CSR)和Compressed Sparse Column(CSC)格式的块稀疏矩阵表示方法。它使用一个字典来存储非零元素,其中每个元素对应于一个包含三个值的元组,分别表示该元素的行索引、列索引和非零元素的值。这种数据结构可以提供更好的计算性能和内存使用效率,特别适合于大规模的块稀疏矩阵计算。

***_array 类的函数虽然类似于***_matrix的数据结构,但它允许更大的灵活性。***_array 可以表示任意的稀疏数组,而不仅仅是块稀疏矩阵。它使用一个具有三个数组的元组来表示稀疏数组,其中第一个数组存储行索引,第二个数组存储列索引,第三个数组存储非零元素的值。这种数据结构适用于更通用的稀疏数组计算,但可能不如***_matrix高效。

总之,***_matrix***_array都是用于表示块稀疏矩阵或稀疏数组的数据结构。***_matrix更适合于大规模的块稀疏矩阵计算,而***_array适用于更通用的稀疏数组计算。

2. 使用示例

稀疏矩阵之所以成为单独的一个模块,是因为它的稀疏的特性在很多领域多有广泛的应用。scipy.sparse子模块中提供了大概7种:

  • csc_matrix: 压缩稀疏列格式(Compressed Sparse Column)
  • csr_matrix: 压缩稀疏行格式(Compressed Sparse Row)
  • bsr_matrix: 块稀疏行格式(Block Sparse Row)
  • lil_matrix: 列表格式的列表(List of Lists format)
  • dok_matrix: 键格式字典(Dictionary of Keys)
  • coo_matrix: 坐标格式(又名 IJV,三元组格式)
  • dia_matrix: 对角线格式(DIAgonal format)
  • 2.1. 使用稀疏矩阵

    稀疏矩阵其实在运算上和使用普通矩阵一样。首先,构造一个创建矩阵的方法create_matrix,这个方法会生成一个10x10的矩阵,方法的参数N表示随机在矩阵的N个位置中生成值。

    from scipy import sparse
    import numpy as np
    
    # 创建一个10x10矩阵,其中有值的元素不超过N个
    def create_matrix(N):
        data = np.zeros((10, 10))
    
        for _ in range(N):
            row = np.random.randint(0, 10, 1)
            col = np.random.randint(0, 10, 1)
            data[row, col] = np.random.randint(1, 100, 1)
    
        return data
    

    create_matrix创建的是普通矩阵,我们将生成的矩阵转换为稀疏矩阵后,计算方式差不多。

    # 创建两个普通矩阵
    m1 = create_matrix(8)
    m2 = create_matrix(6)
    
    # 计算点积
    m1.dot(m2) # 返回m1和m2的点积结果
    
    # 将普通矩阵变为稀疏矩阵
    #(这里的演示用了7种类型中的一种bsr)
    d1 = sparse.bsr_matrix(m1)
    d2 = sparse.bsr_matrix(m2)
    
    # 计算点积后,用toarray方法转换为二维数组
    d1.dot(d2).toarray()
    

    从上面的代码可以看出,用scipy.sparse中的稀疏矩阵和使用一般矩阵差不多。

    2.2. 稀疏矩阵的性能

    我们使用稀疏矩阵,就是因为其运算性能比使用一般矩阵强,否则还不如直接用一般矩阵。下面,简单测试下scipy.sparse模块下稀疏矩阵的性能。

    先看其内存占用是否有减少,为了让性能差别能显著看出,先扩大测试矩阵为 1000x1000

    import sys
    
    def create_matrix(N):
        data = np.zeros((1000, 1000))
    
        for _ in range(N):
            row = np.random.randint(0, 1000, 1)
            col = np.random.randint(0, 1000, 1)
            data[row, col] = np.random.randint(1, 100, 1)
    
        return data
    
    m1 = create_matrix(8)
    m2 = create_matrix(6)
    
    d1 = sparse.csr_matrix(m1)
    d2 = sparse.csr_matrix(m2)
    
    print("一般矩阵 m1 占用的空间:{}".format(sys.getsizeof(m1)))
    print("一般矩阵 m2 占用的空间:{}".format(sys.getsizeof(m2)))
    print("一般矩阵 d1 占用的空间:{}".format(sys.getsizeof(d1)))
    print("一般矩阵 d2 占用的空间:{}".format(sys.getsizeof(d2)))
    # 运行结果:
    一般矩阵 m1 占用的空间:8000128
    一般矩阵 m2 占用的空间:8000128
    一般矩阵 d1 占用的空间:56
    一般矩阵 d2 占用的空间:56
    

    可以看出占用的空间明显缩小了。

    再看点积的运算性能:(运行10轮,每轮100次)

    %%timeit -r 10 -n 100
    m1.dot(m2)
    # 运行结果:
    10.6 ms ± 136 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)
    

    稀疏矩阵的点积运算:

    %%timeit -r 10 -n 100
    d1.dot(d2)
    # 运行结果:
    137 µs ± 14.3 µs per loop (mean ± std. dev. of 10 runs, 100 loops each)
    

    可以看出,运算性能差别非常大,一个是毫秒级别(10.6ms)的,一个是微秒级别(137 µs)的。

    3. 总结

    稀疏矩阵在矩阵中只是一种特殊的矩阵,然而在实际应用领域中,却应用极广,比如:在数值计算中,可以用于解决大规模线性代数方程组、大规模非线性方程组和非线性优化问题,以及求解大规模约束规划问题。

    在模式识别中,如人脸识别、手写数字识别、文本分类等任务,可用于表示高维数据,提取特征并进行降维,提高识别准确率和计算效率。

    在推荐系统中,处理大量用户和物品的数据时,稀疏矩阵可以有效地表示这些数据。

    在社交网络中,因为一般社交关系都是稀疏的,所以可用于分析社交网络的结构和行为,例如社区检测、影响力传播。

    此外,还可以用在计算机视觉,自然语言处理,生物信息学等等领域。所以,研究稀疏矩阵有其重要的实际意义。

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论