Jiahong的个人博客

凡事预则立不预则废


  • Home

  • Tags

  • Archives

  • Search

Python——优先队列PriorityQueue

Posted on 2018-03-26

本文介绍Python中优先队列的用法

  • 注意: queue并不能算是Python标准库,所以在LeetCode等OJ环境中不能使用, 想要使用优先队列的话可以使用Python的标准库heapq
  • heapq的使用请参考 Python——heapq模块-最大堆最小堆

导入包

1
2
3
from Queue import PriorityQueue
# or
from queue import PriorityQueue
  • queue包名已经弃用,测试发现本地Python2.7环境可以用,但是LeetCode线上环境不能用
  • 推荐使用Queue

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from Queue import PriorityQueue

pq = PriorityQueue()

pq.put((10, "start"))
pq.put((5, "b", 12, 123))
pq.put((5, "a", 6))
pq.put(1)
pq.put(4)
pq.put([0, "a"])
pq.put([8, "b"])
pq.put("avb")
pq.put(None)

# while pq.not_empty()
# while not pq.empty()
while pq.qsize():
print pq.get()
# output:
None
1
4
[0, 'a']
[8, 'b']
avb
(5, 'a', 6)
(5, 'b', 12, 123)
(10, 'start')
  • 不能使用not pq这样的语句判断优先队列是否收敛,他不是普通的内嵌对象(list,str等是内嵌对象),除非pq == None否则,双端队列对象永远为not pq == False

  • 下面用法最优:

    1
    while pq.qsize():
  • PriorityQueue中默认递增排序(这一点与Python中的sorted函数和sort()函数一样),每次get(),移除并返回最小的对象

  • PriorityQueue中,可以同时添加不同类别的对象

  • PriorityQueue会将对象首先按照类别排序,然后各个类别内部按照不同数值排序

  • 若传入对象是可以直接比较大小的类型即可直接传入,包括tuple, list, str, int(long)等类型

    • Python中list,tuple,str等都是可以直接比较大小的,默认使用他们的第一个元素比较大小,如果第一个元素相等,则比较第二个元素,以此类推
    • 详细情况参考本文后面的说明

Python中的内嵌对象比较大小

  • Python中类别间也可以比较大小,默认类别间大小为:tuple > str > list > int(long) > None, 但是记不清楚的话不建议使用Python的这个特性,容易造成错误
  • Python中list,tuple,str等都是可以直接比较大小的,默认使用他们的第一个元素比较大小,如果第一个元素相等,则比较第二个元素,以此类推
  • Python中类别间也可以比较大小,默认类别间大小为:tuple > str > list > int(long) > None, 但是记不清楚的话不建议使用Python的这个特性,容易造成错误
    1
    2
    3
    4
    5
    ls = [(1, 'b'), (1, 'a'), (2, 'a'), [1, 'a'], [1, 'b'], [2, 'a'], '1a', '1b', '2a', 1, 2, 3, None]
    ls.sort()
    print ls
    # output
    [None, 1, 2, 3, [1, 'a'], [1, 'b'], [2, 'a'], '1a', '1b', '2a', (1, 'a'), (1, 'b'), (2, 'a')]

Python自定义对象比较大小

  • 在做算法题时,没必要的情况下不建议使用

  • 在做工程时建议使用这种方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    import Queue
    class Node():
    def __init__(self, val):
    self.val = val

    def __lt__(self, other):
    return self.val < other.val

    pq = Queue.PriorityQueue()
    pq.put(Node(5))
    pq.put(Node(1))

    while pq.qsize():
    print pq.get().val
    # output
    1
    5
  • 注意__lt__函数中是小于号,说明递增排序,大于号,说明递减排序

  • PriorityQueue对象不是普通Python内嵌对象,不能使用Python内嵌的len函数

Python——参数*args与**kwargs的意义***

Posted on 2018-03-26

Python中常常使用\args与**kwargs这样的参数形式定义函数的参数,他们表示该函数可以接受任何类型任何数量的参数*

  • 参考博客:https://blog.csdn.net/maliao1123/article/details/52152989

一句话解释

  • *args是非关键字参数,用于元
  • **kwargs是关键字参数,用于字典

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def test(*args, **kwargs):
print "args: ", args
print "kwargs: ", kwargs

test(1,2,3)
test(a=1, b=2)
test(1, a=2, c=2)
# output
args: (1, 2, 3)
kwargs: {}
args: ()
kwargs: {'a': 1, 'b': 2}
args: (1,)
kwargs: {'a': 2, 'c': 2}
  • 注意: 关键字参数后面不能有非关键字参数

    1
    test(1, a=1, 2)
    • 上面的函数调用会造成语法错误

总结

  • *args表示任何多个无名参数,它是一个tuple;
  • **kwargs表示关键字参数,它是一个dict
  • 同时使用*args和**kwargs时,必须*args参数列要在**kwargs前
    • 否则提示语法错误“SyntaxError: non-keyword arg after keyword arg”

Python——双端队列deque

Posted on 2018-03-26

本文介绍Python中双端队列(double-ended queue, 简称为deque)的用法


导入包

1
2
from collections import deque
import collections

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import collections
dq = collections.deque()
dq.append(3)
dq.append(4)
dq.append(1)
dq.appendleft(9)
dq.appendleft(10)
print dq
print dq.pop()
print dq
print dq.popleft()
print dq

while len(dq):
print dq.pop()


# output:
deque([10, 9, 3, 4, 1])
1
deque([10, 9, 3, 4])
10
deque([9, 3, 4])
4
3
9
  • 注意,deque没有qsize()函数,但是可以像普通队列一样使用Python内嵌的len函数

Python——关于列表list的操作

Posted on 2018-03-26

Python的list有很多强大的功能,有些比较罕见的操作可能很有用,需要我们记住

list的常见操作

list子列表
  • 注意使用子列表时是一个新对象,操作子列表与原始list无关
  • 在快速排序和归并排序中不可将子列表传入,以期待可以从函数中修改原始列表的值
list反序子列表
1
2
3
4
5
6
7
l = [1, 2, 3]
l1 = l[::-1]
print l
print l1
# output:
[1, 2, 3]
[3, 2, 1]

list的罕见操作

remove(object)
  • 移除列表中第一个与object相等的对象
    1
    2
    3
    4
    5
    6
    l = [1, 2, 2, 3, 4]
    l.remove(2)
    print l

    # output:
    [1, 2, 3, 4]
pop(index)
  • 从列表中移除一个元素,并返回该元素,index为索引
  • 默认移除最后一个
    1
    2
    3
    4
    5
    6
    7
    8
    l = [1, 2, 2, 3, 4, 5]
    l.pop(0)
    print l
    l.pop()
    print l
    # output:
    [2, 2, 3, 4, 5]
    [2, 2, 3, 4]

Python——装饰器decorator

Posted on 2018-03-26

Python中的装饰器可以在不修改原始函数代码的基础上,在Python函数中插入一些额外操作

  • 参考博客:https://ask.hellobi.com/blog/pythoneer

简单装饰器

  • 装饰器定义

    1
    2
    3
    4
    5
    def decorator(func):
    def wrapper(*args, **kwargs):
    print "decorator"
    return func(*args, **kwargs)
    return wrapper
  • 装饰器使用

    • 不带参数的函数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      @decorator
      def test():
      print "inner test"

      # just like a normal function
      test()

      # output:
      decorator
      inner test
    • 带参数的函数

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      @decorator
      def add(a, b):
      print "sum: ", a+b

      # just like a normal function
      add(10, 20)

      # output:
      decorator
      sum: 30

