Octave:矢量化

0:00

在这段视频中 我将介绍有关向量化的内容无论你是用Octave还是别的语言 比如MATLAB或者你正在用PythonNumPy 或 Java C C++所有这些语言都具有各种线性代数库这些库文件都是内置的容易阅读和获取他们通常写得很好已经经过高度优化通常是数值计算方面的博士或者专业人士开发的而当你实现机器学习算法时如果你能好好利用这些线性代数库或者说数值线性代数库并联合调用它们而不是自己去做那些函数库可以做的事情如果是这样的话 那么通常你会发现 首先 这样更有效也就是说运行速度更快并且更好地利用你的计算机里可能有的一些并行硬件系统等等第二 这也意味着你可以用更少的代码来实现你需要的功能因此 实现的方式更简单代码出现问题的有可能性也就越小举个具体的例子与其自己写代码做矩阵乘法
如果你只在Octave中输入 a乘以b,就是一个非常有效的两个矩阵相乘的程序。
有很多例子可以说明如果你用合适的向量化方法来实现你就会有一个简单得多 也有效得多的代码让我们来看一些例子这是一个常见的线性回归假设函数如果你想要计算 h(x)注意到右边是求和那么你可以自己计算j =0 到 j = n 的和但换另一种方式来想想是把 h(x) 看作θ 转置乘以 x那么你就可以写成两个向量的内积其中 θ 就是θ0 θ1θ2 如果你有两个特征量如果 n 等于2 并且如果你把 x 看作x0 x1 x2这两种思考角度会给你两种不同的实现方式比如说这是未向量化的代码实现方式计算 h(x) 是未向量化的我的意思是 没有被向量化我们可能首先要初始化变量 prediction 的值为0.0而这个变量 prediction 的最终结果就是h(x) 然后我要用一个 for 循环j 取值 0 到 n+1变量prediction 每次就通过自身加上 theta(j) 乘以 x(j) 更新值这个就是算法的代码实现顺便我要提醒一下这里的向量我用的下标是 0所以我有 θ0 θ1θ2 但因为 MATLAB的下标从1开始 在 MATLAB 中 θ0我们可能会用 theta(1) 来表示这第二个元素最后就会变成theta(2) 而第三个元素最终可能就用theta(3) 表示 因为MATLAB 中的下标从1开始即使我们实际的θ 和 x 的下标从0开始这就是为什么这里我的 for 循环j 取值从 1 直到 n+1而不是从 0 到 n 清楚了吗?但这是一个未向量化的代码实现方式我们用一个 for 循环对 n 个元素进行加和作为比较 接下来是向量化的代码实现你把x 和 θ看做向量 而你只需要令变量 prediction 等于 theta转置乘以 x 你就可以这样计算与其写所有这些for 循环的代码你只需要一行代码这行代码右边所做的就是利用 Octave 的高度优化的数值线性代数算法来计算两个向量的内积θ 以及 x这样向量化的实现不仅仅是更简单它运行起来也将更加高效

4:15

