在上节课的视频中
用梯度下降的方法最小化
逻辑回归中代价函数 J(θ)
在这段视频中
教你们一些
高级优化算法和一些
高级的优化概念
利用这些方法 我们就能够
使通过梯度下降
进行逻辑回归的速度
大大提高
而这也将使
算法更加适合解决
大型的机器学习问题
比如 我们有数目庞大的特征量
现在我们换个角度
来看什么是梯度下降
我们有个代价函数 J 而我们想要使其最小化
那么我们需要做的是
我们需要
编写代码
当输入参数 θ 时
它们会计算出两样东西
J(θ) 以及
J等于 0 1直到 n 时的
偏导数项
假设我们已经完成了
可以实现这两件事的代码
那么梯度下降所做的就是
反复执行这些更新
生成了这个叫做 data 的对象 是吧？
所以给出我们
用于计算这些的偏导数的代码
梯度下降法就把它插入
到这里 从而来更新参数 θ
因此另一种考虑
梯度下降的思路是
我们需要写出代码
来计算 J(θ)
这些偏导数 然后
把这些插入到梯度下降中
然后它就可以为我们最小化这个函数
对于梯度下降来说 我认为
从技术上讲 你实际并不需要编写代码
来计算代价函数 J(θ)
你只需要编写代码来计算导数项
但是 如果你希望
代码还要能够监控
这些 J(θ) 的收敛性
那么我们就
需要自己编写代码
来计算
代价函数和偏导数项
所以 在写完能够
计算这两者的代码之后
我们就可以使用梯度下降
但梯度下降并不是我们可以使用的唯一算法
还有其他一些算法
更高级 更复杂
如果我们能用
这些方法来计算
这两个项的话 那么这些算法
就是为我们优化
代价函数的不同方法
共轭梯度法 BFGS (变尺度法) 和
L-BFGS (限制变尺度法) 就是其中
一些更高级的优化算法
它们需要有一种方法来计算 J(θ)
以及需要一种方法
计算导数项
然后使用比梯度下降更复杂
的算法来最小化代价函数
这三种算法的具体细节
超出了本门课程的范畴
实际上你最后通常会
花费很多天
或几周时间研究这些算法
你可以专门学一门课来提高数值计算能力
不过让我来告诉你他们的一些特性
这三种算法有许多优点
一个是
使用这其中任何一个算法 你通常
不需要手动选择学习率 α
所以对于
这些算法的一种思路是 给出
计算导数项和代价函数的方法
你可以认为算法有一个智能的内部循环
而且 事实上 他们确实有一个智能的
内部循环
称为线性搜索(line search)算法 它可以自动
尝试不同的
学习速率 α 并自动
选择一个好的学习速率 α
因此它甚至可以
为每次迭代选择不同的学习速率
那么你就不需要自己选择
这些算法实际上在做
更复杂的事情 而不仅仅是
选择一个好的学习速率
所以它们往往最终
收敛得远远快于梯度下降
这些算法实际上在做
更复杂的事情 不仅仅是
选择一个好的学习速率
所以它们往往最终
比梯度下降收敛得快多了 不过
关于它们到底做什么的详细讨论
已经超过了本门课程的范围
实际上 我过去
使用这些算法
已经很长一段时间了 也许超过
十年了 使用得相当频繁
而直到几年前
我才真正
搞清楚
共轭梯度法 BFGS 和 L-BFGS的细节
因此 实际上完全有可能
成功使用这些算法
并应用于许多不同的学习
问题 而不需要真正理解
这些算法的内环间在做什么
如果说这些算法有缺点的话
那么我想说主要
缺点是它们比
梯度下降法复杂多了
特别是你最好
不要使用 L-BGFS BFGS这些算法
共轭梯度 L-BGFS BFGS
除非你是数值计算方面的专家
实际上
我不会建议你们编写
自己的代码来计算
数据的平方根或者
计算逆矩阵
因为对于这些算法我
还是会建议你直接使用一个软件库
所以 要求一个平方根
我们所能做的
就是调用一些
别人已经
写好用来计算数字平方根的函数
幸运的是 有 Octave 和
与它密切相关的 MATLAB 语言
我们将会用到它们
Octave 有一个非常
理想的库用于实现这些先进的优化算法
所以 如果你直接调用
它自带的库 你就能得到不错的结果
我必须指出
这些算法
实现得好或不好是有区别的
因此 如果你正在你的
机器学习程序中使用一种不同的语言
比如如果你正在使用
C C + + Java
等等 你
可能会想尝试一些
不同的库 以确保你找到一个
能很好实现这些算法的库
因为
在 L-BFGS 或者等高线梯度的
实现上
表现得好与不太好
是有差别的
因此现在让我们来说明
如何使用这些算法 我打算举一个例子
比方说 你有一个
含两个参数的问题
这两个参数是 θ0 和 θ1
那么你的成本函数
J(θ)等于 θ1
减去5的平方 再加上 θ2 减5的平方
因此 通过这个代价函数
你可以得到 θ1 和 θ2 的值
如果你将 J(θ) 最小化的话
那么它的最小值
将是 θ1
等于5 θ2 等于5
我知道你们当中
有些人比别人微积分更好
但是你应该知道代价函数 J 的导数
推出来就是这两个表达式
我已经写在这儿了
那么你就可以应用
高级优化算法里的一个
来最小化代价函数 J
所以 如果我们
不知道最小值
是5 5 但你想要
代价函数找到这个最小值
是用比如
梯度下降这些算法 但最好是用
比它更高级的算法
你要做的就是运行一个
像这样的 Octave 函数 那么我们
运行一个函数
比如 costFunction
这个函数的作用就是
它会返回两个值
第一个是 jVal 它是
我们计算的代价函数 J
所以说 jVal
等于 theta(1)
减5的平方加
theta(2) 减5的平方
这样就计算出这个代价函数
函数返回的第二个值是
梯度值
梯度值应该是
一个2×1的向量
梯度向量的两个元素
对应
这里的两个偏导数项
运行这个 costFunction 函数后
你就可以
调用高级的优化函数
这个函数叫 fminunc
它表示
Octave 里无约束最小化函数
调用它的方式如下
你要设置几个 options
这个 options 变量
作为一个数据结构可以存储你想要的 options
所以 GradObj 和 On
这里设置梯度目标参数为打开(on)
这意味着你现在确实要给这个算法提供一个梯度
然后设置最大
迭代次数 比方说 100
我们给出一个 θ 的猜测初始值
它是一个2×1的向量
那么这个命令就调用 fminunc
这个@符号表示
指向我们刚刚定义的
costFunction 函数的指针
如果你调用它
它就会
使用众多高级优化算法中的一个
当然你也可以把它当成梯度下降
只不过它能自动选择
学习速率α 你不需要自己来做
然后它会尝试
使用这些高级的优化算法
就像加强版的梯度下降法
为你找到最佳的 θ 值
让我告诉你它在 Octave 里什么样
所以我写了这个关于theta的
的 costFunction 函数 跟前面幻灯片中一样
它计算出代价函数 jval
以及梯度 gradient
gradient 有两个元素
是代价函数对于
theta(1) 和 theta(2) 这两个参数的
偏导数
现在 让我们切换到Octave窗口
我把刚刚的命令敲进去
options = optimset 这是
在我的优化算法的 options上
设置参数
的记号
这样就是100
次迭代
我现在要给我的算法提供梯度值
设置 theta 的初始值是一个2×1的零向量
这是我猜测的 theta 初始值
现在我就可以
写出三个返回值
[optTheta, functionVal, exitFlag] 等于
指向代价函数的指针 @costFunction
我猜测的初始值 initialTheta
还有options
如果我敲回车 这个就会运行优化算法
它很快返回值
这个格式很有意思
因为我的代码
是被缠住了
所以这个有点意思
完全是因为我的命令行被绕住了
不过这里只是
数字上的一些问题
把它看成是加强版梯度下降
它们找到 theta 的最优值
是 theta(1) 为5 theta(2) 也为5
这正是我们希望的
functionVal 的值
实际上是10的-30次幂
所以 这基本上就是0
这也是我们所希望的
exitFlag为1
这说明它的状态
是已经收敛了的
你也可以运行
help fminunc 命令
去查阅相关资料
以理解 exitFlag 的作用
exitFlag可以让你确定该算法是否已经收敛
这就是在 Octave 里运行这些算法的过程
哦对了 这里我得指出
用 Octave 运行的时候
向量θ的值 θ的参数向量
必须是 d 维的
d 大于等于2
所以 θ 仅仅是一个实数
因此如果它不是
一个至少二维的向量
或高于二维的向量
fminunc 就可能无法运算
因此如果你有一个
一维的函数需要优化
你可以查找 Octave 里 fminuc 函数的资料
来得到更多的细节
这就是我们如何优化
一个例子的过程 这是一个
简单的二次代价函数
我们如果把它应用到逻辑回归中呢
在逻辑回归中 我们有
一个参数向量 theta
我要混合使用
Octave 记号和数学符号
我希望这个写法很明确
我们的参数 theta
由 θ0 到 θn 组成
因为在 Octave 的标号中
向量的标号是从1开始的
在 Octave 里 θ0实际上
写成 theta(1)
因此用 theta(1) 表示第一个参数 θ0
然后有 theta(2)
接下来写到
theta(n+1) 对吧
这是因为 Octave 的记号
是向量从1开始的
而不是从0开始
因此 我们需要
做的是写一个
costFunction 函数 它为
逻辑回归求得代价函数
具体点说 costFunction 函数
需要返回 jVal 值
因此需要一些代码
来计算 J(θ)
我们也需要给出梯度值 gradient
那么 gradient(1)
对应用来计算代价函数
关于 θ0 的偏导数
接下去关于 θ1 的偏导数
依此类推
再次强调 这是 gradient(1)
gradient(2) 等等
而不是gradient(0) gradient(1)
因为 Octave 的标号
是从1开始 而不是从0开始的
我希望你们从这个幻灯片中
学到的主要内容是
你所要做的是
写一个函数 它能返回
代价函数值 以及梯度值
因此要把这个
应用到逻辑回归
或者甚至线性回归中
你也可以把这些优化算法用于线性回归
你需要做的就是输入
合适的代码来计算
这里的这些东西
现在你已经知道如何使用这些高级的优化算法
有了这些算法
你就可以使用一个
复杂的优化库
它让算法使用起来更模糊一点
more opaque and so
因此也许稍微有点难调试
不过由于这些算法的运行速度
通常远远超过梯度下降
因此当我有一个很大的
机器学习问题时
我会选择这些高级算法
而不是梯度下降
有了这些概念
你就应该能将逻辑回归
和线性回归应用于
更大的问题中
这就是高级优化的概念
在下一个视频
也就是逻辑回归这一部分的最后一个视频中
我想要告诉你如何
修改你已经知道的逻辑回归算法
然后使它在多类别分类问题中
也能正常运行 【教育无边界字幕组】翻译：御姐sama 校对：所罗门捷列夫 审核：Naplessss