装饰器是一种语法糖

  • 实际上上面的代码等价于
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def test():
    print "inner test"

    test = decorator(test)

    # test is a normal
    test()

    # output:
    decorator
    inner test

带参数的装饰器

  • 需要对装饰器进一步的封装
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def outterDecorator(tag):
def decorator(func):
def wrapper(*args, **kwargs):
print "decorator: " + tag
return func(*args, **kwargs)
return wrapper
return decorator


@outterDecorator(tag="123")
def test():
print "inner test"


@outterDecorator("abc")
def add(a, b):
print "sum: ", a+b

test()

add(10, 20)
* 在原始的装饰器外面封装一层函数,用于接受参数,其他的不用改变
  • 理解:
    • 等价于给装饰器加了一层接受参数的外层空间
    • 实际上调用的时候除了参数外,其他的都没变
    • 被装饰的函数依然是被作为内层函数的参数传入装饰器中

类装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Foo(object):
def __init__(self, func):
self._func = func

def __call__(self):
print ('class decorator runing')
self._func()
print ('class decorator ending')

@Foo
def bar():
print ('bar')

bar()
  • 如上述代码所示,类装饰器必须有__init__和__call__两个函数
  • __init__负责接受被装饰函数作为参数并存储该函数
  • __call__负责执行函数调用过程并执行想要插入函数的代码
  • 被装饰的函数被调用时本质上是__call__函数被调用

类装饰器的优点

  • 灵活度高
  • 高内聚,不像函数一样定义在外面
  • 封装的好,容易阅读

多个装饰器的顺序问题

1
2
3
4
5
@a
@b
@c
def f ():
pass
  • 函数可以同时被多个装饰器修饰
  • 装饰器的顺序从靠近函数的那个开始从内向外一层层封装
    1
    f = a(b(c(f)))

装饰器对原始函数的属性修改

  • 涉及到docstring,__name__等属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 装饰器
    def logged(func):
    def with_logging(*args, **kwargs):
    print func.__name__ # 输出 'with_logging'
    print func.__doc__ # 输出 None
    return func(*args, **kwargs)
    return with_logging

    # 函数
    @logged
    def f(x):
    """does some math"""
    return x + x * x

    logged(f)
  • 使用functools.warps装饰器可以修复原始函数的文档

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from functools import wraps
    def logged(func):
    @wraps(func)
    def with_logging(*args, **kwargs):
    print func.__name__ # 输出 'f'
    print func.__doc__ # 输出 'does some math'
    return func(*args, **kwargs)
    return with_logging

    @logged
    def f(x):
    """does some math"""
    return x + x * x

property装饰器

  • 用于类的属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Student(object):
    def __init__(self, birth):
    self._birth = birth

    @property
    def birth(self):
    return self._birth

    @birth.setter
    def birth(self, value):
    self._birth = value

    @property
    def age(self):
    return 2014 - self._birth:
  • 当加上property装饰器后,函数就变成了一个只读属性,被修饰的函数不能再当成普通函数

    • 当前函数不能有参数,除非是默认参数,因为当前函数变成属性后,直接调用

      1
      s.birth(10)
      • 解析是s.birth返回一个属性值,然后,属性值不能被调用,所以抛出异常
  • property装饰器会生成两个新的装饰[method_name].setter和[method_name].getter,分别用于代表当前函数对应属性的的写和读功能,读的功能默认加上了,写的功能需要的话我们可以使用[method_name].setter装饰器实现

  • 总结: property装饰器可以将类的某个属性封装起来(在不暴露类属性的情况下提供getter方法和setter方法(后者需要自己显示定义))

ML——EM算法

Posted on 2018-03-15

期望最大化(Exception Maximization Algorithm)EM算法


不同教材的不同形式

李航统计学习方法

算法步骤
  • 输入: 观测变量数据Y

  • 输出: 模型(参数\(\theta\))

  • E步: 计算\(Q(\theta, \theta^{i})\)
    $$
    \begin{align}
    Q(\theta, \theta^{i}) &= E_{Z}[logP(Y,Z|\theta)|Y,\theta^{i}] \\
    &= E_{Z\sim P(Z|Y,\theta^{i})}[logP(Y,Z|\theta)] \\
    &= \sum_{Z} P(Z|Y,\theta^{i})logP(Y,Z|\theta) \\
    &= \sum_{Z} logP(Y,Z|\theta)P(Z|Y,\theta^{i})
    \end{align}
    $$

  • M步: 求使得\(Q(\theta, \theta^{i})\)极大化的参数\(\theta=\theta^{i+1}\)
    $$\theta^{i+1} = \arg\max_{\theta}Q(\theta, \theta^{i})$$

  • 重复E步和M步,直到收敛

  • 理解: \(Q(\theta, \theta^{i})\)可以理解为\(Q(\theta|\theta^{i})\),表示在参数\(\theta^{i}\)已知的情况下,对数似然函数关于隐变量后验分布的期望函数,函数的参数为\(\theta\)

隐变量的期望还是分布?

参考博客:https://www.jianshu.com/p/c3ff1ae5cb66

仅考虑隐变量的期望
  • 应用场景为k-means聚类,但是k-means聚类E步求的是最可能的\(Z\)值(概率最大的\(Z\)值),而不是\(Z\)的期望
步骤 具体细节
E步 基于\(\theta^{i}\)推断隐变量\(Z\)的期望,记为\(Z^{i}\)
M步 基于已观测变量\(Y\)和\(Z^{i}\)对参数\(\theta\)做极大似然估计,得到\(\theta^{i+1}\) $$\theta^{i+1}=\arg\max_{\theta}P(Y,Z^{i}\mid\theta)$$
考虑隐变量的分布
  • 应用场景为GMM模型聚类
步骤 具体细节
E步 基于\(\theta^{i}\)推断隐变量\(Z\)的后验分布\(P(Z\mid Y,\theta^{i})\)
E步M步均可 基于隐变量的后验分布\(P(Z\mid Y,\theta^{i})\)
计算对数似然函数\(logP(Y,Z\mid\theta)\)关于隐变量\(Z\)的后验分布\(P(Z\mid Y,\theta^{i})\)的期望\(Q(\theta,\theta^{i})\)
$$Q(\theta,\theta^{i}) = E_{P(Z\mid Y,\theta^{i})}logP(Y,Z\mid \theta)$$
M步 基于期望函数\(Q(\theta, \theta^{i})\),对参数\(\theta\)求极值(极大似然估计),得到$$\theta^{i+1}=\arg\max_{\theta}Q(\theta, \theta^{i})=\arg\max_{\theta}E_{P(Z\mid Y,\theta^{i})}logP(Y,Z\mid \theta)$$
推导
  • 已知数据是观测数据Y,像极大似然法一样,使得似然函数最大化即可,这里为了方便计算使用对数似然

  • 我们的终极目标与极大似然法一样,求一个使得似然函数最大(可能是极大)的参数$$\theta^{\star}=\arg\max_{\theta}L(\theta)$$
    其中
    $$
    \begin{align}
    L(\theta)&=logP(Y|\theta)\\
    &=log\sum_{Z}P(Y,Z|\theta)\\
    &=log\left(\sum_{Z}P(Y|Z,\theta)P(Z|\theta)\right)
    \end{align}
    $$

  • 显然,上述似然函数比较难以求解,非凸,且涉及和(积分或加法)的对数等操作,难以展开(可能还有其他的原因)

  • 所以我们使用EM算法迭代不断逼近原始似然函数的最优解\(\theta^{\star}\)(注意:我们只能得到局部最优,但是一般来说局部最优也够用了)

  • 可用Jensen不等式得到\(L(\theta)\)的下界来作为优化目标不断迭代
    $$
    \begin{align}
    L(\theta)&=log\left(\sum_{Z}P(Y|Z,\theta)P(Z|\theta)\right)\\
    &=log\left(\sum_{Z}P(Z|Y,\theta^{i})\frac{P(Y|Z,\theta)P(Z|\theta)}{P(Z|Y,\theta^{i})}\right)\\
    &\geq \sum_{Z}P(Z|Y,\theta^{i})log\frac{P(Y|Z,\theta)P(Z|\theta)}{P(Z|Y,\theta^{i})}\\
    &=B(\theta,\theta^{i})
    \end{align}
    $$

  • 由于此时\(B(\theta, \theta^{i})\)是\(L(\theta)\)的下界(\(B(\theta, \theta^{i})\)是固定\(\theta^{i}\)时关于\(\theta\)的凸函数且容易求导,可以求极大值),所以使得前者增大的参数\(\theta\)也能使得后者增大,为了使得后者尽可能的增大,我们对前者取极大值

    • 下面的推导基于事实: 消去与\(\theta\)无关的项,极大值点(\(\theta^{i+1}\))不变

