• Matlab中用内建函数代替for循环


    在使用matlab进行矩阵计算的时候,经常会遇到要使用for循环的情况。但其实很多操作可以用内部的一些函数代替。 bsxfun, arrayfun, cellfun, spfun, structfun

    bsxfun:

    1
    C = bsxfun(fun,A,B)

    bsxfun可以对矩阵A和矩阵B进行对应元素的fun函数操作。其中,fun是任何标量输入输出的二元操作的函数,例如基本的加减乘除,三角函数,大小比较,以及其他任何符合条件的自定义函数。

    注意,fun不能是符号,例如+,*之类,这些符号都有对应的函数名。例如+ 对应 plus, >= 对应 ge,等等。可以通过matlab命令行输入

    help <运算符号>

    来查询。

    一般来说,如果两个矩阵一样大,我们可以直接通过 A+B 这样的方式一样实现,但是bsxfun有一个优点,就是当A,B中任何一维长度为1的时候,函数会自动将该维度和另一个矩阵对应维度的每一行(列)进行运算。如果我们自己进行这样的操作,我们或者要使用循环,或者要使用repmat来扩展矩阵,这都比bsxfun在底层内部实现慢很多,或者要消耗更多内存。

    网友提供了这样一个例子:假设我们有数据A和B, 每行是一个样本,每列是一个特征。我们要计算高斯核,既:

    k(||x-xc||)=exp{- ||x-xc||^2/(2*σ)^2) } 其中xc为核函数中心,σ为函数的宽度参数 , 控制了函数的径向作用范围。

    当然可以用双重for实现:

    1
    2
    3
    4
    5
    6
    K1 = zeros(size(A,1),size(B,1));
    for i = 1 : size(A,1)
    for j = 1 : size(B,1)
    K1(i,j) = exp(-sum((A(i,:)-B(j,:)).^2)/beta);
    end
    end

    使用2,000×1,000大小的A和B, 运行时间为88秒。

    考虑下面向量化后的版本:

    1
    2
    3
    sA = (sum(A.^2, 2));
    sB = (sum(B.^2, 2));
    K2 = exp(bsxfun(@minus,bsxfun(@minus,2*A*B', sA), sB')/beta);

    使用同样数据,运行时间仅0.85秒,加速超过100倍。

    arrayfun:

    1
    2
    [B1,...,Bm] = arrayfun(func,A1,...,An)
    [B1,...,Bm] = arrayfun(func,A1,...,An,Name,Value)

    这个函数可以直接对数组中的元素进行func函数操作。其中,func函数接受n个输入,m个输出。当输出可以进行合并的时候,可以设置 'UniformOutput' 为true,这样所有 A1..An经过func的第m个输出就会合并为一个数组 Bm,如果'UniformOutput'为false,表示不同输入元素对应的输出不能合并,这样每个Bm就会是一个cell。

    matlab的帮助里有个很好的例子,这里就不贴上来了。

    cellfun:

    1
    2
    [A1,...,Am] = cellfun(func,C1,...,Cn)
    [A1,...,Am] = cellfun(func,C1,...,Cn,Name,Value)

    和arrayfun的用法类似,不过是对cell的对应元素进行操作。

    structfun:

    1
    2
    [A1,...,An] = structfun(func,S)
    [A1,...,An] = structfun(func,S,Name,Value)

    类似的用法,对结构体S的所有域进行func操作。

    spfun:

    1
    f = spfun(fun,S)

    这个函数可以对一个稀疏矩阵S的每个有值的元素进行fun操作。

    这个函数的用途不仅仅是可以提升速度,更重要的是能够保持返回的f中,没有数据的地方依然为0. 例如:

    1
    2
    S = spdiags([1:4]',0,4,4)
    f = spfun(@exp,S)

    S =
    (1,1) 1
    (2,2) 2
    (3,3) 3
    (4,4) 4
    f =
    (1,1) 2.7183
    (2,2) 7.3891
    (3,3) 20.0855
    (4,4) 54.5982
    而直接运行

    1
    exp(S)

    的话,没有数据的地方都变成1了。

    1
    full(exp(S))

    ans =
    2.7183 1.0000 1.0000 1.0000
    1.0000 7.3891 1.0000 1.0000
    1.0000 1.0000 20.0855 1.0000
    1.0000 1.0000 1.0000 54.5982

  • 相关阅读:
    Access, SQL Server, and Oracle数据类型的对应关系
    [转]SQL Server 2005 从差异备份还原数据库
    疲惫
    关于在cmd命令里的路径包含空格的问题
    导Excel时的科学计数法问题
    [转]SQL SERVER 2005 备份与恢复简介
    [转]用C#创建Windows Service
    [转] vb.net option
    [转]sql server profiler only TrueType fonts are supported. this is not a truetype font
    进程、线程、协程之概念理解[转帖]
  • 原文地址:https://www.cnblogs.com/wangduo/p/5242921.html
Copyright © 2020-2023  润新知