【问题标题】:Using NumPy functions in Cython for least-squares fitting of array elements在 Cython 中使用 NumPy 函数对数组元素进行最小二乘拟合
【发布时间】:2017-11-22 02:58:35
【问题描述】:

我需要编写一个脚本,对 4 个相似的 500x500 图像的堆栈逐个像素地进行最小二乘拟合。如中所示,我需要将所有四个图像上特定像素位置的值拟合为长度为 3 的向量,对每个像素使用相同的 4x3 矩阵。

如果不对每个像素进行嵌套的 for 循环迭代,我没有办法做到这一点,所以我认为 cython 可以加快速度。我以前从未使用过 cython,但我根据文档示例编写了以下代码。

问题是,它的运行速度与纯 python 实现(约 25 秒)一样慢或更慢(约 27 秒)。

有没有人看到是什么减慢了速度?谢谢!

import numpy as np
cimport numpy as np
cimport cython

npint = np.int16
npfloat = np.float64

ctypedef np.int16_t npint_t
ctypedef np.float64_t npfloat_t


@cython.boundscheck(False)
@cython.wraparound(False)

def fourbythree(np.ndarray[npfloat_t, ndim=2] U_mat, np.ndarray[npint_t, ndim=3] G):
    assert U_mat.dtype == npfloat and G.dtype == npint
    cdef unsigned int z = G.shape[0]
    cdef unsigned int rows = G.shape[1]
    cdef unsigned int cols = G.shape[2]
    cdef np.ndarray[npfloat_t, ndim= 3] a  = np.empty((z - 1, rows, cols), dtype=npfloat)
    cdef npfloat_t resid
    cdef unsigned int rank
    cdef Py_ssize_t row, col
    cdef np.ndarray s

    for row in range(rows):
        for col in range(cols):
            a[:, row, col] = np.linalg.lstsq(U_mat, G[:, row, col])[0]
    return a

【问题讨论】:

  • 我很快尝试使用 numba jit-compile 一个类似的函数(循环 lstsq),它的加速因子约为 7。所以肯定可以通过编译来加速它,但我不太了解 Cython,无法告诉你出了什么问题。
  • 你是如何准确计时的? 230ms 对于纯 Python 实现来说似乎太快了。我看到 compiled 版本的时间大约是 20 秒...
  • @kazemakase 我使用了 ipython 的 %timeit 命令。我刚刚意识到我在测试时在一个较小的阵列(50x50 图像)上运行了这些测试,我已经用新的时间更新了帖子以获取更大的阵列。仍然得到大约相同的时间。我会看numba,那可能更简单!

标签: python numpy cython least-squares


【解决方案1】:

您不需要迭代 - 您只需调用 lstsq 即可完成所有操作。 lstsq 允许第二个参数为 2D,在这种情况下,结果也是 2D。您的数组是 3D 的,但是您可以轻松地将其重新整形为 2D,然后将输出重新整形(并且重新整形基本上是免费的 - 它不需要复制数据):

a = np.linalg.lstsq(U_mat, G.reshape((G.shape[0],-1)))[0]
a = a.reshape((a.shape[0],G.shape[1],G.shape[2]))

这都是无类型的纯 Python 代码,因为这实际上不是任何索引,所以我不希望 Cython 提供帮助。

我从中获得了 400 倍的加速(尽管其中一些是因为“一次调用”版本似乎并行运行而 Cython 版本没有)。我认为加速的主要原因是重复调用 Python 函数的开销(鉴于它正在处理非常小的数组)。

【讨论】:

  • 这很好用,谢谢!我在早期测试过按原样传递它,但没想到只是重塑。
猜你喜欢
  • 1970-01-01
  • 2016-06-29
  • 2019-03-29
  • 1970-01-01
  • 2012-07-10
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 2013-01-21
相关资源
最近更新 更多