$$
\begin{align}
\theta^{i+1} &= \arg\max_{\theta}B(\theta,\theta^{i})\\
&=\arg\max_{\theta}\left( \sum_{Z}P(Z|Y,\theta^{i})log\frac{P(Y|Z,\theta)P(Z|\theta)}{P(Z|Y,\theta^{i})}\right)\\
&=\arg\max_{\theta}\left( \sum_{Z}P(Z|Y,\theta^{i})logP(Y|Z,\theta)P(Z|\theta)-\sum_{Z}P(Z|Y,\theta^{i})logP(Z|Y,\theta^{i})\right)\\
&= \arg\max_{\theta}\left( \sum_{Z}P(Z|Y,\theta^{i})logP(Y|Z,\theta)P(Z|\theta)\right)\\
&=\arg\max_{\theta}Q(\theta,\theta^{i})
\end{align}
$$

  • 由上式可知,我们的EM算法步骤中E步和M步是正确的
  • 问题:推导第二步中为什么选择\(P(Z|Y,\theta^{i})\)而不是其他分布呢?
    • 解答: \(B(\theta, \theta^{i})\)和\(L(\theta)\)什么时候相等呢?(前面推导中Jensen不等式什么时候能取等号呢?)
    • Jensen不等式取等号当且仅当Jensen不等式中函数的值为常数,此处函数的值为\(log\frac{P(Y,Z|\theta)}{Q(Z)}\)
      $$
      \begin{align}
      L(\theta)&=log\left(\sum_{Z}P(Y,Z|\theta)\right)\\
      &=log\left(\sum_{Z}Q(Z)\frac{P(Y,Z|\theta)}{Q(Z)}\right)\\
      &\geq \sum_{Z}Q(Z)log\frac{P(Y,Z|\theta)}{Q(Z)}\\
      \end{align}
      $$
    • 不等式中当且仅当\(log\frac{P(Y,Z|\theta)}{Q(Z)}\)为常数,也就是\(\frac{P(Y,Z|\theta)}{Q(Z)}=c\), c为常数,时等号成立
    • 此时由于\(Q(Z)\)是一个分布(注意:正因为\(Q(Z)\)是一个分布才能用Jensen不等式),所以有
      $$
      \begin{align}
      Q(Z)=\frac{P(Y,Z|\theta)}{\sum_{Z}P(Y,Z|\theta)}=\frac{P(Y,Z|\theta)}{P(Y|\theta)}=P(Z|Y,\theta)
      \end{align}
      $$

吴恩达CS229

  • E步: 计算\(Q_{i}(Z)=P(Z|Y,\theta^{i})\)
  • M步: 求使得原始似然函数下界极大化的参数\(\theta=\theta^{i+1}\)
    $$
    \begin{align}
    \theta^{i+1} &= \arg\max_{\theta}\sum_{Z}P(Z|Y,\theta^{i})log\frac{P(Y|Z,\theta)P(Z|\theta)}{P(Z|Y,\theta^{i})} \\
    &= \arg\max_{\theta}\sum_{Z}Q_{i}(Z)log\frac{P(Y|Z,\theta)P(Z|\theta)}{Q_{i}(Z)}
    \end{align}
    $$
    • 进一步消除与\(\theta\)无关的项可以得到
      $$
      \begin{align}
      \theta^{i+1} &= \arg\max_{\theta}\sum_{Z}Q_{i}(Z)logP(Y|Z,\theta)P(Z|\theta)
      \end{align}
      $$
  • 推导步骤和李航统计学习方法一样,核心是运用Jensen不等式

总结

  • 以上两个不同课程的E步不同,但完全等价,吴恩达CS229课程中E步计算\(Q_{i}(Z)=P(Z|Y,\theta^{i})\)就等价于计算出了李航统计学习方法中的\(Q(\theta, \theta^{i})\),二者关系如下:
    $$
    \begin{align}
    Q(\theta, \theta^{i})&=\sum_{Z}P(Z|Y,\theta^{i})logP(Y|Z,\theta)P(Z|\theta) \\
    &= \sum_{Z}Q_{i}(Z)logP(Y|Z,\theta)P(Z|\theta)
    \end{align}
    $$
  • M步中,二者本质上完全相同,但是吴恩达CS229中没消去与\(\theta\)无关的项,所以看起来不太简洁

实例

实例一
  • 三个硬币的抛硬币问题
    • 第一次:抛硬币A,决定第二次抛C还是B,选中B的概率为\(\pi\)
    • 第二次:抛硬币B或C,正面为1,反面为0
  • (第一个硬币A抛中B的概率为隐变量)
实例二
  • 200个人不知道男女的身高拟合问题(性别为隐变量)
  • 这里是高斯混合模型的代表
实例三
  • K-Means聚类
  • 参考<<百面机器学习>>P100-P101

进一步理解

我的理解
  • 初始化参数\(\theta^{0}\)

  • 1.根据参数\(\theta^{i}\)计算当前隐变量的分布函数\(Q_{i}(Z)=P(Z|Y,\theta^{i})\)

    • 这一步的本质是使得在参数 \(\theta = \theta^i\) 时, 求得一个隐变量 \(Z\) 的分布,使得原始式子中的不等式取等号
  • 2.根据\(Q_{i}(Z)=P(Z|Y,\theta^{i})\)得到对数似然函数下界函数\(B(\theta, \theta^{i})\)(求原始似然函数的下界B函数是因为直接对原始似然函数求极大值很难)或者\(Q(\theta,\theta^{i})\)
    $$\arg\max_{\theta}B(\theta, \theta^{i})=\arg\max_{\theta}Q(\theta,\theta^{i})$$
    (\(Q(\theta,\theta^{i})\)可以看作是\(B(\theta, \theta^{i})\)的简化版,\(B(\theta, \theta^{i})\)才是原始似然函数的下界,\(Q(\theta,\theta^{i})\)不是原始似然函数的下界)

    • 这里 \(B(\theta, \theta^{i})\) 就是原始似然函数的下界(也就是不等式取到等号)
  • 3.求使得函数\(B(\theta, \theta^{i})\)极大化的参数\(\theta=\theta^{i+1}\)

    • 这一步是在固定隐变量 \(Z\) 的分布时, 用极大似然求一个使得下界 \(B(\theta, \theta^{i})\) 最大的参数 \(\theta = \theta^{i+1}\) 使得 \(B(\theta^{i+1}, \theta^{i}) = \text{max} B(\theta, \theta^{i})\)
  • 4.循环1,2,3直到收敛(相邻两次参数的变化或者是似然函数的变化足够小即可判断为收敛)

    • \(||\theta^{i+1}-\theta^{i}||<\epsilon_{1}\)或者\(||Q(\theta^{i+1},\theta^{i})-Q(\theta^{i},\theta^{i})||<\epsilon_{2}\)
  • 总结:

    • 在吴恩达CS229课程中: E步包含1, M步包含2,3,其中第2步中求的是\(B(\theta, \theta^{i})\)
    • 在李航<<统计学习方法>>中: E步包含1,2, M步包含3,其中第2步中求的是\(Q(\theta,\theta^{i})\)
    • 两种表达等价
