如何矢量化方程?

9

我在观看Andrew Ng教授关于广义线性模型的讲座后,尝试实现Softmax回归算法来解决K分类问题。我认为我理解他所说的一切,直到我开始编写代码来实现Softmax回归的代价函数,如下所示:

Cost function for Softmax Regression with Weight Decay

我遇到的问题是试图找出一种向量化的方法。虽然我之前已经成功地对线性回归和逻辑回归进行了向量化,但是看到这个公式后,我陷入了困境。
虽然我很想为此找到一个向量化的解决方案(我意识到已经有类似的问题发布了: Softmax回归的向量化实现),但我更感兴趣的是,你们中的任何人能否告诉我一种(你自己的)将这样的方程系统地转换为向量化形式的方法。例如,对于那些在机器学习领域是专家或老手的人,当你第一次阅读文献中介绍的新算法,并看到它们以类似上面公式的符号写成时,你是如何将它们转换为向量化形式的?
我意识到自己可能会像一个学生问莫扎特:“你怎么弹钢琴这么好?”但我的问题仅仅是出于想要在这个领域变得更好的愿望,假设并非每个人都天生知道如何向量化方程,因此肯定有人想出了自己的系统,如果有,请分享!提前致谢!祝好!

你能提供GLM讲座的链接吗? - justis
1
感谢斯坦福大学Andrew Ng教授的机器学习课程提供的支持:http://cs229.stanford.edu/materials.html - GLM和Softmax回归材料位于第1讲的末尾。 - oort
2个回答

2

Octave自带的帮助文件中有这样一条目录:

19.1 基本向量化

在向量化方面,一个很好的近似目标是编写避免循环并使用整个数组操作的代码。举个简单的例子,考虑以下代码:

 for i = 1:n
   for j = 1:m
     c(i,j) = a(i,j) + b(i,j);
   endfor
 endfor

与简单得多的相比,

 c = a + b;

这不仅更易于撰写;也更容易进行内部优化。Octave将此操作委托给底层实现,其中包括使用特殊的向量硬件指令或甚至可能并行执行加法等优化。通常情况下,如果代码被向量化,底层实现在为了实现更快的执行而做出更多假设。

这对于具有“廉价”主体的循环特别重要。通常,仅向量化最内部的循环就足以获得可接受的性能。一个经验法则是,向量化主体的“顺序”应大于或等于封闭循环的“顺序”。

作为一个不太平凡的例子,可以用以下方式改写:

 for i = 1:n-1
   a(i) = b(i+1) - b(i);
 endfor

写作

 a = b(2:n) - b(1:n-1);

这展示了使用数组进行索引而不是循环索引变量的重要概念。同时,要大量使用布尔索引。如果需要测试条件,该条件也可以编写为布尔索引。例如,可以使用布尔索引代替

 for i = 1:n
   if (a(i) > 5)
     a(i) -= 20
   endif
 endfor

 a(a>5) -= 20;

利用“a>5”产生布尔索引的事实,尽可能使用逐元素向量运算符以避免循环(例如“.*”和“.^”)。

算术运算。对于简单的内联函数,“vectorize”函数可以自动完成此操作。

-- 内置函数:vectorize(FUN) 通过将所有出现的“”、“/”等替换为“.”、“./”等,创建内联函数FUN的矢量化版本。

 This may be useful, for example, when using inline functions with
 numerical integration or optimization where a vector-valued
 function is expected.

      fcn = vectorize (inline ("x^2 - 1"))
         => fcn = f(x) = x.^2 - 1
      quadv (fcn, 0, 3)
         => 6

 See also:  inline,  formula,
  argnames.

同时在这些逐元素运算中利用广播来避免循环和不必要的中间内存分配。

尽可能使用内置和库函数。内置和编译函数非常快。即使是m-file库函数,很可能已经优化过,或者将在以后的版本中进一步优化。

例如,甚至比

 a = b(2:n) - b(1:n-1);

is

 a = diff (b);

大多数 Octave 函数都是针对向量和数组参数编写的。如果你发现自己在编写一个非常简单操作的循环,那么很有可能已经存在这样一个函数。以下函数在向量化代码中经常出现:

  • Index manipulation

    * find
    
    * sub2ind
    
    * ind2sub
    
    * sort
    
    * unique
    
    * lookup
    
    * ifelse / merge
    
  • Repetition

    * repmat
    
    * repelems
    
  • Vectorized arithmetic

    * sum
    
    * prod
    
    * cumsum
    
    * cumprod
    
    * sumsq
    
    * diff
    
    * dot
    
    * cummax
    
    * cummin
    
  • Shape of higher dimensional arrays

    * reshape
    
    * resize
    
    * permute
    
    * squeeze
    
    * deal
    

请查看以下这些来自斯坦福机器学习维基的页面,以获取更多的指导和示例。

http://ufldl.stanford.edu/wiki/index.php/Vectorization

http://ufldl.stanford.edu/wiki/index.php/Logistic_Regression_Vectorization_Example

http://ufldl.stanford.edu/wiki/index.php/Neural_Network_Vectorization


2
这个看起来很难向量化,因为你在求和中进行了指数运算。我假设你正在计算任意幂次的e。你可以向量化表达式\sum \sum theta ^2的第二项,只需在matlab中使用.*运算符计算theta ^2即可enter link description here
同样适用于进入对数的比率的内部项。θ' x^(i)是可向量化的表达式。
您还可以从备忘录或动态编程技术中受益,并尝试重复使用e^θ' x^(i)的计算结果。
通常,在我的经验中,向量化的方法是首先让非向量化的实现工作。然后尝试向量化计算中最明显的部分。在每一步中微调您的函数,始终检查是否获得与非向量化计算相同的结果。此外,具有多个测试用例非常有帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接