这就是 Octave 所做的而向量化的方法在其他编程语言中同样可以实现让我们来看一个 C++ 的例子这就是未向量化的代码实现的样子我们再次初始化变量 prediction 为 0.0然后我们现在有一个完整的从 j 等于 0 直到 n变量 prediction +=theta 乘以 x再一次 你有这样的自己写的 for 循环与此相反 使用一个比较好的C++ 数值线性代数库你就可以用这个方程来写这个函数与此相反 使用较好的C++ 数值线性代数库你可以写出像这样的代码因此取决于你的数值线性代数库的内容你可以有一个对象 (object)像这个C++ 对象theta 和一个 C++对象 向量 x你只需要用 theta.transpose ( )乘以 x而这次是让 C++ 来实现运算因此你只需要在 C++ 中将两个向量相乘根据你所使用的数值和线性代数库的使用细节的不同你最终使用的代码表达方式可能会有些许不同但是通过一个库来做内积你可以得到一段更简单更有效的代码现在 让我们来看一个更为复杂的例子提醒一下这是线性回归算法梯度下降的更新规则所以我们用这条规则对 j 等于 0 1 2 等等的所有值更新 对象 θj我只是用 θ0 θ1 θ2来写方程那就是假设我们有两个特征量所以 n等于2这些都是我们需要对θ0 θ1 θ2 进行更新你可能还记得在以前的视频中说过这些都应该是同步更新因此 让我们来看看我们是否可以拿出一个向量化的代码实现这里是和之前相同的三个方程只不过写得小一点而已你可以想象实现这三个方程的方式之一就是用一个 for 循环就是让 j 等于0等于 等于2来更新 θj但让我们用向量化的方式来实现 看看我们是否能够有一个更简单的方法基本上用三行代码或者一个 for 循环一次实现这三个方程让我们来看看怎样能用这三步并将它们压缩成一行向量化的代码来实现做法如下我打算把 θ 看做一个向量然后我用θ 减去α 乘以 某个别的向量δ 来更新 θ这里的 δ 等于m 分之 1对 i=1 到 m进行求和然后这个表达式对吧?让我解释一下是怎么回事在这里 我要把θ 看作一个向量有一个 n+1 维向量我是说 θ 被更新我们的 n+1 维向量α 是一个实数δ 在这里是一个向量所以这个减法运算是一个向量减法没问题吧 ?因为 α 乘以 δ是一个向量 所以θ 就是θ 减去 α 乘以 δ 得到的向量那么什么是向量 δ 呢 ?嗯 向量 δ 是这样子的这部分实际上代表的就是这部分内容具体地说 δ 将成为n+1 维向量并且向量的第一个元素就等于这个所以我们的 δ如果要写下标的话就是从零开始 δ0 δ1 δ2我想要的是δ0 等于这个第一行绿色框起来的部分事实上 你可能会写出 δ0 是m 分之 1乘以 h(x(i))减去 y(i)乘以 x(i)0 的求和所以让我们在同一页上计算真正的 δδ 就是 m 分之 1乘以这个和那这个和是什么 ?嗯 这一项是一个实数这里的第二个项 是 x(i)这一项是一个向量对吧 ? 因为 x(i)可能是一个向量这将是x(i)0 x(i)1 x(i)2 对吧 ?那这个求和是什么 ?嗯 这个求和就是这里的式子这里的这一项等于 h(x(1)) - y(1) 乘以 x(1)加上h(x(2)) - y(2) 乘以 x(2)依此类推对吧 ?因为这是对 i 的加和所以当 i 从 1 到 m你就会得到这些不同的式子 然后作加和每个式子的意思很像如果你还记得实际上在以前的一个小测验 如果你要解这个方程我们说过为了向量化这段代码我们会令 u = 2v +5w 因此我们说 向量u等于2乘以向量v加上 5乘以向量 w用这个例子说明如何对不同的向量进行相加这里的求和是同样的道理这一部分只是一个实数就有点像数字 2而这里是别的一些数字来乘以向量x1这就像是 2v只不过用别的数字乘以 x1然后加上 你知道不是5w 而是用别的实数乘以一个别的向量 然后你加上其他的向量这就是为什么总体而言在这里 这整个量δ 就是一个向量具体而言对应这三个 δ 的元素如果n等于2δ 的三个元素一一对应这个第二个 以及这第三个式子 这就是为什么当您更新 θ 值时 根据θ - αδ 这个式子我们最终能得到完全符合最上方更新规则的同步更新我知道幻灯片上的内容很多但是再次重申请随时暂停视频我也鼓励你一步步对比这两者的差异如果你不清楚刚才的内容我希望你能一步一步读幻灯片的内容以确保你理解为什么这个式子用 δ 的这个定理定义的 好吗 ?以及它为什么和最上面的更新方式是等价的为什么是这样子的就是这里的式子这就是向量 x而我们只是用了你知道这三个计算式并且压缩成一个步骤用这个向量 δ这就是为什么我们能够向量化地实现线性回归所以 我希望步骤是有逻辑的请务必看视频 并且保证你确实能理解它如果你实在不能理解它们数学上等价的原因你就直接实现这个算法也是能得到正确答案的所以即使你没有完全理解为何是等价的 如果只是实现这种算法你仍然能实现线性回归算法所以如果你能弄清楚为什么这两个步骤是等价的那我希望你可以对向量化有一个更好的理解以及 最后如果你在实现线性回归的时候使用一个或两个以上的特征量有时我们使用几十或几百个特征量来计算线性归回当你使用向量化地实现线性回归通常运行速度就会比你以前用你的 for 循环快的多也就是自己写代码更新 θ0 θ1 θ2因此使用向量化实现方式你应该是能够得到一个高效得多的线性回归算法而当你向量化我们将在之后的课程里面学到的算法这会是一个很好的技巧无论是对于 Octave 或者一些其他的语言 如C++Java 来让你的代码运行得更高效

你可能感兴趣的:(Octave:矢量化)