Sweetkang 的机器学习实验室 (1)

前言

近年来,Machine Learning 在许多领域上已然取得了可喜的成就,很是火热。就我我的来说,有意将业余 Sport Programming 的范围扩展一下,譬如 Topcoder Marathon。在解决实际问题中,方法太 Naive 每每效果不怎么样,依旧须要学习一下相关的基础知识。
本系列文章主要基于 Coursera 的 Machine Learning,我社内部 Machine Learning 课里能说的一部分,wikipedia,以及一些其余的读物。算法

一些概念

机器学习的定义

对于某类任务T和性能度量P,若是一个计算机程序在T上以P衡量的性能随着经验E而自我完善,那么咱们称这个计算机程序从经验E中学习。
这是一个比较严谨的界定机器学习问题的 Guideline。若是有什么问题搞不清楚是否是这个范畴,能够尝试套用定义来检查:任务是什么,性能度量是什么,经验是什么,性能是否因为经验而提高。机器学习

一些机器学习应用

  • 手写识别,Optical character recognition
  • 文本分类,识别垃圾邮件,工口反动内容等
  • 语音识别,机器翻译等
  • 图像识别,人脸识别
  • 识别钓鱼网站
  • 机器人,无人机等

一些机器学习问题

  • 分类(Classification):给每组输入打一个 tag,譬如手写识别,实际上至关于对一个图像进行分类
  • 回归(Regression):对每组输入,预测一个实数值,譬如预测股市行情
  • Ranking:将输入排序,譬如对搜索引擎的搜索结果,推荐系统等
  • 聚类(Clustering):将输入数据分红若干类
  • 降维(Dimensionality reduction):寻找输入数据的低维表示

一些定义

  • 样例(Example):某个实体
  • Features:实体的属性集合,一般用向量来表示
  • Label:对于分类问题,就是样例属于哪一类;对于回归问题,就是实数值
  • 训练集(Training Data):用来训练模型
  • Validation set:每每用来调整学习的参数
  • 测试集(Test Data):用来评估模型的表现
  • 监督学习:从给定的训练数据集中学习出一个函数,当新的数据到来时,能够根据这个函数预测结果
  • 非监督学习:训练集没有人为标注的结果
  • 区别:训练数据有没有标注

机器学习三要素:模型,策略,算法

  • 模型:就是所要学习条件几率分布或决策函数
  • 策略:按照什么样的准则来学习或者挑选模型
  • 算法:学习模型的具体计算方法,即用什么样的方法来求得最优解

我的理解,模型表明着你如何看待这个问题。譬如识别一个东西是否是汽车,若是你认为识别的依据是:金属壳 + 车灯 + 反光镜 + 车轮子 … = 汽车,这个思路就比较接近基于规则,决策树,贝叶斯;若是你考虑这个东西和见过的什么东西比较类似,就是 KNN 的思路。以后咱们要不断学习的实际上都是模型。ide

常见的两个策略是经验风险最小化和结构风险最小化。经验风险最小化意味着咱们倾向于对训练数据取得精准的预测。这个想法很直接,且有必定道理:模型在训练数据上表现不佳,更没法期望在测试数据上取得好结果。可是,在训练集上表现好的模型,未必在测试集上表现好。一般来说,简单的模型会更有通用性,而复杂的模型,每每会有一些 hardcode 了训练数据的感受,效果反而不必定好。结构风险最小化在经验风险最小化的状况下,加入一些因子来限制模型的复杂度。函数

根据策略,能够列出一个须要最优化的式子。算法就是求这个式子最优或者较优解的方法。最多见的方法是梯度降低,其余技能尚未 get,就暂不讨论了。性能

梯度降低法(Gradient Descent)

暂时忘记机器学习,如今须要优化一个形如 \( y = f(\theta) \) 的式子,求 \( x = argmax f(\theta) \) 或 \( x = argmin f(\theta) \),有什么好的办法么?
梯度降低法,基于这样的观察:若是实值函数\( F(x) \)在点 a 处可微且有定义,那么函数 \( F(x) \)在 a 点沿着梯度相反的方向 \( -F\nabla(a) \) 降低最快。所以,若是 \( b = a - \gamma\nabla F(a) \) 对于 \( \gamma > 0 \) 且为一个够小数时成立,那么 \( F(a) \geq F(b) \)。换句话说,咱们给出一个对极值的估计 a,不断迭代求 \( a = a - \gamma\nabla F(a) \) ,就能取得一个极值。学习

用一个实际例子来演示一下:对二次函数 \( f(y) = x^{2} + 2x + 10 \) ,使用梯度降低法求 \( min f(x) \) 和 \( argmin f(x) \),函数图像以下:测试

结论不管是从图像仍是初中数学的角度来看都很简单。咱们看看梯度降低算法是如何进行的:优化

f <- function(x) {
    x^2 + 2 * x + 10
}
df <- function(x) {
    2 * x + 2
}

x <- 5
y <- f(x)
learning.rate <- 0.3
plot(f, -5, 5)

