f(x) 在 x0 点可展开为幂级数 f(x)=∑∞i=0aif(x−x0)i ,则 f(x) 在 x0 的 N(x0,σ) 邻域内有任意阶导数,且系数 an=f(n)(x0)n! 。因此
称为 f(x) 在 x0 的泰勒级数,系数称为泰勒系数。当 x0=0 时,称为麦克劳林级数。
牛顿法的求根方法其实就是泰勒公式的一阶展开。
首先平方根的函数 y=x−−√ 构造以 y 为自变量的函数
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span style="font-family:Times New Roman;font-size:18px;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">sqrt</span>(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> x){ <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">double</span> y = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.0</span>; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">while</span>(<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">fabs</span>(y * y - x) >= <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1e-9</span>){ y = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5</span> * (y - x / y ); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 对应上面的公式</span> } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> y; }</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">1</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">2</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">3</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">4</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">5</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">6</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">7</span></li></ul>
魔数的平方根倒数算法。
<code class="hljs cpp has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span style="font-family:Times New Roman;font-size:18px;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> Q_rsqrt( <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> number ) { <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> i; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> x2, y; <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">const</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> threehalfs = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1.5F</span>; x2 = number * <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0.5F</span>; y = number; i = * ( <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">long</span> * ) &y; <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// evil floating point bit level hacking</span> i = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0x5f3759df</span> - ( i >> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span> ); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// what the fuck?</span> y = * ( <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">float</span> * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 1st iteration </span> <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> y; }</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">1</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">2</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">3</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">4</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">5</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">6</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">7</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">8</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">9</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">10</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">11</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">12</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">13</span></li><li style="box-sizing: border-box; padding: 0px 5px;"><span style="font-family:Times New Roman;font-size:18px;">14</span></li></ul>
首先求平方根的倒数 y=1x√ 可以构造以y为自变量的函数,由如下函数表示
y = y * ( threehalfs - ( x2 * y * y ) )
,但是由于那个魔数的存在,它只需要迭代一轮。
假设函数 u=f(x,y,z) 在 p(x,y,z) 可微,那么
方向导数就是函数在任意一个方向上的变化率。于是产生一个问题:函数沿着哪个方向变化的时候能够取得最大值?
求解:函数 u=f(x,y,z) 在沿着向量 l⃗ 的方向导数为
因此,梯度是一个矢量,它表示函数沿着该矢量的方向导数能够取得最大值,最大值为该矢量的模。
设损失函数为
沿着梯度的方向,函数可以取得极大值,因此梯度下降的公式为
其中的 η 表示步长
,或者叫学习率
,用来表示每次更新的程度。
缺点:每次迭代都需要计算全部的数据集,当数据集非常大的时候,计算效率就非常低。
即不是一次使用所有误分类点,而是随机选择一个误分类点进行梯度下降。
已知梯度下降公式为
不再使用全部的误分类点,而是随机选择一个误分类点的子集对w
和b
进行更新,极端的情况就是每次只选择一个误分类点。
这样,由于算法会由于在初始时选择初始值的不同,或者选择误分类点的顺序上的不同,导致最后得到的模型也会不一样。可以证明,误分类的次数是有限的,当训练数据集线性可分的时候,学习算法是收敛的。但当数据集线性不可分的时候,算法就不收敛了,迭代结果会发生震荡。
其实就是泰勒公式的二阶展开。
由于牛顿法需要计算目标函数的二阶偏导,且要求目标Hesse矩阵正定,难度比较大,因此有了拟合牛顿法。不过,不会用!
http://en.wikipedia.org/wiki/Quasi-Newton_method