程序问答   发布时间:2022-06-01  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了删除 for 循环以加快执行速度 - 向量化大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决删除 for 循环以加快执行速度 - 向量化?

开发过程中遇到删除 for 循环以加快执行速度 - 向量化的问题如何解决?下面主要结合日常开发的经验,给出你关于删除 for 循环以加快执行速度 - 向量化的解决方法建议,希望对你解决删除 for 循环以加快执行速度 - 向量化有所启发或帮助;

作为我学术项目的一部分,我正在研究图像的线性过滤器。下面是代码,仅使用 NumPy(无外部库)并希望通过矢量化或任何其他选项来消除 for 循环。如何实现矢量化以加快执行速度?感谢您的帮助。

输入 -

  • Image.shape - (568,768)
  • weightArray.shape - (3,3)
    def apply_filter(image: np.array,weight_array: np.array) -> np.array:
        rows,cols = image.shape
        height,wIDth = weight_array.shape
        output = np.zeros((rows - height + 1,cols - wIDth + 1))
    
        for rrow in range(rows - height + 1):
            for ccolumn in range(cols - wIDth + 1):
                for hheight in range(height):
                    for wwIDth in range(wIDth):
                        imgval = image[rrow + hheight,ccolumn + wwIDth]
                        filterval = weight_arraY[hheight,wwIDth]
                        output[rrow,ccolumn] += imgval * filterval
                        
        return output

解决方法

您可以构建图像切片视图的数组,每个视图根据权重数组的索引进行移位,然后乘以权重并求和。

def apply_filter(image: np.array,weights: np.array) -> np.array:
    height,width = weights.shape
    inDices = np.inDices(weights.shapE).T.reshape(weights.size,2)
    views = np.array([image[r:-height+r,c:-width+c] for r,c in inDices])
    return np.inner(views.T,weights.T.flatten()).T  # sum product

(我必须在几个点上进行转置和重塑,才能将数据变成所需的形状和顺序。可能还有更简单的方法。)

仍然存在以列表推导形式对权重索引进行偷偷摸摸的 for 循环,但我们将 for 循环内的操作最小化以创建一组切片视图。使用 sliding_window_view 可以潜在地避免循环,但不清楚这是否会提高性能;或Stride_tricks.as_Strided(参见this question的答案)。

,

向量化是将每个显式 for 循环转换为一维数组操作的过程。 在 Python 中,这将涉及根据 slices 重新构想您的数据。

在下面的代码中,我提供了内核循环的工作向量化。这展示了如何进行矢量化,但由于它只是优化了 3x3 数组,因此不会为您提供最大的可用收益。

如果您想看到更大的改进,您可以对图像数组进行矢量化处理,我也为您制作了模板——但留下一些作为练习。

import numpy as np
from PIL import Image

## no vectorization
def applyFilterMethod1(image: np.array,weightArray: np.array) -> np.array:
    rows,cols = image.shape ; height,width = weightArray.shape
    output = np.zeros((rows - height + 1,cols - width + 1))

    for rrow in range(rows - height + 1):
        for ccolumn in range(cols - width + 1):
            for hheight in range(height):
                for wwidth in range(width):
                    imgval = image[rrow + hheight,ccolumn + wwidth]
                    filterval = weightArraY[hheight,wwidth]
                    output[rrow,ccolumn] += imgval * filterval
                    
    return output

## vectorize the kernel loop (~3x improvement)
def applyFilterMethod2(image: np.array,cols - width + 1))

    for rrow in range(rows - height + 1):
        for ccolumn in range(cols - width + 1):
            imgval = image[rrow:rrow + height,ccolumn:ccolumn + width]
            filterval = weightArraY[:,:]
            output[rrow,ccolumn] = sum(sum(imgval * filterval))
                    
    return output

## vectorize the image loop (~50x improvement)
def applyFilterMethod3(image: np.array,cols - width + 1))

    for hheight in range(height):
        for wwidth in range(width):
            imgval = 0 ## TODO -- construct a compatible slice
            filterval = weightArraY[hheight,wwidth]
            output[:,:] += imgval * filterval
                    
    return output

src = Image.open("input.png")
sb = np.asarray(srC)
cb = np.array([[1,2,1],[2,4,2],[1,1]])
cb = cb/sum(sum(cb)) ## normalize

db = applyFilterMethod2(sb,cb)

dst = Image.fromarray(db)
dst.convert("L").save("output.png")
#src.show() ; dst.show()

注意:您可能会移除所有四个 for 循环,但会增加一些额外的复杂性。但是,因为这只会消除 9 次迭代的开销(在本例中),我不估计它会产生超过 applyFilterMethod3 的任何额外性能提升。此外,然我还没有尝试过,但我想象的完成方式可能会增加比删除更多的开销。

仅供参:这是一个标准的图像卷积(仅支持已实现的灰度)。我总是想指出,为了在数学上是正确的,这需要补偿几乎所有默认图像编码中隐含的 gAMMa compression - 但这个小细节经常被忽略。


讨论

这种类型的向量化在 Python 中通常是必需的,特别是因为标准 Python 解释器在处理大型 for 循环时是 extremely inefficient。因此,显式迭代图像的每个像素会浪费大量时间。不过,归根结底,矢量化实现不会改变实际执行的工作量,因此我们只是在讨论消除算法的 overhead 方面。

然而,矢量化有一个副作用:Parallelization。将大量数据处理集中到单个运算符上,使语言/库在如何优化执行方面具有更大的灵活性。这可能包括在 GPU 上执行您的 embarrassingly parallel 操作——如果您拥有合适的工具,例如 Tensorflow image module。

Python 对 array progrAMMing 的无缝支持是它在机器学习中非常受欢迎的原因之一,机器学习可能是计算密集型的。


解决方案

这是 imgval值的解决方案,上面留作练习。

imgval = image[hheight:hheight+rows - height+1,wwidth:wwidth+cols - width +1]

大佬总结

以上是大佬教程为你收集整理的删除 for 循环以加快执行速度 - 向量化全部内容,希望文章能够帮你解决删除 for 循环以加快执行速度 - 向量化所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:-for删除