while (TRUE) {
    nx = x - df(x) * learning.rate
    ny = f(nx)
    if (abs(x - nx) < 0.01) 
        break
    arrows(x, y, nx, ny, col = "red")
    x = nx
    y = ny
    print(c(x, ny))
}

plot of chunk unnamed-chunk-1

## [1]  1.40 14.76
## [1] -0.040  9.922
## [1] -0.616  9.147
## [1] -0.8464  9.0236
## [1] -0.9386  9.0038
## [1] -0.9754  9.0006
## [1] -0.9902  9.0001

不管是简单问题仍是复杂问题,参数 learning.rate,也就是前文中提到的\( \gamma \)的选择很是重要。Learning rate 太小则须要更多的迭代。Learning rate 过大则会出现之字降低,甚至之字上升。网站

看一个非凸,多元函数的例子:Rosenbrock函数:\( f(x, y) = (1-x)^2 + 100(y-x^2)^2 \) 很显然 x = y = 1 的时候能够取得最优解,可是求解过程倒是很坑的。我们把 x = y = 1 附近的图像画出来:ui

plot of chunk unnamed-chunk-2

再研究一下 x = 1 时的切面:

plot of chunk unnamed-chunk-3

大概能看出来,这个函数在解附近有个很大的很平的底。。。贴一段代码,你们能够 play 一下:

f <- function(x, y) { (1 - x) ** 2 + 100 * (y - x ** 2) ** 2}
df.dx <- function(x, y) { x * 2 - 2 - 400 * y + 400 * x ** 3}
df.dy <- function(x, y) { 200 * y - 200 }

x <- runif(1, 0, 2)
y <- runif(1, 0, 2)
z = f(x, y)
learning.rate = 1E-6
eps <- 1E-10

while (TRUE) {
  new.x = x - df.dx(x, y) * learning.rate
  new.y = y - df.dy(x, y) * learning.rate
  new.z = f(new.x, new.y)
  if (abs(new.z - z) < eps) break
  x = new.x
  y = new.y
  z = new.z
  print(c(x, y, z))
}

能够调整一些参数,譬如 learning.rate,eps 去看看某些现象。咱们能够看到他最后几步的收敛极为缓慢,若是 learning.rate 过大,还会之字上升等等。总的来说,选择一个合适的 learning rate 是很是重要的,除去经验性的技巧,每每也只好枚举了,看看 cost function 的变化状况,若是降低过慢,则须要增大 learning rate,若是反而增加了,则须要减小 learning rate。这也就是为何某些时候咱们须要一个比较小的 validate set,咱们能够按期的在训练中的模型上跑一下 validate set,看一下 cost function 的变化,从而决定 learning rate 的调整。

一元线性回归

以 Stanford Machine Learning 为例:根据房子的面积预测房价。我们来把一些概念对上号:

  • Training Set:m 个二元对 \( (x_{i},y_{i}) \)
  • feature:房屋面积,即 \( x_{i} \)
  • label:房价,即 \( y_{i} \)
  • 这是监督学习,由于测试数据是标注过的
  • 这是回归问题,由于 label 是连续值
  • 模型:一元线性回归,这个想法很显然
  • 策略:\[ minimize J(\theta_{0}, \theta_{1}) = \sum_{i=1}^{m}(\theta_{0}x_{i} + \theta_{1} - y_{i})^2 \]

  • 算法:注意此时咱们要求解的是 \( \theta_{0},\theta_{1} \),而 \( x_{i},y_{i} \) 都是已知量,能够考虑求偏导,而后用梯度降低求解,这就是技能范围之内的东西了,由于每次迭代用了全部的 Training Data,因此这个作法叫 Batch Gradient Descent。

实际应用中,比较好用的算法是 Stochastic Gradient Descent,Batch Gradient Descent 每次迭代,对 \( \sum_{i=1}^{m}(\theta_{0}x_{i} + \theta_{1} - y_{i})^2 \) 求导,至关于 \[ \theta_{0} = \theta_{0} - 2\alpha\sum_{i=1}^{m}(\theta_{0}x_{i} + \theta_{1} - y_{i})x_{i} \] \[ \theta_{1} = \theta_{1} - 2\alpha\sum_{i=1}^{m}(\theta_{0}x_{i} + \theta_{1} - y_{i}) \] 而 Stochastic Gradient Descent 至关与把 Batch Gradient Descent 的 1 次迭代拆成了 m 次,每次对 \( (\theta_{0}x_{i} + \theta_{1} - y_{i})^2 \) 求导,而后 \[ \theta_{0} = \theta_{0} - 2\alpha(\theta_{0}x_{i} + \theta_{1} - y_{i})x_{i} \] \[ \theta_{1} = \theta_{1} - 2\alpha(\theta_{0}x_{i} + \theta_{1} - y_{i}) \]

Batch Gradient Descent 能够求得更精确的解,可是若是模型复杂,或者数据量大,就很难直接 Batch Gradient Descent 了。

相关文章
相关标签/搜索