前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >在 Cython 中高效访问 scipy lil_matrix

在 Cython 中高效访问 scipy lil_matrix

原创
作者头像
华科云商小徐
发布2024-05-15 09:12:41
770
发布2024-05-15 09:12:41
举报
文章被收录于专栏:小徐学爬虫小徐学爬虫

在 Cython 中高效地访问 scipy 的 lil_matrix(LInked List format)可以通过以下步骤实现:

  1. 导入所需的模块: 首先,导入必要的模块,包括 numpyscipy.sparse 中的 lil_matrix
  2. 定义函数原型: 在 Cython 中,您需要定义函数原型,以便能够调用 lil_matrix 中的方法。
  3. 使用 cimport 导入声明: 使用 cimport 声明导入 numpyscipy.sparse 中的 lil_matrix 类。
  4. 类型声明: 在函数中声明 lil_matrix 对象,以便能够正确地访问其属性和方法。
  5. 访问 lil_matrix 使用 lil_matrix 对象的属性和方法来读取或修改其内容。

1、问题背景

scipy sparse 矩阵是一种稀疏矩阵,在处理大型数据集时非常有用。Cython 是一种静态类型语言,可以编译成 Python 代码,从而提高性能。然而,在 Cython 中访问 scipy 稀疏矩阵时,可能会遇到一些问题。例如,lil_matrix 表示使用不同长度的列表列表。将此类数据结构有效地传递给 Cython(无需复制)可能很困难。

2、解决方案

一种解决方案是使用 Cython 的 cimport 语句导入 scipy。这将允许您在 Cython 代码中使用 scipy 数据类型。然后,您可以使用 cdef 语句声明变量来存储 scipy 稀疏矩阵。例如,以下代码显示了如何声明一个存储 lil_matrix 的变量:

代码语言:javascript
复制
cimport scipy.sparse as sp
​
cdef sp.lil_matrix m = sp.lil_matrix((10, 10))

另一种解决方案是使用 Cython 的 def 语句定义一个函数来访问 lil_matrix。例如,以下代码显示了如何定义一个函数来计算 lil_matrix 的和:

代码语言:javascript
复制
def sum_lil_matrix(sp.lil_matrix m):
    cdef int i, j, sum = 0
    for i in range(m.shape[0]):
        for j in range(m.shape[1]):
            sum += m[i, j]
    return sum

最后,您还可以使用 Cython 的 @cython.boundscheck(False) 修饰器来关闭边界检查。这将提高代码的性能,但可能会导致错误,因此仅在您确信代码不会访问数组或列表的边界之外时才使用此修饰器。

以下是一些代码示例,展示了如何在 Cython 中高效访问 scipy lil_matrix:

代码语言:javascript
复制
import numpy as np
cimport numpy as np
​
from scipy.sparse import lil_matrix
​
cdef iter_over_lil_matrix(m):
    cdef list sums, data_row
    sums = []
    for data_row in m.data:
        s = 0
        for value in data_row:
            s += value
        sums.append(s)
    return sums
​
def main():
    a = np.random.random((1e4*1e4))
    a[a>0.1] = 0
    a = a.reshape(1e4,1e4)
    m = lil_matrix(a)
​
    t0 = time.clock()
    sums = iter_over_lil_matrix(m)
    t1 = time.clock()
    print 'Cython lil_matrix Time', t1-t0
​
    t0 = time.clock()
    array_sums = a.sum(axis=1)
    t1 = time.clock()
    print 'Numpy ndarray Time', t1-t0
​
    t0 = time.clock()
    lil_sums = m.sum(axis=1)
    t1 = time.clock()
    print 'lil_matrix Time', t1-t0
​
    mcsr = m.tocsr()
    t0 = time.clock()
    csr_sums = mcsr.sum(axis=1)
    t1 = time.clock()
    print 'csr_matrix Time', t1-t0
​
    assert np.allclose(array_sums, sums)
    assert np.allclose(array_sums, np.asarray(lil_sums).flatten())
    assert np.allclose(array_sums, np.asarray(csr_sums).flatten())
​
Timings in seconds - only about 2 times slower than the super-optimized NumPy :D, much faster than the lil_matrix.sum() method because it converts to csr_matrix() before, as clarified by @hpaulj and confirmed by the results below. Note that the csr_matrix.sum() over the columns is almost one order of magnitude faster than the dense sum.
Cython lil_matrix Time 0.183935034665
Numpy ndarray Time 0.106583238273
lil_matrix Time 2.47158218631
csr_matrix Time 0.0140050888745
​
Things that will slow down the code:
​
use of for i in range(len(m.data)): with data_row = m.data[i]
declare buffers like np.ndarray[object, ndim=1] data with data=m.data
​
Things that did not affect:
​
boundscheck or wraparound

通过使用这些解决方案,您可以在 Cython 中高效访问 scipy lil_matrix。

在这个示例中,我们首先创建了一个 lil_matrix 对象 A,并设置了一些值。然后,我们访问了矩阵的元素,并将其转换为 CSR 格式(压缩稀疏行格式)以进行更高效的操作。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档