图示理解
  • 迭代图示如下图(图来自博客:https://www.cnblogs.com/xieyue/p/4384915.html)
  • 也可参考李航<<统计学习方法>>第160页的图和解释

收敛性

  • 参考李航<<统计学习方法>>第160页-第162页推导过程
  • 参考<<百面机器学习>>第P099页-第P100页
    • 核心思想原始函数单调有界
    • 原始函数为\(L(\theta)\),函数下界为\(B(\theta,\theta^{i})\)
    • E步:
      • 找到使得在当前\(\theta^{i}\)确定时,原始函数的下界\(B(\theta, \theta^{i})\),在\(\theta^{i}\)处有
        \(\)
        $$
        \begin{align}
        L(\theta^{i}) = B(\theta,\theta^{i})
        \end{align}
        $$
    • M步:
      • 找到使得函数\(B(\theta,\theta^{i})\)取得极大值的\(\theta^{i+1}\)
    • i = i + 1,然后重新开始E和M步
      $$
      \begin{align}
      L(\theta^{i+1}) >= L(\theta^{i+1})
      \end{align}
      $$
    • 所以函数是单调的
    • 由于\(L(\theta)\)有界(这里原始函数有界可以从似然函数的定义得到)
    • 函数单调有界=>函数收敛(数学分析中的定理)

优劣性

优势
  • 简单性
  • 普适性
劣势
  • 不能保证收敛到最大值,只能保证收敛到极大值
  • 对初始值敏感,不同初始值可能收敛到不同极值点
  • 实际使用时通常采用多次选择不同的初始值来进行迭代,最终对估计值选最好的

EM算法的推广

  • 引入F函数
GEM1

F函数极大-极大法

  • 初始化参数\(\theta^{0}\)
  • E步: 求使得\(F(\tilde{P},\theta^{i})\)极大化的\(\tilde{P}^{i+1}\)
  • M步: 求使得\(F(\tilde{P}^{i+1},\theta)\)极大化的\(\theta^{i+1}\)
  • 重复E,M,直到收敛
GEM2
  • 初始化参数\(\theta^{0}\)
  • E步: 计算\(Q(\theta,\theta^{i})\)
  • M步: 求\(\theta^{i+1}\)使得\(Q(\theta^{i+1},\theta^{i}) > Q(\theta^{i},\theta^{i})\)
  • 重复E,M,直到收敛
  • 总结: \(Q(\theta,\theta^{i})\)的极大化难求时,这种方法可以简化计算
GEM3
  • 初始化参数\(\theta^{0}\)
  • E步: 计算\(Q(\theta,\theta^{i})\)
  • M步: 对参数\(\theta^{i}\)的每一个维度k,固定参数的其他维度,求使得\(Q(\theta,\theta^{i})\)极大化的\(\theta_{k}^{i+1}\),最终得到\(\theta^{i+1}\)
    • 使得\(Q(\theta^{i+1},\theta^{i}) > Q(\theta^{i},\theta^{i})\)
  • 重复E,M,直到收敛
  • 总结: 一种特殊的GEM算法,将M步分解为参数\(\theta\)的维度次来条件极大化

ML——HMM-MEMM-CRF

Posted on 2018-03-15

本文主要区分隐马尔可夫模型(HMM),最大熵马尔可夫模型(MEMM),和条件随机场(CRF)


HMM

  • 生成式模型
  • 有向图模型,贝叶斯网络

模型描述

  • 模型参数: \(\lambda = (A, B, \pi)\)
    • A为状态转移矩阵
    • B为观测概率矩阵
    • \(\pi\)为初始状态概率向量
  • HMM对

假设

  • 观测序列之间独立
  • 当前状态仅仅依赖于上一个状态

问题

  • 概率计算问题: 给定模型\(\lambda = (A, B, \pi)\)和观测序列\(O=(o_{1}, o_{2},,,o_{n})\),计算在给定模型下观测序列出现的概率\(P(O|\lambda)\)
  • 学习问题: 已知观测序列\(O=(o_{1}, o_{2},,,o_{n})\),估计模型参数\(\lambda = (A, B, \pi)\),使得在该模型下观测序列出现的概率\(P(O|\lambda)\)最大.(极大似然法,EM算法)
  • 预测问题(解码问题): 给定模型\(\lambda = (A, B, \pi)\)和观测序列\(O=(o_{1}, o_{2},,,o_{n})\),求状态序列\(I=(i_{1}, i_{2},,,i_{n})\),使得\(P(I|O;\lambda)\)最大,(维特比算法)

序列标注问题

  • 序列标注问题是已知观测序列\(O=(o_{1}, o_{2},,,o_{n})\),求状态序列\(I=(i_{1}, i_{2},,,i_{n})\),使得\(P(I|O)\)最大
  • 实际上序列标注问题包括学习问题和预测问题两个问题:
    • 学习问题: 根据观测序列确定模型参数\(\lambda = (A, B, \pi)\), 极大似然法或EM算法(EM算法会同时估计得到最优状态序列(隐变量))
    • 预测问题: 根据模型参数和观测序列确定最优状态序列\(I=(i_{1}, i_{2},,,i_{n})\),维特比算法

优点

  • 算法成熟
  • 效率高, 模型简单, 容易训练

缺点

  • 序列标注问题中,当前状态(标注)往往不仅仅和前一个状态相关,还可能和观察序列相关(这里指的是整个序列)
  • 也就是说每个状态可能还与整个观察序列的(除了当前观察值以外的)其他观察值(观察序列上下文)相关

MEMM

  • 判别式模型
  • 有向图模型,贝叶斯网络

假设

  • 当前状态仅依赖于上一状态和当前观测值(或所有观测值)
  • (问题: 为什么有些书上画出的图是当前状态依赖上一状态和所有观测值?,这里应该是当前观测值和所有观测值两种情况都是MEMM,<<百面>>画的是所有观测值的情况)

问题

  • MEMM似乎只用于序列标注,也就是在已知观测序列的情况下,寻找最优的状态序列
  • 有其他应用的话再添加

序列标注问题

  • 用于序列标注时,一般也包括两个问题: 学习问题和预测问题
    • 学习问题: 根据观测序列确定模型参数(每条边的(概率)值和初始状态?)
    • 预测问题: 根据模型和观测序列确定维特比算法

优点

  • 解决了观测独立性问题(观测独立性是只当前观测序列只与当前状态相关)[问题: 在MEMM中并不关心观测序列由谁影响,而是关心观测序列如何影响了状态序列]

缺点

  • 标签偏置(labeling bias)问题
    • MEMM中概率最大路径往往容易出现在转移少的状态中
    • MEMM归一化在加和函数\(\sum\)计算内部,而CRF的归一化在加和函数\(\sum\)的外部,这使得MEMM只会关注加和函数[原始建模问题概率值\((y_{1…n}|x_{1…n})\)]的局部特征,而不是的整体特征,所以MEMM存在偏置问题
  • 比HMM复杂

CRF

  • 判别式模型
  • 无向图模型,马尔科夫网络

假设

  • 当前状态仅依赖于上一状态和当前观测值(或所有观测值)
  • (问题: 为什么有些书上画出的图是当前状态依赖上一状态和所有观测值?,这里应该是当前观测值和所有观测值两种情况都是线性CRFs,<<百面>>画的是所有观测值的情况)
  • 与MEMM的区别就是无向图模型与有向图模型的区别

问题

序列标注问题

优点

  • 模型复杂,能建模更多可能的特征
  • 全局归一化(这里与MEMM的区别是,MEMM归一化在加和函数[原始建模问题概率值\((y_{1…n}|x_{1…n})\)]\(\sum\)计算内部,而CRF的归一化在加和函数[原始建模问题概率值\((y_{1…n}|x_{1…n})\)]\(\sum\)的外部)

缺点

  • 模型复杂,速度慢

ML——MCMC采样

Posted on 2018-03-15

本文介绍MCMC采样法和他的两个常用方法:MH(Metropolis-Hastings)采样法和Gibbs采样法
马尔科夫蒙特卡洛(Markov Chain Monte Carlo, MCMC)采样法

  • 对于高维空间中的随机向量,拒绝采样和重要性采样经常难以找到合适的参考分布,容易导致采样效率低下(样本的接受概率太小或者重要性权重太低),此时可以考虑马尔科夫蒙特卡洛采样法(MCMC)
  • MCMC中常见的有两种,MH(Metropolis-Hastings)采样法和Gibbs采样法

MCMC概述

  • 马尔科夫蒙特卡洛(Markov Chain Monte Carlo, MCMC)采样法可分为两个部分(两个MC)描述

蒙特卡洛法

  • 蒙特卡洛法(Monte Carlo)是指: 基于采样的数值型近似求解方法

马尔科夫链

又称离散时间马尔可夫链(discrete-time Markov chain,缩写为DTMC),或者马氏链

  • 马尔科夫链(Markov Chain)是指: 状态空间中经过从一个状态到另一个状态的转换的随机过程, 该随机过程满足马尔科夫性
  • 马尔科夫性(Markov property)是指: 当一个随机过程在给定现在状态及所有过去状态情况下,其未来状态的条件概率分布仅依赖于当前状态;换句话说,在给定现在状态时,它与过去状态(即该过程的历史路径)是条件独立的,那么此随机过程即具有马尔可夫性质。具有马尔可夫性质的过程通常称之为马尔可夫过程
    • 马尔科夫性的简单理解: “无记忆性”: 下一状态的概率分布只能由当前状态决定,在时间序列中它前面的事件均与之无关

MCMC基本思想

  • 针对采样的目标分布,构造一个马尔科夫链,使得该马尔科夫链的平稳分布就是目标分布
  • 从任何一个初始状态出发,沿着马尔科夫链进行状态转移,直到马尔科夫链收敛(到达平稳状态)
  • 继续在马尔科夫链上进行状态转移,收敛后继续采样得到的样本就是原始目标分布的样本
    • burn-in处理: 现实应用中,我们需要丢弃收敛前的样本,只保留收敛后的样本
    • burn-in 原意为”老化,定型”之意,在这里表示我们只取后面马氏链定型(收敛)后采样得到的样本
    • 假设采样到收敛用了n次采样,那么服从原始分布的k个样本为\((x^{n+1}, x^{n+2},,,, x^{n+k})\)有时候为了得到近似独立的样本,可以间隔每r次再取出其中一个样本\((x^{n+r}, x^{n+2r},,,, x^{n+kr})\)
    • 真正独立同分布的k个样本可用多条k条不同的收敛后的马氏链得到,不同马氏链采样得到的样本是独立同分布的
  • 核心: 马尔科夫链的构造,也就是确定马尔科夫链的状态转移概率

常见的MCMC方法

MH(Metropolis-Hastings)采样法

  • 对于原始目标分布\(p(x)\)
  • 选择一个参考条件分布\(q(x^{\star}|x)\), 定义接受概率\(A(x,x^{\star})\):
    • (注意这里是参考条件分布,因为是马尔科夫链,所以每个状态都由上一个状态转移而来,需要定义的参考分布应该是条件分布,不是一般拒绝采样中的普通参考分布)
      $$
      A(x,x^{\star}) = min\left ( 1, \frac{p(x^{\star})q(x|x^{\star})}{p(x)q(x^{\star}|x)} \right )
      $$
  • MH采样法构建满足平稳分布就是目标分布\(p(x)\)的秘诀就是让每次采样时,当前状态以一定概率停留在上一状态
    • 与拒绝采样对应: 接受意味着跳转到下一状态,拒绝意味着停留在当前状态
采样过程
  • 随机选取初始样本x^{0}
  • for t = 1,2,3,…:
    • 参考条件分布采样\(x^{\star} \sim q(x^{star}|x^{t-1})\)
    • 均匀分布采样\(u \sim U(0,1)\)
    • 判断是否接受: 如果\(u < A(x^{t-1}, x^{\star})\),则接受,令: \(x^{t} = x^{\star}\), 否则拒绝,令: \(x^{t}=x^{t-1}\)
  • burn-in处理: 丢弃采样到平稳分布前的样本, 只保留平稳分布后的样本即为服从原始分布\(p(x)\)的样本
    • 假设采样到收敛用了n次采样,那么服从原始分布的k个样本为\((x^{n+1}, x^{n+2},,,, x^{n+k})\)有时候为了得到近似独立的样本,可以间隔每r次再取出其中一个样本\((x^{n+r}, x^{n+2r},,,, x^{n+kr})\)
    • 真正独立同分布的k个样本可用多条k条不同的收敛后的马氏链得到,不同马氏链采样得到的样本是独立同分布的
  • 采样次数一般来说是凭经验选择一个足够大的值,现实是现实可以使用一些参数变化量这类的指标来判断采样是否收敛,参考NLP——LLDA的Gibbs采样实现
与拒绝采样的区别
  • MH采样基于拒绝采样来逼近平稳分布
  • 拒绝采样中: 如果样本某一步被拒绝,那么该步不会产生新的样本,需要重新对当前步进行采样
  • MH中: 每一步都会产生一个样本,被拒绝后,就令当前样本和上一个样本相同即可
    • 因为这里是为了使得每个状态的转出概率等于转入概率,所以拒绝就意味着当前采样步骤状态不跳转
    • MH采样法最核心的思想就是一定概率停留在上一个状态来实现对马尔科夫链的构建的
MH采样法正确性证明
  • MH采样法构造的马尔科夫链(状态转移概率矩阵)是正确的吗?

  • 细致平稳条件, 如果非周期的马氏链的状态转移矩阵P和分布\(\pi(x)\)满足下面的式子对任意的\(i,j\)都成立:
    $$\pi(x^{i})P_{ij} = \pi(x^{j})P_{ji}$$

    • 上式为细致平稳分布条件(detailed balance condition)
    • 其中\(\pi(x)\)为马氏链的平稳分布,在这里等于我们的原始分布\(p(x)\)
  • 证明\(\pi(x)\)为马氏链的平稳分布:
    $$
    \begin{align}
    \sum_{i=1}^{\infty}\pi(x^{i})P_{ij} = \sum_{i=1}^{\infty}\pi(x^{j})P_{ji} = \pi(x^{j})\sum_{i=1}^{\infty}P_{ji} = \pi(x^{j}) \\
    => \pi(x) P = \pi(x)
    \end{align}
    $$

    • 由于\(\pi(x)\)为方程\(\pi(x) P = \pi(x)\)的解,所以\(\pi(x)\)是状态转移矩阵P对应的马氏链的平稳分布
  • 在MH采样法中

    • 参考条件分布函数本对应状态转移矩阵的一个元素,\(q(x^{i}|x^{j}) = P_{ij}\)(注意: 实际上一般不相等)
    • 但是很难构造这样方便采样的函数,于是我们使用一个接受率来修正\(q(x^{i}|x^{j})\alpha(x^{j}, x^{i}) = P_{ij}\)
      • \(\alpha(x^{j}, x^{i})\)表示从\(x^{j}\)跳转到\(x^{i}\)的接受率, 其值可如下求得:
        $$
        \begin{align}
        \pi(x^{i}) P_{ij} &= \pi(x^{j})P_{ji} \\
        \pi(x^{i}) q(x^{j}|x^{i})\alpha(x^{i}, x^{j}) &= \pi(x^{j})q(x^{i}|x^{j})\alpha(x^{j}, x^{i})
        \end{align}
        $$
    • 显然,直接取:
      $$
      \begin{align}
      \alpha(x^{i}, x^{j}) &= \pi(x^{j})q(x^{i}|x^{j})\\
      \alpha(x^{j}, x^{i}) &= \pi(x^{i})q(x^{j}|x^{i})\\
      \end{align}
      $$
    • 即可
  • 但是由于\(\alpha(x^{j}, x^{i})\)一般来说太小,所以我们考虑将\(\alpha(x^{j}, x^{i})\)和\(\alpha(x^{i}, x^{j})\)同时扩大M倍,使得其中大的那个为1,即可得到最大的接受率

    • 使用原始接受率的方法称为一般MCMC方法
    • 使用扩大M被接受率的方法称为MCMC的改进方法: MH方法
  • 改进后的接受率为从\(x^{i}\)跳转到\(x^{j}\)的接受率:
    $$
    \begin{align}
    A(x^{i}, x^{j}) = min\left ( 1, \frac{p(x^{j})q(x^{i}|x^{j})}{p(x^{i})q(x^{j}|x^{i})} \right )
    \end{align}
    $$

    • 理解:
      $$
      \begin{align}
      p(x^{j})q(x^{i}|x^{j}) &> p(x^{i})q(x^{j}|x^{i})时: A(x^{i}, x^{j}) = 1 \\
      p(x^{j})q(x^{i}|x^{j}) &< p(x^{i})q(x^{j}|x^{i})时: A(x^{i}, x^{j}) = \frac{p(x^{j})q(x^{i}|x^{j})}{p(x^{i})q(x^{j}|x^{i})}
      \end{align}
      $$
  • 在MH中表现为从\(x\)跳转到\(x^{\star}\)的接受率:
    $$
    A(x,x^{\star}) = min\left ( 1, \frac{p(x^{\star})q(x|x^{\star})}{p(x)q(x^{\star}|x)} \right )
    $$

Gibbs采样法

Gibbs采样是MH采样法的一个特例,每次只更新样本的一个维度

  • 针对维度很高的多维向量,同时采样多个维度难度较高,且接受率很小
  • 使用Gibbs采样每次采样一个维度可以解决这个问题
准备
  • 求得已知其他维度下,每一维度的条件概率\(p(x_{i}|x_{1},,,x_{i-1}, x_{i+1},,,x_{d})\)
采样过程
  • 随机选择初始状态\(x^{0} = (x_{1}^{0}, x_{2}^{0}, x_{3}^{0},,,, x_{d}^{0})\)

  • for t = 1,2,3,…:

    • 基于前一次产生的样本:\(x^{t-1} = (x_{1}^{t-1}, x_{2}^{t-1}, x_{3}^{t-1},,,, x_{d}^{t-1})\), 依次采样和更新每个维度的值,即依次按照:
      • \(x_{1}^{t} \sim p(x_{1}|x_{2}^{t-1},,,x_{d}^{t-1})\)
      • \(x_{2}^{t} \sim p(x_{2}|x_{1}^{t}, x_{3}^{t-1},,,x_{d}^{t-1})\)
      • \(x_{i}^{t} \sim p(x_{i}|x_{1}^{t},,,x_{i-1}^{t}, x_{i+1}^{t-1},,,x_{d}^{t-1})\)
      • \(x_{d}^{t} \sim p(x_{d}|x_{1}^{t}, x_{2}^{t},,,x_{d-1}^{t})\)
    • 得到新的一个样本:\(x^{t} = (x_{1}^{t}, x_{2}^{t}, x_{3}^{t},,,, x_{d}^{t})\)
  • burn-in处理: 丢弃采样到平稳分布前的样本, 只保留平稳分布后的样本即为服从原始分布\(p(x)\)的样本

    • 假设采样到收敛用了n次采样,那么服从原始分布的k个样本为\((x^{n+1}, x^{n+2},,,, x^{n+k})\), 有时候为了得到近似独立的样本,可以间隔每r次再取出其中一个样本\((x^{n+r}, x^{n+2r},,,, x^{n+kr})\)
    • 真正独立同分布的k个样本可用多条k条不同的收敛后的马氏链得到,不同马氏链采样得到的样本是独立同分布的
    • 注意: 采样完成部分维度生成的中间样本如\((x_{1}^{t},,,x_{i-1}^{t}, x_{i}^{t}, x_{i+1}^{t-1},,,x_{d}^{t-1})\)是不能作为最终样本的,因为他们之间(同一轮次的多个中间样本)相互依赖性太强,不具有独立同分布的(虽然完全采样完成的也不能视为具有独立同分布,但是可近似的认为是独立同分布的)
  • 采样次数一般来说是凭经验选择一个足够大的值,现实是现实可以使用一些参数变化量这类的指标来判断采样是否收敛,参考NLP——LLDA的Gibbs采样实现

ML——主动学习-半监督学习-直推学习

Posted on 2018-03-15

主动学习(Active Learning), 半监督学习(Semi-Supervised Learning)与直推学习(Transductive Learning)
半监督学习又称为归纳学习(Inductive Learning)


补充知识

“开放世界”假设

  • 学得的模型能适用于训练过程中从未观察到的数据
  • 也就是说:测试集未知

“封闭世界”假设

  • 学得的模型仅仅能适用于训练过程中观察到的未标记样本
  • 也就是说:测试集就是训练时观察到的未标记数据

相同点

  • 都是用于解决有少量标注数据和海量未标注数据的问题的算法
  • 都是迭代扩充标记数据集的算法:
    • 每次迭代时添加如一部分新的标记数据(由未标记数据标记产生的)

不同点

主动学习

  • 主动学习添加了专家知识(人工确认或者打标签),每次迭代时加入的新的标记数据都是由专家打出来的标签
  • 半监督学习和直推学习都是全自动的(无需人工干预),主动学习是半自动的

半监督学习与直推学习

  • 直推学习将当前的为标签数据看成是最终的测试数据
  • 半监督学习和主动学习的测试集都是未知数据
  • 半监督学习是基于”开放世界”假设的
  • 直推学习是基于”封闭世界”假设的

总结

总体概览

表格概览

学习算法 是否需要专家知识(人工) 是否具有泛化性
半监督学习 否 是(“开放世界”假设)
主动学习 是 是(“开放世界”假设)
直推学习 否 不具有,测试集是已知的未标记数据(“封闭世界假设”)

ML——最优化方法-无约束参数优化方法

Posted on 2018-03-15

本文介绍无约束的参数优化方法:梯度下降法(Gradient Descent)、牛顿法(Newton’s Method)和拟牛顿法(Quasi-Newton Methods)


无约束参数优化方法概览

目标

$$
\begin{align}
\theta^{\star} = \arg\max_{\theta}L(\theta)
\end{align}
$$

直接法

使用直接法需要满足两个条件
  • \(L(\theta)\)为关于\(\theta\)的凸函数
  • \(\nabla L(\theta)=0\)有解析解(又名闭式解,指的是有限个常见运算的组合给出的形式)
求解
  • 目标函数直接对参数求导后令目标函数导数为0: $$\nabla L(\theta)=0$$

迭代法

  • 包括梯度下降法和牛顿法,牛顿法又可以拓展为拟牛顿法

梯度下降法

更详细的说明参考ML——最小二乘与梯度下降中的介绍

  • 梯度下降法通过每次迭代沿着梯度下降最快的方向(梯度的负方向)前进一个\(\Delta \theta\)长度
  • \(\Delta \theta\)为步长\(\alpha\)(参数)乘以梯度的模(变化率)的方法,实现对极大(小)值的一步步逼近

牛顿法

数学中的牛顿法

  • 牛顿法的本质是求函数值\(f(x)\)为零(\(f(x)=0\))时参数(自变量\(x\))的值
  • 本质上说,牛顿法是用逼近的方法来解方程的一种方法
算法流程
  • 对于确定的方程\(f(x)=0\),我们的目标是求解自变量\(x\)的值
  • 1.初始值定义为\(x=x_{0}\)
  • 2.牛顿法通过迭代每次从当前点\(x={k}\)沿着斜率\(\frac{\partial f(x)}{\partial x}, x=x_{k}\)出发做一条直线,并求出其表达式
  • 3.求出该直线与x轴的交点\(x_{k+1}=x_{k}-\frac{f(x_{k})}{f{}’(x_{k})}\)
  • 4.设置下一次迭代的点为\(x=x_{k+1}\)
  • 5.重复2到4,直到斜率小于某个阈值\(\epsilon\)时停止迭代
  • 6.迭代停止时\(x=x_{k+1}\)就是方程的近似解
  • 迭代过程图示化如下:
  • 图片引用自博客:https://www.cnblogs.com/lyr2015/p/9010532.html*
迭代公式推导
  • 上述迭代流程中迭代公式\(x_{k+1}=x_{k}-\frac{f(x_{k})}{f{}’(x_{k})}\)的推导如下:

最优化方法中的牛顿法

  • 最优化方法的目标是学习函数\(f(\theta)\)的极小/大值(若\(f(\theta)\)是凸函数,则为最小/大值)
  • 可以证明,目标函数(凸函数)取最优点(最大/小值)时,目标函数的导数\(\frac{\partial f(\theta)}{\partial \theta}=0, 其中\theta=\theta^{\star}\)
  • 基于这个事实,在知道目标函数的导数\(f{}’(\theta)=\frac{\partial f(\theta)}{\partial \theta}\)的表达式后,我们可以列出方程\(f{}’(\theta)=0\)
    • 此时方程的解\(\theta^{\star}\)就是原始目标函数的最优解
  • 解上述方程\(\frac{\partial f(\theta)}{\partial \theta}=0\)时我们即可使用数学中的牛顿法
算法流程
  • 具体算法步骤与数学中的算法流程小节一致,不同的地方在于此时迭代公式变为\(\theta_{k+1}=\theta_{k}-\frac{f{}’(\theta_{k})}{f{}’{}’(\theta_{k})}\)
  • 在具体的实现中,我们一般会直接推导出每一步的迭代公式,按照公式迭代即可得到最优解

迭代公式推导

  • 根据上述事实,此时我们的目标函数为\(f(\theta)\),目标方程方程为\(f{}’(\theta)=0\)
  • 此时迭代公式为$$\theta_{k+1}=\theta_{k}-\frac{f{}’(\theta_{k})}{f{}’{}’(\theta_{k})}$$
  • 当参数数量不止一个时,\(\theta\)表示一个向量,此时迭代公式为$$\theta_{k+1}=\theta_{k}-H_{k}^{-1}\nabla_{\theta}f(\theta_{k})$$
    • 其中\(H_{k}^{-1}\)为海森矩阵\(H_{k}\)的逆, \(H_{k}=H(\theta_{k})\)
    • \(H_{k}^{-1}\)和\(\frac{1}{f{}’{}’(\theta_{k})}\)分别是多维和一维参数时目标函数的二阶导
    • 海森矩阵是目标函数对参数的二阶导数,\(H(\theta)=\left [ \frac{\partial^{2}f}{\partial \theta^{i}\partial \theta^{j}} \right ]_{n\times n}\)
  • 推导步骤和上面的数学中的迭代公式推导一致

牛顿法与梯度下降法的一种简单推导方法

  • 用泰勒展开来推导,详情待更新(参考<<百面>>P149)

迭代法的思想

  • 最小化目标函数
    $$
    \begin{align}
    \delta_{t} &= \arg\min_{\delta}L(\theta_{t} + \delta) \\
    \theta_{t+1} &= \theta_{t} + \delta_{t} \\
    \end{align}
    $$
  • 注意,如果这里是max最大化目标函数的话,对应的是梯度上升法,此时后面推导的步骤中加入L2正则项时为了使得\(\left | \delta \right |_{2}^{2}\)的值最小,正则项的权重应该为负数,这样整体目标函数最大时正则项才能取得最小值,最终推导得到的结果也将变成梯度上升的表达式,(\(\alpha > 0\)时对应的参数迭代公式变成加好而不是减号)
  • 但是实际上最大化目标函数可以价格负号转变为最小化目标函数,所以其实掌握最小化目标函数的优化方法即可

一阶法——梯度下降法

  • 对目标函数在\(L(\theta_{t} + \delta)\)处做一阶泰勒展开
    $$
    \begin{align}
    L(\theta_{t} + \delta) = L(\theta_{t}) + \nabla L(\theta_{t})^{T}\delta \\
    \end{align}
    $$
  • 由于上式在\(\delta\)非常小时才成立,所以我们一般加上加入L2正则项(L2正则项可以保证\(\delta\)的值不会太大),为了保证\(\left | \delta \right |_{2}^{2}\)的值最小,要求\(\alpha > 0\), 才能保证目标函数最小时正则项也对应最小 (梯度提升法中要求\(\alpha < 0\)或者需要在正则项前面的系数加上负号,才能保证目标函数最大时正则项最小)
    $$
    \begin{align}
    L(\theta_{t} + \delta) = L(\theta_{t}) + \nabla L(\theta_{t})^{T}\delta + \frac{1}{2\alpha}\left | \delta \right |_{2}^{2} \\
    \end{align}
    $$
  • 直接对上式求导=0得
    $$
    \begin{align}
    \delta_{t} &= \arg\min_{\delta}L(\theta_{t} + \delta) \\
    &= \arg\min_{\delta}(L(\theta_{t}) + \nabla L(\theta_{t})^{T}\delta + \frac{1}{2\alpha}\left | \delta \right |_{2}^{2}) \\
    &= -\alpha \nabla L(\theta_{t})
    \end{align}
    $$
  • 于是梯度下降法的更新表达式为
    $$
    \begin{align}
    \theta_{t+1} &= \theta_{t} + \delta_{t} \\
    &= \theta_{t} - \alpha \nabla L(\theta_{t})
    \end{align}
    $$

二阶法——牛顿迭代法

  • 对目标函数在\(L(\theta_{t} + \delta)\)处做二阶泰勒展开
    $$
    \begin{align}
    L(\theta_{t} + \delta) = L(\theta_{t}) + \nabla L(\theta_{t})^{T}\delta + \frac{1}{2}\delta^{T}\nabla^{2}L(\theta_{t})\delta \\
    \end{align}
    $$
  • 直接对上式求导=0得
    $$
    \begin{align}
    \delta_{t} &= \arg\min_{\delta}L(\theta_{t} + \delta) \\
    &= \arg\min_{\delta}(L(\theta_{t}) + \nabla L(\theta_{t})^{T}\delta + \frac{1}{2}\delta^{T}\nabla^{2}L(\theta_{t})\delta) \\
    &= -\nabla^{2} L(\theta_{t})^{-1} \nabla L(\theta_{t}) \\
    &= -H(\theta_{t})^{-1}\nabla L(\theta_{t}) \\
    \end{align}
    $$
  • 于是梯度下降法的更新表达式为
    $$
    \begin{align}
    \theta_{t+1} &= \theta_{t} + \delta_{t} \\
    &= \theta_{t} - \nabla^{2} L(\theta_{t})^{-1} \nabla L(\theta_{t})
    \end{align}
    $$

比较梯度下降法与牛顿法

  • 一般来说,牛顿法收敛速度快
    • 一种解释是梯度下降法用一次平面去拟合局部区域牛顿法是用二次曲面去拟合局部区域,所以后者能得到更好的拟合效果,迭代的方向也就越精确
    • 另一种解释是梯度下降只能看到当前目标函数的下降方向,牛顿法可以看到当前当前目标函数的下降方向,同时还能看到一阶导数的变化趋势,所以拟合更快
  • 梯度下降法中有个超参数\(\alpha\)
    • 牛顿法中海森矩阵的逆在迭代过程中不断减小,可以起到逐步减小步长的效果(这里的步长与梯度下降中的\(\alpha\)步长不一样,梯度下降中的\(\alpha\)是超参数,表示每次向着负梯度移动的长度,而牛顿法中没有超参数)
    • 为了防止震荡,这个步长\(\alpha\)也可以随着迭代次数不断减小
  • 梯度下降法可能造成震荡
    • 越接近最优值时,步长\(\alpha\)应该不断减小,否则会在最优值附近来回震荡
    • <<统计学习方法>>第一版附录A中,\(\alpha\)是不断变化的,能保证不会造成震荡
  • 牛顿法在多变量时需要求海森矩阵H的逆,比较复杂,时间和空间上有要求,不如梯度下降法来的容易

拟牛顿法

  • 解决牛顿法求取海森矩阵\(H\)的逆\(H^{-1}\)时比较耗时间的难题
  • 用一个近似矩阵\(B\)代替海森矩阵\(H\)的逆\(H^{-1}\)
  • 不同算法近似矩阵\(B\)的计算有差异
  • 常见的拟牛顿法:BFGS,L-BFGS和OWL-QN等
    • <<统计学习方法>>中讲解了三个拟牛顿算法: DFP,BFGS和Broyden类算法

总结

归纳自<<统计学习方法>>

相同迭代公式

  • 目标函数为\(f(\theta)\),最优化方法的终极目标是求\(f(\theta)\)的最大值点(或极大值点)
  • 目标函数的一阶导数
    • 参数一维时为:\(f{}’(\theta)=\frac{\partial f(\theta)}{\partial \theta}\)
    • 参数多维时为:\(\nabla f(\theta)\)
  • 目标函数的二阶导数
    • 参数一维时为:\(f{}’{}’(\theta)\)
    • 参数多维时为:(海森矩阵)\(H(\theta)=\left [ \frac{\partial^{2}f}{\partial \theta^{i}\partial \theta^{j}} \right ]_{n\times n}\)
  • 梯度下降法,牛顿法和拟牛顿法的迭代参数均可表示为下面的迭代形式:
    $$\theta_{k+1}=\theta_{k}+\lambda_{k}p_{k}$$
  • 均通过一阶导数\(\left | \nabla f(\theta) \right |<\epsilon\)为收敛判断条件
    • 在<<统计学习方法>>中,梯度下降法还可以通过\(\left | \theta_{k+1}-\theta_{k+} \right |<\epsilon\)或\(\left | f(\theta_{k+1})-f(\theta_{k+}) \right |<\epsilon\)来判断收敛

梯度下降法

  • \(p_{k}=\nabla f(x)\)
  • \(\lambda_{k}\)是步长,满足
    $$f(\theta_{k}+\lambda_{k}p_{k})=\min_{\lambda \geq 0}f(\theta_{k}+\lambda p_{k})$$

牛顿法

  • \(p_{k}=-H_{k}^{-1}\nabla f(\theta)\)
  • \(\lambda_{k}=1\)是固定长度的,详情见数学中的牛顿法的推导,每次迭代到斜率与横轴的交点
    $$\lambda_{k}=1$$

拟牛顿法

  • 核心思想是找一个容易计算的近似矩阵(可以迭代计算,而不是每次重新计算逆矩阵的矩阵)替代原始牛顿法中的海森矩阵\(H\)(\(B\))或者海森矩阵的逆矩阵\(H^{-1}\)(\(G\))
DFP算法
  • 使用\(G_{k}\)逼近海森矩阵的逆矩阵\(H^{-1}\)
  • \(p_{k}=-G_{k}\nabla f(\theta)\)
    • 关于\(G_{k}\)的计算:
      • 初始化\(G(0)\)为正定对称矩阵
      • \(G_{k+1}=G_{k}+\frac{\delta_{k}\delta_{k}^{T}}{\delta_{k}^{T}y_{k}}-\frac{G_{k}y_{k}y_{k}^{T}G_{k}}{y_{k}^{T}G_{k}y_{k}}\)
        • \(\delta_{k}=\theta_{k+1}-\theta_{k}\)
        • \(y_{k}=\nabla f(\theta_{k+1})-\nabla f(\theta_{k})\)
  • \(\lambda_{k}\)是步长,满足
    $$f(\theta_{k}+\lambda_{k}p_{k})=\min_{\lambda \geq 0}f(\theta_{k}+\lambda p_{k})$$
BFGS算法
  • 使用\(B_{k}\)逼近海森矩阵\(H_{k}\)
  • \(p_{k}=-B_{k}^{-1}\nabla f(\theta)\)
    • 关于\(B_{k}\)的计算:
      • 初始化\(B(0)\)为正定对称矩阵
      • \(B_{k+1}=B_{k}+\frac{y_{k}y_{k}^{T}}{y_{k}^{T}\delta_{k}}-\frac{B_{k}\delta_{k}\delta_{k}^{T}B_{k}}{\delta_{k}^{T}B_{k}\delta_{k}}\)
        • \(\delta_{k}=\theta_{k+1}-\theta_{k}\)
        • \(y_{k}=\nabla f(\theta_{k+1})-\nabla f(\theta_{k})\)
  • \(\lambda_{k}\)是步长,满足
    $$f(\theta_{k}+\lambda_{k}p_{k})=\min_{\lambda \geq 0}f(\theta_{k}+\lambda p_{k})$$
Broyden类算法(Broyden’s algorithm)
  • 使用\(G_{k}\)逼近海森矩阵的逆矩阵\(H^{-1}\)
  • 在BFGS中取\(G^{BFGS}=B^{-1}\)
  • 利用DFP和BFGS二者的线性组合选择合适的海森矩阵的逆矩阵\(H^{-1}\)的替代矩阵
    $$G_{k+1}=\alpha G^{DFP}+(1-\alpha)G^{BFGS}$$
  • 可以证明\(G\)此时是正定的
  • \(0\leq \alpha \leq 1\)
  • 这样得到的一类拟牛顿法都称为Broyden类算法
1…131415…20
Joe Zhou

Joe Zhou

世界上只有一种真正的英雄主义,那就是在认清生活真相之后依然热爱生活。 ——罗曼·罗兰

195 posts
38 tags
GitHub E-Mail
© 2024 Joe Zhou
Powered by Hexo
|
Theme — NexT.Gemini v5.1.4