【笔记】迈向人工智能 | Coursera-斯坦福大学-机器学习-吴恩达(已完结)
课程首页:Coursera-Stanford-Machine Learning
授课教授:吴恩达(Andrew Ng)
------Week 1------2018.10.10------
Introduction
Linear Regression with One Variable
Linear Algebra Review
1. What is Machine Learning?
Arthur Samuel: "the field of study that gives computers the ability to learn without being explicitly programmed."
Tom Mitchell: "A computer program is said to learn from experience E with respect to some class of tasks T and performance measure P, if its performance at tasks in T, as measured by P, improves with experience E."
举个例子:在机器学习象棋对弈中,E就是成千上万次的象棋对弈实战,T就是象棋对弈这一任务,P就是机器在下次对弈中获胜的可能性。那么上述第二个定义就可以表述为:对于象棋对弈这一学习任务,机器学习能从不断的对弈实战经验中,提升自己的对弈获胜概率。
2. Supervised Learning & Unsupervised Learning
In supervised learning, we are given a data set and already know what our correct output should look like, having the idea that there is a relationship between the input and the output. Supervised learning problems are categorized into "regression" and "classification" problems.
Unsupervised learning allows us to approach problems with little or no idea what our results should look like. We can derive structure from data where we don't necessarily know the effect of the variables.
机器学习问题通常可以分为两类:监督性学习和无监督性学习。二者的区别就在于Supervised,翻成中文“监督性”似乎有点晦涩,其实可以理解为是否给定了“正确答案或方向”。
在监督性学习中,数据集的每个样本均有提供“正确答案”(如这张照片是一名35岁的女生,或这个肿瘤样本是良性的),可据此进行预测或判定。例如,通过人物正面照预测他/她的年龄(也称为“回归”问题,map input variables to some continuous function),或者判定病人身上的肿瘤是良性还是恶性(也称为“分类”问题,map input variables into discrete categories)。
在无监督性问题中,只给定数据集,每个样本并没有给出“正确答案”,要求在数据中自动找出某种结构,进行预测或分类,其结果也不存在反馈。例如,Google对当日新闻进行同主题自动分类,或者对相互混杂的声音应用Cocktail Party Algorithm进行语音识别。
3. Model and Cost Function
Model Representation: 给定训练集,通过学习算法,得到假设模型,那么对任意的输出,可以通过假设模型得到预测值。
Training Set -> Learning Algorithm -> Hypothesis \( h \) => \( Y=h(X) \) .
Cost Function: 用来描述假设函数的精确度,即计算预测值与实际值的“距离”,在单变量线性回归问题中,\( h_θ(x_i) = θ_0 + θ_1 x_i \),那么:
$$ J(θ_0 , θ_1 ) = \frac{1}{2m} \sum_{i=1}^m (\hat{y}_i - y_i)^2 = \frac{1}{2m} \sum_{i=1}^m (h_θ(x_i) - y_i)^2 $$
我们的目标就是最小化$ J(θ_0 , θ_1 ) $(如果进一步简化,令$ θ_0 = 0 $,那么就是最小化$ J(θ_1) $),这样预测值与实际值就最接近。在凸函数中,就是找到cost function的最低点。
4. Gradient Descent
梯度下降,顾名思义,就是沿着梯度下降最快的地方,最容易走到最低点。想象你站在山坡上,要去往山脚,但却不知道路,你可以考察前后左右各个方向,下降最快的地方最有可能是通往山脚的路径,但,也有可能走到一个山谷去,而不是真正的山脚,也就是所谓的困在了“局部最小值”中。算法如下:
1)随机选择两个初始值$ θ_0, θ_1 $;
2)重复执行$ θ_j := θ_j - α\frac{\partial}{\partial θ_j}J(θ_0, θ_1) $,其中$j = 0,1$,直至收敛(注:$ θ_0, θ_1 $必须同时更新)。
其中$ α $称为Learning Rate(学习速率,或步长),如果太小的话,梯度下降会很慢,如果太大的话,又可能无法收敛,甚至发散。另外,如果在每一步的下降中,都选用全部的样本进行计算,那么这称为Batch Gradient Descent(与之对应的有Stochastic Gradient Descent和Mini-batch Gradient Descent,后面会介绍)。
5. Linear Algebra Review
线性代数的复习,不赘述,需要了解的概念:
Matrices and Vectors (element, dimension, 1-indexed, scalar), Addition and Scalar Multiplication, Matrix Vector Multiplication, Matrix Matrix Multiplication (associative, not commutative, Identity Matrix), Inverse and Transpose.
------Week 2------2018.10.14------
Linear Regression with Multiple Variables
Octave/Matlab Tutorial
1. Multivariate Linear Regression
在线性回归中,如果变量/特征不止一个,如根据样本的面积,房间数,楼层预测房屋价值,那么就称为多元线性回归。令$m$为训练样本数,$n$为变量/特征数,$x^{(i)}$为第$i$个训练样本,$x_j^{(i)}$为第$i$个样本的第$j$个变量/特征,那么之前的假设模型$h_θ(x)$则为:
$$ h_θ(x) = θ_0 + θ_1 x_1 + θ_2 x_2 + \cdots + θ_n x_n = \left[ \begin{matrix} θ_0 & θ_1 & \cdots & θ_n \end{matrix} \right] \left[ \begin{matrix} x_0 \\ x_1 \\ \vdots \\ x_n \end{matrix} \right] = θ^T x $$
其中,$ x_0^{(i)} = 1 $。
那么多元线性回归中的梯度下降算法则修改为:1)选定初始值;2)重复执行$ θ_j := θ_j - α\frac{1}{m}\sum_{i=1}^m (h_θ (x^{(i)}) - y^{(i)})\cdot x_j^{(i)} $直至收敛。
算法的实际应用中,由于$θ$对于范围小的输入变量下降较快,范围大的下降慢,所以当变量之间不平均时,容易振荡下降,性能不佳,因此可以采用特征缩放(Feature Scaling)和均值归一化处理(Mean Normalization)技巧来调整输入变量的范围,以此加快收敛,减少迭代的次数,即:
$$ x_i := \frac{x_i - μ_i}{s_i} $$
其中,$μ_i$是样本中所有特征的均值,$s_i$是特征值的范围(max - min),或称为标准差。举个例子,如果数据集中房屋样本的价格范围为100到2000,平均价格为1000,那么$ x_i := (price - 1000)/1900 $
而对于步长$α$,如果太小,则收敛慢,如果太大,则可能不收敛,甚至发散。在具体调试中,可以做$J(θ)$随迭代次数变化的图,如果随着迭代次数增加,曲线下降,那么说明梯度下降算法正常工作,如果曲线反而上升,那么可以考虑减小$α$。判断是否收敛,可以考察$J(θ)$在一次迭代中是否下降小于某个小值$ε$,如$10^{-3}$。
此外,如果可以用新的一个变量代替多个变量的组合,将减少算法的计算量,例如,在房价预测中,对于房屋的长$x_1$和宽$x_2$,可以用面积$x_3$来代替。
之前的例子中,我们用直线去拟合数据,但实际中直线不一定能很好的拟合数据,因此我们可以采用多项式回归(Polynomial Regression),即
$$ h_θ(x) = θ_0 + θ_1 x_1 + θ_2 x_1^2 + \cdots + θ_n x_1^n $$
不过值得注意的是,在这种情况下,特征缩放就尤为重要,因为1-1000范围的三次方就已经是1-1000000000。
2. Computing Parameters Analytically
除了梯度下降法,还可以使用正规方程(Normal Equation)来求解$θ$的最优值。假设数据集$X$有$m$个样本,$n$个特征,那么
$$ X = \left[ \begin{matrix} 1 & x_1^{(1)} & x_2^{(1)} & \cdots & x_n^{(1)} \\ 1 & x_1^{(2)} & x_2^{(2)} & \cdots & x_n^{(2)} \\ \vdots & \vdots & \vdots & \vdots & \vdots \\ 1 & x_1^{(m)} & x_2^{(m)} & \cdots & x_n^{(m)} \end{matrix} \right] , y = \left[ \begin{matrix} y^{(1)} \\ y^{(2)} \\ \vdots \\ y^{(m)} \end{matrix} \right], θ = \left[ \begin{matrix} θ_0 \\ θ_1 \\ \vdots \\ θ_n \end{matrix} \right] $$
则可以求出$ θ = (X^T X)^{-1}X^Ty $
相比梯度下降法,正规方程法的优点在于无需选择步长$α$,也无需迭代计算,也无需进行特征缩放,缺点在于时间复杂度较高,为$O(n^3)$,同时需要计算$X^TX$的逆矩阵,当$n$很大时(超过10000),算法将会变得很慢,而梯度下降法的时间复杂度为$O(kn^2)$,当$n$很大时,仍然能奏效。
不过你可能会质疑$X^TX$的逆矩阵是否存在(逆矩阵存在的定理请回顾线性代数课程),不过请放心,不存在的情况是极少的,而且在Octave中,用Pinv命令去求逆矩阵,事实上它是求伪逆(pseudo inverse)操作,即便矩阵不可逆,也能求解。如果$X^TX$真的不可逆,那么可以考虑是否有:
• 冗余变量(Redundant Features),也就是两个变量相关性很高,如线性依赖;
• 太多变量,相比较之下样本数不足。这种情况下可以删除一些特征,或者使用正则化(regularization);
3. Octave/Matlab Tutorial
语法跟MATLAB差不多,找本书或找篇相关文章看看应该就能上手,介绍了Basic Operations,Moving Data Around, Computing on Data, Plotting Data, Control Statements (for, while if), Vectorization。建议做一下第一课的编程作业,熟悉下。
------Week 3------2018.10.17------
Logistic Regression
Regularization
1. Classification and Representation
前面主要介绍了回归问题,在分类(Classification)问题中,预测值是离散的,如判断邮件是否是垃圾邮件,肿瘤是良性还是恶性,即常见的二元分类问题(Binary Classification Problem,$ y\in \{0,1\}$,0通常被称为负类,1是正类,也可用“-”和“+”表示)和多元分类问题。
对于分类问题,也可以借鉴之前的线性回归算法,不过需要变化一下:由于$ y\in \{0,1\}$,所以$h_θ(x)$也满足这个范围,我们可以采用Sigmoid函数(或称“Logistic函数”):
$$ g(z) = \frac{1}{1+e^{-z}} $$
它的函数曲线大致如下图所示:
可以看出当$z ≥ 0$时,$g(z) ≥ 0.5$,当$z → ∞$时,$g(z) = 1$,当$z → -∞$时,$g(z)= 0$。
令$h_θ(x) = g(θ^T x)$,它给出了$y = 1$的概率,如$h_θ(x) = 0.7$意味着有70%的概率输出为1,或30%的概率为0。如果判定$h_θ(x) ≥ 0.5$时,$y = 1$,$h_θ(x) < 0.5$时,$y = 0$,那么决策边界(Decision Boundary)就是$h_θ(x) = 0.5 = g(θ^T x)$,也就是$θ^T x ≥ 0$时,$y = 1$,$θ^T x < 0$时,$y = 0$。另外,$z$可以是非线性的,如$z = θ_0 + θ_1 x_1^2 + θ_2 x_2^2$。
2. Logistic Regression Model
对于逻辑回归,之前线性回归中的Cost Function可能不适用,因为代价函数有可能是个非凸函数,有许多局部最优点。因此,逻辑回归的代价函数修改如下:
$$ J(θ) = \frac{1}{m}\sum_{i=1}^{m}Cost(h_θ(x^{(i)}), y^{(i)}) $$
其中,$Cost(h_θ(x^{(i)}), y^{(i)}) = -log(h_θ(x))$,当$y = 1$时;$Cost(h_θ(x^{(i)}), y^{(i)}) = -log(1 - h_θ(x))$,当$y = 0$时。
注意到,当$h_θ(x) = y$时,$Cost(h_θ(x^{(i)}), y^{(i)})$为0;当$y = 0$,而$h_θ(x) = 1$时,或者$y = 1$,而$h_θ(x) = 0$时,$Cost(h_θ(x^{(i)}), y^{(i)})$为无穷大,这是符合逻辑的。同时在这种情况下,保证了成本函数是凸函数。
我们可以进一步作简化,令$Cost(h_θ(x^{(i)}), y^{(i)}) = -y log(h_θ(x)) - (1-y)log(1 - h_θ(x))$,那么代价函数为
$$ J(θ) = -\frac{1}{m} \sum_{i=1}^{m} [ y^{(i)} log(h_θ(x^{(i)})) + (1-y^{(i)})log(1 - h_θ(x^{(i)})) ] $$
对应的向量化实现方式为:$ J(θ) = \frac{1}{m}\cdot\left( -y^T log(h) - (1-y)^T log(1-h)\right) $。
之前线性回归中的梯度下降算法在逻辑回归中同样适用,即:
重复执行$ θ_j := θ_j - α\frac{1}{m}\sum_{i=1}^m (h_θ (x^{(i)}) - y^{(i)})\cdot x_j^{(i)} $直至收敛。
此外,可以运用共轭梯度(Conjugate gradient), BFGS, L-BFGS等更高级的算法,这些算法能够更快的得出最优解。不过不建议自己从头写,直接调用已有的库函数即可(如Octave中的fminunc()函数)。
3. Multiclass Classification
在多元分类问题中,我们采用一对多的方法:
1)选择一个分类,将剩下的所有(不论有几个)都看成第二个分类,然后求出对应的假设函数$h_θ^{(i)}(x)$,依此对所有分类进行训练;
2)对于需要进行分类的$x$,选出$h_θ^{(i)}(x)$里最大的那一个,即为分类值。
4. Solving the Problem of Overfitting
在一些情况下,直线并不能很好的拟合数据(下图1),这称为欠拟合(Underfitting,或high bias),通常是由于预测函数太简单,或者使用特征值太少。于是我们会想用曲线去拟合,增加一个额外的特征变量$x^2$,能够取得不错的效果(下图2),但是特征变量并不是越多越好,对数据集样本更精确的拟合,并不一定能更准确的进行预测,太复杂的函数往往带来许多不必要的曲线和转角,如下图3,这称为过拟合(Overfitting)。
对于过拟合,通常采用如下两个方式处理:
1)减少特征变量数:手动选择要保留的特征;或使用模型选择算法;
2)正则化(Regularization):保留所有特征,但减少$θ_j$的贡献;当我们有许多只有些许用处的特征,但又不想舍弃的情况下,正则化是很好的选择。
5. Regularization
正则化通过增加部分项的代价以减少它们的权重,避免过拟合现象。例如,有假设函数为$ θ_0 + θ_1 x + θ_2 x^2 + θ_3 x^3 + θ_4 x^4 $,如果我们想要减少最后两项的影响,那么可以修改代价函数为:$ min_θ \frac{1}{2m} \sum_{i=1}^{m} (h_θ(x_{(i)}) - y_{(i)})^2 + 1000\cdot θ_3^2 + 1000\cdot θ_4^2 $,这种情况下,为了使代价函数接近0,必须减小$θ_3$和$θ_4$至趋于0,以此更好的拟合曲线,减少过拟合。推广到一般情况,则得到:
$$ min_θ \frac{1}{2m} \sum_{i=1}^{m} (h_θ(x_{(i)}) - y_{(i)})^2 + λ\sum_{j=1}^{n}θ_j^2 $$
其中,$λ$称为正则化参数,它对曲线起平缓作用,如果它选得太大,容易造成太平滑,导致欠拟合,如果太小或等于0,则起不到正则化的效果,仍然会有过拟合的现象。
正则化方法在线性回归和逻辑回归中均可应用,在线性回归中,如果使用梯度下降算法,那么只需要关键步骤为:
重复执行$ θ_0 := θ_0 - α\frac{1}{m}\sum_{i=1}^m (h_θ (x^{(i)}) - y^{(i)})x_0^{(i)} $
$ θ_j := θ_j - α\left[ \left( \frac{1}{m}\sum_{i=1}^m (h_θ (x^{(i)}) - y^{(i)})x_j^{(i)} \right) + \frac{λ}{m}θ_j \right] = θ_j (1 - α\frac{λ}{m}) - α\frac{1}{m}\sum_{i=1}^m (h_θ (x^{(i)}) - y^{(i)})x_j^{(i)}, \qquad j \in \{1,2,\cdots,n\} $直至收敛。
注意到,$1 - α\frac{λ}{m}$永远小于1,可以看成在每次迭代中减少$θ_j$的值。
如果使用正规方程,那么之前的求解式就变成$ θ = (X^T X + λ\cdot L)^{-1}X^Ty $,其中:
$$ L = \left[ \begin{matrix} 0 & \quad & \quad & \quad & \quad \\ \quad & 1 & \quad & \quad & \quad \\ \quad & \quad & 1 & \quad & \quad \\ \quad & \quad & \quad & \ddots & \quad \\ \quad & \quad & \quad & \quad & 1 \end{matrix} \right] $$
同时,如果m < n,那么$X^T X$是不可逆的,但当引入了λ后,$X^T X + λ\cdot L$变为一定可逆。
在逻辑回归中,类似的,可以修改代价函数为:
$$ J(θ) = -\frac{1}{m} \sum_{i=1}^{m} [ y^{(i)} log(h_θ(x^{(i)})) + (1-y^{(i)})log(1 - h_θ(x^{(i)})) ] + \frac{λ}{2m} \sum_{j=1}^n\theta_j^2 $$
即可利用梯度下降算法处理。
------Week 4------2018.10.29------
Neural Networks: Representation
1. Why Neural Networks?
之前的课程中已经有提到Non-linear Hypotheses,例如可以对特征进行多项式组合,这样就能得到更“完美”的拟合(有时也会变成过拟合)。当特征数量少时,是个不错的选择,但是当特征逐渐增多时,计算量将急剧递增,在实际的机器学习问题中并不是很好的选择。举个例子,计算机希望识别出图片中的物体是否是一辆车,对于人眼来说自然很容易做到,但在计算机眼中,这就是一幅二维矩阵(再加上RGB三个通道),即便是100x100大小的照片,也有10000个特征点,如果考虑$x_i x_j$的二阶组合,那么将组合出$5 \times 10^7$个特征,计算量特别庞大。因此我们需要一种新的算法,神经网络在解决复杂的非线性分类问题上被证明是一种很好的算法,即使对于特征维数n很大的情况。
神经网络(Neural Networks)在80年代得到广泛应用,其流行度在90年代有所消退,但近年来随着AI的兴起,再度受到人们的关注。神经网络的思想是试图模仿大脑的信号处理方式,我们知道人类可以通过看,听,触,味觉去感知这个世界,那么大脑是如何处理这些信号,而获得对外部世界的认知呢?如果计算机能学会大脑的处理方式,是不是就拥有了大脑的学习能力?
2. Neural Networks Model
一个神经元有很多树突(dendrites),呈放射状,是接受从其它神经元传来的信号的入口(如触觉和听觉),当它接收的刺激足够强,超出一定阈值,就会兴奋并向后传导。也就是通过轴突(axons)将当前神经元发出的信号传递给下一个神经元,每个神经元有一个轴突。两个神经元之间接触的地方就是突触。
如果用一个简单的逻辑单元来表示神经模型,那么树突就相当于输入,轴突就是输出,神经元的细胞核就是处理函数:
$$ \begin{bmatrix} x_0\\ x_1\\ x_2 \end{bmatrix} \rightarrow [\quad] \rightarrow h_\theta(x) $$
其中,$h_\theta (x) = \frac{1}{1+e^{-\theta ^{T}x}} $,称为Sigmoid (logistic) 激活函数(activation function)。
推广到神经网络中,我们会有多个输入(input layer),通过多层的神经传导(hidden layer),最后输出(output layer)
其中hidden layer中的节点又称为激活单元(activation units),具体如下:
$$\begin{align*}& a_i^{(j)} = \text{activation of unit $i$ in layer $j$} \newline& \Theta^{(j)} = \text{matrix of weights controlling function mapping from layer $j$ to layer $j+1$}\end{align*}$$
每个激活单元可以通过如下式子得到:
$$ \begin{align*} a_1^{(2)} = g(\Theta_{10}^{(1)}x_0 + \Theta_{11}^{(1)}x_1 + \Theta_{12}^{(1)}x_2 + \Theta_{13}^{(1)}x_3) \newline a_2^{(2)} = g(\Theta_{20}^{(1)}x_0 + \Theta_{21}^{(1)}x_1 + \Theta_{22}^{(1)}x_2 + \Theta_{23}^{(1)}x_3) \newline a_3^{(2)} = g(\Theta_{30}^{(1)}x_0 + \Theta_{31}^{(1)}x_1 + \Theta_{32}^{(1)}x_2 + \Theta_{33}^{(1)}x_3) \newline h_\Theta(x) = a_1^{(3)} = g(\Theta_{10}^{(2)}a_0^{(2)} + \Theta_{11}^{(2)}a_1^{(2)} + \Theta_{12}^{(2)}a_2^{(2)} + \Theta_{13}^{(2)}a_3^{(2)}) \newline \end{align*} $$
也就是说如果神经网络的第$j$层有$s_j$个单元,第$j+1$层有$s_{j+1}$个单元,那么$\Theta^{(j)}$的维度就是$s_{j+1} \times (s_j + 1)$,其中+1是考虑了$x_0$和$\Theta_0^{(j)}$。举个例子,如果第一层有2个输入节点,第二层有4个激活节点,那么$\Theta^{(1)}$的维度就是4x3。
对于上式的例子,我们可以采用向量化编程来实现,我们用$z_k^{(j)}$来代替括号内的式子,那么
$$ \begin{align*}a_1^{(2)} = g(z_1^{(2)}) \newline a_2^{(2)} = g(z_2^{(2)}) \newline a_3^{(2)} = g(z_3^{(2)}) \newline \end{align*} $$
也就是说,对于第二层j=2和节点k,$z_k^{(2)} = \Theta_{k,0}^{(1)}x_0 + \Theta_{k,1}^{(1)}x_1 + \cdots + \Theta_{k,n}^{(1)}x_n$
那么$x$和$z^j$的向量表示为:
$$ \begin{align*}x = \begin{bmatrix}x_0 \newline x_1 \newline\cdots \newline x_n\end{bmatrix} &z^{(j)} = \begin{bmatrix}z_1^{(j)} \newline z_2^{(j)} \newline\cdots \newline z_n^{(j)}\end{bmatrix}\end{align*} $$
令$x = a^{(1)}$,那么$z^{(j)} = \Theta^{(j-1)}a^{(j-1)}$,也就是$h_\Theta (x) = a^{(j+1)} = g(z^{(j+1)})$,值得注意的是最后一步其实就很像逻辑回归。
3. Example and Intuitions
上面的公式似乎比较难理解,举个简单的例子:如果我们要用神经网络来预测$x_1$ AND $x_2$,那么对应的描述为:
$$ \begin{align*}\begin{bmatrix}x_0 \newline x_1 \newline x_2\end{bmatrix} \rightarrow\begin{bmatrix}g(z^{(2)})\end{bmatrix} \rightarrow h_\Theta(x)\end{align*} $$
其中权重为:$\Theta^{(1)} = [-30 \quad 20 \quad 20]$,那么回忆Sigmoid函数的曲线特征,有:
$$ \begin{align*}& h_\Theta(x) = g(-30 + 20x_1 + 20x_2) \newline \newline & x_1 = 0 \ \ and \ \ x_2 = 0 \ \ then \ \ g(-30) \approx 0 \newline & x_1 = 0 \ \ and \ \ x_2 = 1 \ \ then \ \ g(-10) \approx 0 \newline & x_1 = 1 \ \ and \ \ x_2 = 0 \ \ then \ \ g(-10) \approx 0 \newline & x_1 = 1 \ \ and \ \ x_2 = 1 \ \ then \ \ g(10) \approx 1\end{align*} $$
也就是通过这种方式,我们构造出了一个“与门”的神经网路。同样的,只要改变下权重,我们可以构造出“或门”,或其它逻辑门。那么,在第2层,我们可以设置多个激活单元,通过不同的权重实现不同的逻辑门,然后送往第3层,通过组合,实现更复杂的输入输出。依次类推,对于更为复杂的非线性方程,神经网络都可以很好的模拟。
那么对于多元分类,不再是只有一个输出,而是多个输出, 每个中间层都提供了新的信息,以供最后的判断。
------Week 5------2018.12.04------
Neural Networks: Learning
1. Backpropagation
在神经网络中,首先我们定义$L$:网络中的总层数;$s_l$:第$l$层中的节点数量(不包括偏差节点);$K$:输出节点/分类数量;
回忆逻辑回归中的代价函数:
$$ J(\theta) = - \frac{1}{m} \sum_{i=1}^m [ y^{(i)}\ \log (h_\theta (x^{(i)})) + (1 - y^{(i)})\ \log (1 - h_\theta(x^{(i)}))] + \frac{\lambda}{2m}\sum_{j=1}^n \theta_j^2 $$
那么神经网络中的代价函数可以写成:
$$ \begin{gather*} J(\Theta) = - \frac{1}{m} \sum_{i=1}^m \sum_{k=1}^K \left[y^{(i)}_k \log ((h_\Theta (x^{(i)}))_k) + (1 - y^{(i)}_k)\log (1 - (h_\Theta(x^{(i)}))_k)\right] + \frac{\lambda}{2m}\sum_{l=1}^{L-1} \sum_{i=1}^{s_l} \sum_{j=1}^{s_{l+1}} ( \Theta_{j,i}^{(l)})^2\end{gather*} $$
看着略复杂,其实相比只是加了几个嵌套求和,上式的第一部分在方括号前加了一个额外的对输出节点从1到K的循环;在正则化部分我们对每一层的$\Theta$都进行考虑加权,即从第$1$层到$L-1$层,第$l$层的每一个节点到第$l+1$层的每一个节点对应的$\Theta_{j,i}^{(l)}$。
定义了代价函数,我们的目标当然就是$\min_\Theta J(\Theta)$,如果利用梯度下降法,我们就需要计算$\dfrac{\partial}{\partial \Theta_{i,j}^{(l)}}J(\Theta)$,这就需要引入反向传播(Backpropagation)算法:
给定训练集,对于所有的$(l,i,j)$,设$\Delta^{(l)}_{i,j} := 0$,对于训练样本t=1到m,
1. 设$a^{(1)} := x^{(t)}$
2. 执行前向传播计算$a^{(l)}$,即$a^{(1)} = x, z^{(2)} = \Theta^{(1)}a^{(1)}, a^{(2)} = g(z^{(2)}), z^{(3)} = \Theta^{(2)}a^{(2)}, \cdots$
3. 利用$y^{(t)}$计算最后一层的误差:$\delta^{(L)} = a^{(L)} - y^{(t)}$,这样就能往前计算每一层的误差
4. 利用$\delta^{(l)} = ((\Theta^{(l)})^T \delta^{(l+1)})\ .*\ a^{(l)}\ .*\ (1 - a^{(l)})$计算之前每一层的误差,其中也可用$g'(z^{(l)}) = a^{(l)}\ .*\ (1 - a^{(l)})$来简化形式
5. 更新$\Delta^{(l)}_{i,j} := \Delta^{(l)}_{i,j} + a_j^{(l)} \delta_i^{(l+1)}$,那么
$$D^{(l)}_{i,j} := \dfrac{1}{m}\left(\Delta^{(l)}_{i,j} + \lambda\Theta^{(l)}_{i,j}\right), j \ne 0$$
$$D^{(l)}_{i,j} := \dfrac{1}{m}\Delta^{(l)}_{i,j}, j = 0$$
这就是我们要求的偏导数$\frac \partial {\partial \Theta_{ij}^{(l)}} J(\Theta)=D_{ij}^{(l)}$
这个算法乍看上去很难理解,到底是在做些什么?
考虑一个简单情况,非多类分类问题(k=1),且忽略正则化,对于单个样本$x^{(t)}, y^{(t)}$,代价函数为
$cost(t) =y^{(t)} \ \log (h_\Theta (x^{(t)})) + (1 - y^{(t)})\ \log (1 - h_\Theta(x^{(t)}))$
直观上来说,$\delta_j^{(l)}$是$a^{(l)}_j$的误差,更正式来说,它其实是代价函数的导数$\delta_j^{(l)} = \dfrac{\partial}{\partial z_j^{(l)}} cost(t)$。所以要求梯度下降法中的导数,就要计算误差值,然后去更新权重参数。而计算一个节点的误差项,需要先计算每个与其相连的下一层节点的误差项。这就要求误差项的计算顺序必须是从输出层开始,然后反向依次计算每个隐藏层的误差项,直到与输入层相连的那个隐藏层。
还是不懂在说些什么是吧?其实,反向传播就类似于“从错误中学习”:一开始,所有的权重都是随机分配的,对于训练数据集输入,神经网络得到一组输出。这个输出会和我们已知的的输出作比较,误差会传播回上一层。依次计算每一层的误差,权重也会被相应的调整。反复执行该流程,直到输出误差足够低,就得到了一个训练好的神经网络。
2. Implementation Note
在神经网络的具体实施过程中,一些技巧能够让我们更好的实现效果。例如,参数展开(Unrolling Parameters):
对于需要处理的矩阵
$\begin{align*} \Theta^{(1)}, \Theta^{(2)}, \Theta^{(3)}, \dots \newline D^{(1)}, D^{(2)}, D^{(3)}, \dots \end{align*}$
我们可以把它们展开到长向量中:
thetaVector = [ Theta1(:); Theta2(:); Theta3(:); ]
deltaVector = [ D1(:); D2(:); D3(:) ]
当然也可以从长向量中求得原始的值(假设Theta1为10x11,Theta2为10x11,Theta3为1x11):
Theta1 = reshape(thetaVector(1:110),10,11) Theta2 = reshape(thetaVector(111:220),10,11) Theta3 = reshape(thetaVector(221:231),1,11)
这样,我们就可以利用Octave中的fminunc()函数来实现算法,fminunc(@costFunction, initialTheta, options)。
另一个技巧就是梯度检验(Gradient Checking):在算法实现过程中,如何确认你的代码是否正确工作呢?梯度检验的思路就是通过近似估算当前的梯度,与计算得到的值进行比较,如果二者相差在允许误差范围内,说明代码运行正常,怎么估算呢?
$\dfrac{\partial}{\partial\Theta}J(\Theta) \approx \dfrac{J(\Theta + \epsilon) - J(\Theta - \epsilon)}{2\epsilon}$
这个不难理解,在切线出作三角形就可以得到上式近似。多个Theta矩阵的话,可以用下式估算:
$\dfrac{\partial}{\partial\Theta_j}J(\Theta) \approx \dfrac{J(\Theta_1,\Theta_j + \epsilon, \Theta_n) - J(\Theta_1 , \Theta_j - \epsilon, \Theta_n)}{2\epsilon}$
有了估算公式,在具体的实现中,我们利用反向传播算法来计算梯度向量DVec,然后利用梯度检验方法得到gradApprox,如果二者相近,则关闭梯度检验,使用反向传播继续学习。为什么验证后要关闭梯度检验?因为在每一次迭代中都计算该梯度将会使代码变得很慢。
最后,随机初始化(Random Initialization)是有必要的,所有参数初始化为0是不合适的,因为在反向传播中,所有节点都会更新为相同值,正确的做法是将$\Theta^{(l)}_{ij}$初始化为$[-\epsilon, \epsilon]$之间随机值。
3. Putting it Together
综上所述,神经网络的算法具体实现可以归纳为:
在训练之前,首先必须设计神经网络架构,包括总共多少层,每层多少个节点,通常输入单元的数量=样本特征的维度,输出单元的数量=分类的数量,隐藏层单元的数量=通常越多越好(但必须与计算成本相平衡),另外,如果隐藏层超过1层,通常设计成每个隐藏层节点数量一致。然后,就可以训练神经网络:
1. 随机初始化权重。
2. 实施前向传播,得到$h_\Theta(x^{(i)})$。
3. 实施代价函数。
4. 实施反向传播,计算偏导数。
5. 使用梯度检验来确认反向传播计算正确,然后关闭梯度检验。
6. 使用梯度下降或其它优化算法最小化代价函数。
理想情况下,$h_\Theta(x^{(i)}) \approx y^{(i)}$,使得代价函数最小,但是由于$J(\Theta)$不是凸函数,所以我们可能得到的只是局部最小值。
------Week 6------2018.12.05------
Advice for Applying Machine Learning
Machine Learning System Design
1. Evaluating a Learning Algorithm
如果在实施正则化线性回归以预测房价的过程中,你发现预测值有很大的误差,那么应该怎么做?以下有几种思路:
- 获得更多的训练样本
- 尝试更小的特征集
- 尝试获取额外的特征
- 尝试特征的多项式组合
- 尝试增加或减小$\lambda$
但如何知道哪种方法有效,逐一尝试显然不是最合适的方法。在改进我们的算法之前,我们需要做的是诊断(Diagnostic),它能让你深入了解算法中哪些起作用,哪些不起作用,并指导你如何最好的提升算法性能。尽管有时候诊断需要花费一些时间,但这是值得的!
有的时候,我们把机器学习算法训练得很好,对于训练样本能够很好的预测和分类,但是遇到样本集以外的新样本,性能就急剧下降。为了避免这种情况,在训练过程中,我们会把训练样本分为训练集(train,通常为70%)和测试集(test,通常为30%),那么训练过程可以改进为:
- 从训练集中学习参数$\theta$(最小化训练误差$J(\theta)$)
- 计算测试集误差
对于线性回归,测试集误差计算如下:
$J_{test}(\Theta) = \dfrac{1}{2m_{test}} \sum_{i=1}^{m_{test}}(h_\Theta(x^{(i)}_{test}) - y^{(i)}_{test})^2$
对于逻辑回归,测试集误差计算如下:
$J_{test}(\theta) = -\frac{1}{2m_{test}}\sum_{i=1}^{m_{test}}y^{(i)}_{test}log(h_{\theta}(x^{(i)}_{test})) + (1-y^{(i)}_{test})log(1-h_{\theta}(x^{(i)}_{test}))$
如果训练集误差很小,但是测试集误差很大,那很有可能是过拟合,那么如何选择合适的假设模型呢?以多项式回归为例,假设函数可以是n阶方程,那么怎么知道n到底是多少合适?测试集只能给出当前模型下误差,因此我们有必要从训练样本集中再分出一部分数据作为交叉验证集(cross validation),通常比例为60%,20%,20%,那么便可以分别计算三部分的误差值,以此来评价算法性能:
1. 利用训练样本集,对于每个多项式假设模型,计算优化参数$\Theta$
2. 利用交叉验证集,得到最小误差对应的假设模型
3. 利用测试样本集,计算该算法的预测误差
得到了该算法的误差指标,我们并不清楚应该如何改进我们的算法,因此有必要引入另外两个特征指标:偏差(bias)和方差(variance)。
通常,欠拟合表示高偏差,过拟合表示高方差,我们的目标就是找到一个模型,让二者平衡,尽可能都小。以下图为例:
在多项式回归中,我们知道通常如果只用一阶函数去拟合曲线,误差都会比较大,如果阶数越高,对训练集的拟合就越好,误差就越小,这就是$J_{training}(\Theta)$随着d增加而下降的原因。但并不是阶数越高越好,容易出现过拟合的问题,所以当d超过某一个值后,$J_{cross-validation}(\Theta)$反而开始转为上升。总结来说,
在高偏差(High bias,underfitting)中,$J_{train}(\Theta)$和$J_{CV}(\Theta)$都很高,且二者相近;
在高方差(High variance,overfitting)中,$J_{train}(\Theta)$很低,而$J_{CV}(\Theta)$远大于$J_{train}(\Theta)$。
在之前的课程中,我们知道正则化可以有效减少过拟合,通常$\lambda$很大时,会造成求解代价函数最小值的过程中尽可能的减小$\theta_1, \theta_2, \cdots$,因此容易造成欠拟合,即高偏差;$\lambda$很小时,正则化几乎不起作用,所以容易造成过拟合,即高方差,那么怎样的$\lambda$才是合适的呢?以下是常用的做法:
1. 创建一个$\lambda$列表(例如,λ∈{0,0.01,0.02,0.04,0.08,0.16,0.32,0.64,1.28,2.56,5.12,10.24})。
2. 创建一个带不同次数或任意变量的模型集合。
3. 遍历$\lambda s$,对于每个$\lambda$在模型集合中训练,得到$\Theta$。
4. 不使用正则化(或$\lambda = 0$),利用上面得到的$\Theta$计算交叉验证误差$J_{CV}(\Theta)$。
5. 选择令交叉验证得到的误差最低的最佳组合。
6. 使用最佳的$\Theta$和$\lambda$,应用于$J_{test}(\Theta)$,测试它是否有好的性能。
学习曲线(Learning Curves)是另一种评价和检查算法有效性的指标,如果我们只有几个样本点,那么很容易找到一个曲线来完美的拟合它,但是随着训练集的增大,误差将会增大,而误差随着训练集的不断增大,会趋于平缓。如下图所示:
从左图可以得到,如果算法当前高偏差,那么增加样本数量,会使得$J_{train}(\Theta)$和$J_{CV}(\Theta)$都很高且相近,因此并没有什么帮助。
从右图可以得出,如果算法当前高方差,那么增加样本数量,会使得$J_{train}(\Theta)$增大,$J_{CV}(\Theta)$减小,且二者之间距离较远,因此可以起到一定作用。
总结一下:
- 更多训练样本:解决高方差(一定程度上)
- 减少特征集:解决高方差(无谓的特征太多,干扰了我们的拟合,容易过拟合)
- 增加特征:解决高偏差(特征太单调,仅靠面积就想预测房价,肯定有很大偏差)
- 增加多项式特征:解决高偏差(用曲线去拟合数据,会比直线更准一些)
- 减小$\lambda$:解决高偏差(正则化作用减小,高次因子发挥功能,更能精确拟合数据)
- 增大$\lambda$:解决高方差(正则化起作用,降低高次因子的影响,不容易过拟合)
对于神经网络而言,越少的参数越容易欠拟合,尽管计算成本降低;越多的参数越容易过拟合,同时计算成本也很高(可以使用正则化减少过拟合)。一开始的时候应该尽量选择一层的隐藏层,然后使用交叉验证集训练多个隐藏层的神经网络,从中选择一个最优的。
模型的复杂性对算法的影响在于:低阶多项式(低模型复杂度)具有高偏差和低方差,不能很好的拟合数据;高阶多项式(高模型复杂度)在训练数据中表现很好,在测试数据中有时却很糟糕,即低偏差,高方差。因此,必须选择一个介于二者之间的模型,才能更好的拟合数据。
2. Building a Spam Classifier
举个垃圾邮件分类器的例子,如何判断一封邮件是不是垃圾邮件?通常,如果这封邮件语法和拼写各种出错,或者带有明显的推销和广告的字眼,那么我们就认为它是一封垃圾邮件。以关键字为例,我们选择最常见的垃圾邮件关键字100个(实际中通常会选择1万到5万个关键字),作为特征$x$,构成100x1的向量,如果邮件中包含这个关键字,则对应元素置1;$y$表示分类结果,1表示垃圾邮件,0表示正常邮件。这样我们就能通过训练样本集来训练我们的算法,检测是否垃圾邮件。在这过程中,如何减小分类误差?你可以:
- 收集大量的数据
- 选用更为复杂的特征
- 选用不同的算法以不同方式处理邮件
- ……
但是很难说哪种方式最好,我们必须有一套误差分析(Error Analysis)准则,通常推荐的做法是:
- 采用一个简单的算法,快速的实施,尽早用交叉验证数据测试;
- 绘制出学习曲线,看看更多的数据,或者更多的特征,等等,是否有帮助;
- 手动检查交叉验证误差,尝试找出是什么造成误差最大
例如,如果我们有500封邮件,而我们的算法误分类了其中100封,那我们可以手动检查这100封邮件,尝试根据它们的类型分类,然后分析出新的特征可以帮助我们准确的对它们进行分类。例如,如果这些邮件都企图盗窃你的密码,那么我们可以归纳出新的特征,加到我们的模型中;或者在模型中是否要考虑单词的大小写,词性变化等要素。
误差分析不一定有用,但是值得一试,且试且行,量化的误差分析十分重要,否则的话很难去评估算法性能。例如,如果你在算法中考虑了词性变化,误差只有3%,不考虑的话误差有5%,那么我们当然应该把这个加到算法里。但如果考虑单词大小写和不考虑大小写,误差一个是3.2%,一个是3%,那就没必要加入这个新特征。
3. Handling Skewed Data
在机器学习算法的实施过程中,有时候样本数据很不平衡,存在倾斜(Skewed),例如在癌症诊断分类器中,建立逻辑回归模型,1表示有癌症,0表示没有,最终得到算法准确率有99%,只有1%的误差。听起来好像很不错,但如果我们发现样本数据中只有0.5%的病人有癌症,那么算法的准确度就不见得很不错。即便在你的算法里,你简单粗暴地判断所有的样本分类值都为0,这个算法也只有0.5%的误差,甚至还比之前的算法“好”!所以不能简单的从误差上判断算法的优劣。有必要引入精确率(Precision)和召回率(Recall):
Actual Class | |||
Predicted Class |
1 | 0 | |
1 | True Positive | False Positive | |
0 | False Negative | True Negative |
精确率:$\frac{True pos}{predicted pos} = \frac{True pos}{True pos+ false pos}$,即对于我们预测为1-有癌症的病人,真正有癌症的占几成?
召回率:$\frac{True pos}{actual pos} = \frac{True pos}{True pos+ false neg}$,即对于真正有癌症的病人,我们准确预测出了几成?
通常二者需要达到一个平衡,对于逻辑回归来说,我们通常会预测$h_\theta(x)$大于0.5为1,小于0.5为0。如果我们想要在十分有把握的情况下才判断这个病人有癌症,那就需要把阈值调高,例如调至0.9,只有当$h_\theta(x)$大于0.9的时候才判断为1,这时精确率将会提高,召回率将会降低;如果我们不想错过任何有可能的癌症患者,那就需要把阈值调低,例如调至0.1,只要$h_\theta(x)$大于0.1就判断为1,这时精确率将会降低,召回率将会提高。(直觉上不难理解)
怎么比较两个指标呢?我们引入了另一个指标F1 Score:$F = 2\frac{PR}{P+R}$,当P=0或者R=0时,F1为0,当P=1且R=1时,F1为1。
4. Using Large Data Sets
在一定条件下,数据量越大,算法的训练就越好,也就是常说的“It's not who has the best algorithms that wins, it's who has the most data.”
但前提条件是什么呢?
1. 特征x是否包含了足够多的信息来准确的预测y?(单纯从房屋面积预测房价显然不合理;或者给定了x,人类的专家能自信的预测出y吗?)
2. 使用带许多参数的学习算法(例如带许多参数的线性/逻辑回归,或者许多隐藏层的神经网络)
------Week 7------2018.12.07------
Support Vector Machines
1. Large Margin Classification
回忆一下逻辑回归,$h_\theta(x) = \frac{1}{1+e^{-\theta^T x}}$,如果$y =1$,我们希望$h_\theta(x) \approx 1$,即$\theta^T x >> 0$;如果$y =0$,我们希望$h_\theta(x) \approx 0$,即$\theta^T x << 0$。代价函数为:
$J(\theta) = \frac{1}{m}[\sum_{i=1}^m y^{(i)} (-logh_{\theta}(x^{(i)})) + (1-y^{(i)})(-(log(1-h_\theta(x^{(i)}))))] + \frac{\lambda}{2m}\sum_{j=1}^{m}\theta_j^2$
回忆y=1和y=0的曲线(见week3),是上升和下降的曲线,如果我们用更严格的直线来替换这两条曲线,例如y=1,当z大于某个数时,代价函数为0,如下图所示:
那么,代价函数可以替换成:
$J(\theta) = \frac{1}{m}[\sum_{i=1}^m y^{(i)} Cost_1(\theta^Tx^{(i)}) + (1-y^{(i)})Cost_0(\theta^Tx^{(i)})] + \frac{\lambda}{2m}\sum_{j=1}^{m}\theta_j^2$
不考虑m(因为不影响最小化结果),提取$\lambda$,则也可以写成:
$J(\theta) = C\sum_{i=1}^m [y^{(i)} Cost_1(\theta^Tx^{(i)}) + (1-y^{(i)})Cost_0(\theta^Tx^{(i)})] + \frac{1}{2}\sum_{j=1}^{m}\theta_j^2$
这就是被称为支持向量机(Support Vector Machines)的代价函数。它与逻辑回归不同的地方在于:如果$y =1$,我们希望$\theta^T x \geq 1$,而不是只是大于等于0;如果$y =0$,我们希望$\theta^T x \leq -1$,而不是只是小于0。当C很大时(也被称为惩罚系数),就要求代价函数的前一部分非常小,即满足上述的条件,此时求代价函数最小值就转化为求$\frac{1}{2}\sum_{i=1}^{n}\theta_j^2$的最小值,这个式子也可以表示为求$||\theta||$最小值,那么$\theta^T x$表示什么含义呢?
回忆一下,两个向量相乘(或内积)$u^Tv = p \cdot ||u||$,其中$p$是$v$在$u$上的投影长度(可正可负),所以$\theta^T x^{(i)} = p^{(i)} \cdot ||\theta||$,其中$p^{(i)}$是$x^{(i)}$在向量$\theta$上的投影长度。所以,我们希望$p^{(i)}$尽可能的大,即$x^{(i)}$在$\theta$上的投影尽可能大,这样满足了约束条件,才能转化为求$||\theta||$最小值。
以下图左图为例,红色线和蓝色线都能区分正负集,但很明显我们会觉得蓝色的决策边界更为合理。对于红色决策边界,离某些样本点过于近,垂直于该边界的法线为$\theta$的方向,那么作这些样本点在法线上的投影,$||p^{(i)}||$就会比较小,这样为了使约束条件满足,我们需要$||\theta||$取值很大,因此这条直线不算非常好的决策边界。相反的,对于蓝色决策边界,样本点在$\theta$上的投影相对更大,因此$||\theta||$可以取值更小。
其实支持向量机的思想就是找到正负样本集最中间的分界线,也可以看成如果想在中间修一条笔直的马路,怎么样才能让这条马路最宽?而马路的中间就是最佳的决策边界,这也是为什么被称为最大间距分类(Large Margin Classification)。为此,根据代价函数,就必须找到样本点在某个向量上的投影$p$最长,进而转化为求$||\theta||$的最小值。
2. Kernels
在之前的课程中,我们遇到过非线性拟合问题,当时我们采用的是多项式拟合的方法,即取多项式为新的特征,但是这个方法的一个缺点在于随着多项式次数增高,计算量逐渐加大,有没有另外的构成新特征的方法?这里引入核函数(Kernel)方法:
首先,取几个标记点$l^{(i)}$,计算样本和标记点的相似性$f_i = similarity(x, l^{(i)}) = exp(-\frac{||x - l^{(i)}||^2}{2\delta^2})$,这里的$exp$函数为高斯核函数,当$x \approx l^{(i)}$时,$f_i \approx 1$,当$x$离$l^{(i)}$很远时,$f_i \approx 0$,也就是离标记点越近值越高。然后将计算得到的$f_i$带入Hypothesis中进行预测。以三个标记点为例,当$\theta_0 + \theta_1 f_1 + \theta_2 f_2 + \theta_3 f_3 \geq 0$时,预测为1。那么,标记点怎么选择呢?
一种方法是取样本集的点为标记点。假设有m个样本,则有m个标记点$l$,这样可以计算出m+1个特征$f$(其中$f_0 = 1$),当$\theta^T f \geq 0$时,预测$y = 1$,怎么得到参数$\theta$呢?其实就是最小化下式:
$J(\theta) = C\sum_{i=1}^m [y^{(i)} Cost_1(\theta^Tf^{(i)}) + (1-y^{(i)})Cost_0(\theta^Tf^{(i)})] + \frac{1}{2}\sum_{j=1}^{m}\theta_j^2$
这就是带核函数的SVM。
最后提一下SVM中参数对算法的影响:
C(=1/λ):值很大(λ很小),则低偏差,高方差;值很小(λ很大),则高偏差,低方差。
$\delta^2$:值很大,则特征$f_i$变化平缓,即高偏差,低方差;值很小,则特征$f_i$变化不平缓,即低偏差,高方差。
3. Using an SVM
具体在实践中,怎么使用SVM呢?
直接利用SVM软件包中的函数进行机器学习,优化参数$\theta$。你需要做的就是确定参数C,以及确定核函数(如果没有核函数,则称为线性核函数;如果选择高斯核函数,就要确定$\delta^2$,并记得先进行特征缩放!)。当然,也有许多其它核函数可以选择,但不是所有的相似性函数都是有效的核函数,必须满足Mercer's Theorm。
对于多分类问题,许多SVM包以及集成了分类函数,直接调用即可,使用之前介绍过的one-vs.-all方法也是可以的。
最后,何时使用逻辑回归,何时使用SVM?以下是一些参考:
1. 特征维度很大,可使用逻辑回归,或不带核函数的SVM;
2. 特征维度小,样本数中等,则使用带高斯核函数的SVM;
3. 特征维度小,样本数大,则增加新的特征,然后使用逻辑回归,或不带核函数的SVM;
4. 神经网络对于以上情况均表现不错,就是可能训练起来会很花时间。
------Week 8------2018.12.08------
Unsupervised Learning
Dimensionality Reduction
1. Clustering
这周开始介绍无监督性学习(unsupervised learning),这里每个样本并没有标记值,因此需要找到一个算法能够自动地将它们分类,如下图所示。
其中一种基本的算法称为聚类算法(Clustering Algorithm),而其中最简单的则是被称为K-means算法:
1. 随机选择K个聚类质心点cluster centroids(假设要分成K类)$\mu_1, \mu_2, \cdots, \mu_k$;
2. 重复执行以下步骤,直至收敛:
对于每一个样本,通过$c_{i} := arg min_i ||x^{(i)} - \mu_j||^2$计算离哪个centroids最近,则标记为属于哪一类
对于每一个质心点,根据上面计算后归类的点,重新计算均值质心点$\mu_k$
听起来有点绕口,其实看图很直观:
其实,这个过程也可以看出是一个最优化问题,或者最小化代价函数问题,只是这里的代价函数为:
$J(c^{(1)}, \cdots, c^{(m)}, \mu_1, \cdots, \mu_k) = \frac{1}{m}\sum_{i=1}^{m} ||x^{(i)} - \mu_{c^{(i)}}||^2$
在K-means算法中,随机挑选初始值,可能会影响最后的结果,有可能就会找到局部最优解,例如几个质心点都在同一个簇中。一种比较推荐的初始化方法是从1到m中随机挑选k个数,取这k个数对应的样本值作为初始聚类质心。另外,可以多次随机初始化,运行K-means算法,然后计算对应代价函数,选择最小的那个。
另外还有一个问题,怎么知道要分几类?即K取多少?
一种方法是Elbow method,即计算随着K的增加,代价函数的变化曲线,如果在某个点有明显的转角(类似手肘),则那个点一般是比较合适的K值。
但如果曲线很平滑的话,那么这种方法就失效了。另一种方法是根据实际的应用场景设置,例如根据需求决定T-shirt的尺寸需要分成几类。
2. Principal Component Analysis
在实际应用中,数据的维度往往是很大的,带来的计算量也非常庞大,因此,数据降维(Data Dimensionality Reduction)是很有必要的。 例如我们可以在二维坐标系中做一条直线向量,把所有二维点投影到该向量上,取这些点在该向量上的位置作为新的特征值(一维);又或者把三维坐标系中的点投影到一个平面上,即完成3维到2维的降维。
除了数据压缩(Data Compression),降维的另一个需求是数据可视化(Data Visualization),例如我们收集了每个国家的GDP,人均GDP,人类发展指数,预期寿命等等,很难去绘制出多维度的图,但是如果我们能降维成2个特征,那么就可以用图展示出来,更加直观。
对于实现数据降维,最常用的算法是主成分分析法(Principal Component Analysis,PCA),它的算法思想是由高维向低维(使得投影误差最小)投影。例如,从2维向1维投影,就是找到一个向量,使得数据投影到这个向量后的投影误差最小。类似的,从n维到k维投影,就是找到k个向量,使得数据投影到这些向量的投影误差最小。
这个似乎和线性回归很像,在线性回归中,也似乎是找到一条直线最好的拟合这些点。不过二者其实不同,在线性回归中计算的是预测值与实际值的误差(以二维坐标为例,就是计算y方向上的误差),而在PCA中计算的是数据点到向量的垂直距离。
PCA的具体算法如下:
1. 数据预处理:进行特征缩放和均值归一化处理;
2. 计算样本之间的协方差矩阵covariance matrix:$Sigma = \frac{1}{m}\sum_{i=1}^{m}(x^{(i)})(x^{(i)})^T$;
3. 进行奇异值分解,计算特征向量[U, S, V] = svd(Sigma);
4. 提取前K个主成分Ureduce = U(:, 1:k);
5. 降维后的数据z = Ureduce' * x;
降维之后如果要恢复的话,也是可以的,x = Ureduce * z,这里是近似值。
另外,如何选择k?
1. 计算平均均方投影误差(Average Squared Projection Error):$\frac{1}{m}\sum_{i=1}^{m}||x^{(i)} - x_{approx}^{(i)}||^2$;
2. 计算数据总方差(Total Variation):$\frac{1}{m}\sum_{i=1}^{m}||x^{(i)}||^2$
3. 选择使得上面两式相除后值最小的k,如果值小于0.01,则我们可以说PCA算法保留了原数据99%的差异性。
因此,在实际应用中,我们通常是先设定好阈值,如我们希望保留99%的差异性,然后从k=1开始尝试,如果不满足则k加1,直至满足条件的最小的k出现。
PCA算法可以用于加速监督学习:提取训练样本的输入$(x^{(i)}, y^{(i)})$,运用PCA降维(如从10000降到1000),得到新的训练样本集$(z^{(i)}, y^{(i)})$,用其进行机器学习求解最优参数。另外,PCA算法只用于训练样本中,得到映射关系后,可以直接运用与交叉验证数据和测试数据。
总结一下,
1. PCA的应用场景在于:1. 数据压缩(减少存储空间,加速学习算法)2. 数据可视化。
2. 人们会认为PCA减少了特征的数量,因此可以减少过拟合,这是不正确的。正确的应该是使用正则化。
3. 在设计机器学习系统时,不应该一上来就用PCA算法,而是应该尝试用原始数据进行训练学习,只有当算法结果不理想时,才需要尝试考虑PCA算法。
------Week 9------2018.12.08------
Anomaly Detection
Recommender Systems
1. Anomaly Detection
机器学习的一个应用场景就是异常检测(Anomaly Detection),什么是异常检测?举个例子,对于航空发动机,有几个特征参数决定它工作正不正常:$x_1$:工作产生的热量;$x_2$:震动强度,等等。你收集到了一些数据,那么对于一台新的发动机,你需要根据之前的样本集来判断它是否有异常。
通常,这些样本点都会围绕一个中心点分布,因此,如果越接近样本点的中心,正常的概率越高,离中心越远,异常的可能性就越高。
因此处理此类问题的通常做法是建立一个概率模型$p(x)$,它以样本中心为峰值,向外递减(类似于等高线)。如果测试数据代入这个概率模型中,求得概率小于某个小值$\epsilon$,则判定它为异常样本。
这种异常检测在诸如欺诈检测(用户行为监测),制造业(产品QA测试),数据中心主机监控等方面有重要应用。
那么如何建立概率模型?常用的是高斯(正态)分布,这是因为自然界中许多事件的概率都服从该分布,其概率公式为$p(x) = \frac{1}{\sqrt{2\pi}\sigma}\exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)$,这个大家应该很熟悉了,就不过多介绍,值得一提的是独立分布事件的概率等于事件概率的乘积。
有了概率模型,异常检测的算法就可以具体为:
1. 选出你觉得可能会指示出异常的重要特征$x_i$
2. 计算各个特征的均值与方差$\displaystyle \mu_j = \frac{1}{m}\sum_{i=1}^m x_j^{(i)},\ \sigma_j^2 = \frac{1}{m}\sum_{i=1}^m(x_j^{(i)} - \mu_j)^2$,得到每种特征的概率$p(x_j; \mu_j, \sigma_j^2)$
3. 对于一个新样本,计算其概率是否小于$\epsilon$,其中$p(x)$等于各项特征概率的乘积。
有了异常检测算法,我们还需要知道如何去评估异常检测系统性能。最常用的方法就是跟监督性学习一样,将样本集分成Trainning Set,Cross Validation Set,和Test Set(通常为60%,20%,20%)。这样的话,就可以用之前的指标去评估系统性能,具体如下:
1. 对训练集进行学习,建立概率模型$p(x)$;
2. 对交叉验证集进行测试,概率小于$\epsilon$的预测为1-anomaly,然后利用之前介绍过的Precision/Recall/F1-score来评价算法;也可以用交叉验证集来选择参数$\epsilon$。
有人可能会问,这类问题如果用监督性学习来做,是否也可以?同样是有带标记的样本集,训练后用来对新样本进行分类(0/1)。二者其实是有一些区别的:
在异常检测中,只有少量的正样本(y=1,通常20个以内),但有大量的负样本;同时异常的种类也很多,很难通过这些正样本学习到所有的异常类型;之后的异常类型也有可能与当前的完全不一样。在这种情况下,用概率模型去检测是比较合理的做法。在监督学习中,有许多的正样本和负样本,包含足够多的正样本让算法获取正样本的信息,而未来的正样本也跟当前训练集的正样本类似。
因此二者的应用场景也有所不同,异常检测通常应用于欺诈检测,工业质检,数据中心检测等,监督学习通常应用于垃圾邮件分类,天气预测,癌症诊断等。
整个异常检测算法是基于样本中的特征概率符合高斯分布的假设,那如果样本特征不服从高斯分布怎么办?有时候可以做一些简单的数学转换,让其更服从高斯分布即可,如做log变换,或者做平方根,立方根转换。
另外,在算法中我们希望$p(x)$对于正常样本值很大,对于异常样本值很小。但有时单个特征中的正常和异常样本的$p(x)$比较相近,因此如果能增加一个特征结合一起判断,准确度会更高(即类似于0.3x0.3=0.09)。
最后再提一点,之前的异常检测系统我们都考虑特征之间是彼此独立不相关的,因此概率直接相乘就好。但是也许两个特征是有相关性的呢?例如在数据中心主机监测问题中,CPU的温度是一个特征,网络流量也是一个特征,如果不考虑相关性,某个时间点CPU温度很高,因此极有可能异常,网络流量也很大,也极有可能异常,两者概率相乘,直接就判定为主机异常。但是,我们都知道网络流量很大时,CPU的负载就会很高,温度自然会比较高,但这时主机还是在正常工作状态的!所以,必须考虑样本特征之间的相关性,例如可以选择新变量为CPU温度/网络流量。
另一种方法就是使用多元高斯分布模型(Multivariate Gaussian Distribution),相比正常的高斯分布呈均匀圆形分布,多元高斯分布由于特征之间的相关性,可能会呈椭圆形分布。
多元高斯分布的概率模型为:
$p(x; \mu, \sum) = \frac{1}{(2\pi)^{n/2}|\sum|^{1/2}}exp(-\frac{1}{2}(x-\mu)^T \sum^{-1}(x-\mu))$
其中,$\mu = \frac{1}{m}\sum_{i=1}^{m}x^{(i)}$是每个正态分布的对称轴,$\sum = \frac{1}{m}\sum_{i=1}^{m}(x^{(i)}-\mu)(x^{(i)}-\mu)^T$是协方差矩阵。关于这两个参数对图形形状的影响,这里不再赘述。
因此利用多元高斯分布进行异常检测的算法如下:
1. 对于训练样本集,根据上面的式子分布计算$\mu$和$\sum$,得到$p(x)$;
2. 对于新样本,计算其$p(x)$,如果小于$\epsilon$,则判定为异常。
对比之前的异常检测模型,多元高斯分布检测模型的特点在于它计算中自动包含特征间的相关性,但是相对的计算成本更高,同时还必须要求样本数大于特征数,不然的话协方差矩阵不可逆(通常要求m≥10n)。而单元告诉分布检测模型需要手动创建新特征,以减少特征相关性带来的影响,不过它的计算成本比较低,另外在样本集比较小的时候也能适用。
2. Recommender Systems
推荐系统(Recommender Systems)目前已深入到我们生活的点点滴滴, 今日头条,淘宝广告,豆瓣主页,几乎每个App都有自己的推荐算法,根据客户之前的浏览和评价记录推荐可能感兴趣的内容,定位更为精准,虽然有时候也挺烦的。那么如何建立一套推荐系统?
以电影评分举例,假设有5部电影,前三部是爱情片,后两部是动作片,有4位用户A、B、C、D的评分如下55?00,5?400,0?035,00?4?(其中?表示未评分,需要我们去预测),根据直观的判断,我们推测A和B比较喜欢爱情片,讨厌动作片,因此A对第三部电影的评分大概会是4或5,B同理。C的话对两部爱情片都评0分,因此有理由推测他对第二部爱情片评分也会很低。这就是基于内容推荐(Content-based recommender)的基本简单思想,具体怎么做呢?
用户数量记为$n_u$,电影数量记为$n_m$,$r(i,j)=1$表示用户$j$对电影$i$已经评分过/rated,$y^{(i,j)}$则表示对应的电影评分,$\theta^{(j)}$是用户$j$的参数向量,$x^{(i)}$是电影的特征向量,$m^{(j)}$是用户$j$评分过的电影数量,那么$y^{(i,j)} = (\theta^{(j)})^T x^{(i)}$。举个例子,如果我们已经知道第三部电影的特征向量为$x^{(3)} = [1, 0.99, 0]^T$,那么通过算法学习得到第一位用户的$\theta^{(1)} = [0, 5, 0]$,那么可以求得用户1对电影3的评分为$(\theta^{(1)})^T x^{(3)} = 4.95$。
这里有两个问题,一是电影特征向量怎么得到?当然,可以人为的取特征,并给出值,如取爱情,动作为特征,人为给出电影3的特征为$[1, 0.99, 0]^T$(表示这部电影爱情成分居多,毫无动作成分),也可以让系统自动归纳,这个后面再谈。二是如何学习$\theta$?同之前代价函数一样,用户$j$所有评过分的电影作样本集,最小化预测值与实际值,并采用正则化:
$min_{\theta^{(j)}} \frac{1}{2} \sum_{i:r(i,j)=1} ((\theta^{(j)})^T x^{(i)} - y^{(i,j)})^2 + \frac{\lambda}{2} \sum_{k=1}^{n}(\theta_k^{(j)})^2$
如果要学习每个用户的参数,则
$min_{\theta^{(1)},\cdots,\theta^{(n_u)}} \frac{1}{2} \sum_{j=1}{n_u} \sum_{i:r(i,j)=1} ((\theta^{(j)})^T x^{(i)} - y^{(i,j)})^2 + \frac{\lambda}{2} \sum_{j=1}^{n_u} \sum_{k=1}^{n}(\theta_k^{(j)})^2$
这样就可以使用梯度下降法去优化参数。
以上的基于内容推荐算法是基于我们得到不同电影的特征向量,但是实际应用中我们很难确定所有的特征,以及对应的特征向量,因此我们需要一种算法能够自动地学习所要的特征,这就是以下要介绍的协同过滤(Collaborative Filtering)。如果用户能够告诉我们他有多喜欢看爱情片,多喜欢看动作片,那么我们就能反过来根据他们的评分反推这部电影的特征,也就是通过$\theta$学习$x$,这就是协同的含义,给定$x$可以学习$\theta$,给定$\theta$可以学习$x$,如此反复,同时最小化两类参数,即:
$J(x^{(1)},\cdots,x^{(n_m)},\theta^{(1)},\cdots,\theta^{(n_u)}) = \frac{1}{2} \sum_{(i,j):r(i,j)=1} ((\theta^{(j)})^T x^{(i)} - y^{(i,j)})^2 + \frac{\lambda}{2} \sum_{i=1}^{n_m} \sum_{k=1}^{n}(x_k^{(i)})^2 + \frac{\lambda}{2} \sum_{j=1}^{n_u} \sum_{k=1}^{n}(\theta_k^{(j)})^2$
协同过滤的算法可以归纳如下:
1. 初始化$x^{(1)},\cdots,x^{(n_m)},\theta^{(1)},\cdots,\theta^{(n_u)}$为很小的随机值;
2. 使用梯度下降算法或其它高级优化算法最小化代价函数,求得$\theta$和$x$;
3. 利用$\theta^T x$预测用户对电影的评分。
协同过滤的向量化实现方法如下:
令$X = \begin{bmatrix} - & (x^{(1)})^T & - \\ & \vdots & \\ - & (x^{(n_m)} & - \end{bmatrix},\ \Theta = \begin{bmatrix} - & (\theta^{(1)})^T & - \\ & \vdots & \\ - & (\theta^{(n_u)} & - \end{bmatrix}$
则$X\Theta^T = \displaystyle \begin{bmatrix} (x^{(1)})^T(\theta^{(1)}) & \ldots & (x^{(1)})^T(\theta^{(n_u)})\\ \vdots & \ddots & \vdots \\ (x^{(n_m)})^T(\theta^{(1)}) & \ldots & (x^{(n_m)})^T(\theta^{(n_u)})\end{bmatrix}$
也就是所谓的低秩矩阵分解。
从这个过程中我们也可以衡量特征向量之间的距离,如果两部电影的特征向量之间距离很小$small \ ||x^{(i)}-x^{(j)}||$,那么就表明这两部电影很相似。
最后提一下,如果有个用户从来没有对任何电影评分过,这如何预测?这时可以利用均值归一化方法:
$ Y = \begin{bmatrix} 5 & 5 & 0 & 0 & ? \\ 5 & ? & ? & 0 & ?\\ ? & 4 & 0 & ? & ?\\ 0 & 0 & 5 & 4 & ?\\ 0 & 0 & 5 & 0 & ? \end{bmatrix} $
计算前四列的均值$\mu$,然后让$Y$减去$\mu$,带进算法中求解后,再把均值加回来,即$(\theta^{(j)})^T(x^{(i)}) + \mu_i$。
对于用户5来说,由于从来没有评过分,所以$\theta^{(5)} = [0,0]^T$,如此其实预测值就是$\mu$。
好吧,说了半天,其实就是如果一个用户从来没有评过分,就取之前所有用户对电影评分的均值。
------Week 10------2018.12.09------
Large Scale Machine Learning
1. Gradient Descent with Large Datasets
记得我们之前提到过,It's not who has the best algorithms that wins, it's who has the most data. 近年来,机器学习再度掀起热潮的其中一个原因在于我们已经拥有了处理海量数据的能力,使得机器学习算法的性能不断提升。但并不是增加训练样本一定会提升系统性能,例如之前我们提到,对于已经高偏差的学习算法,增加数据量并不一定是合适的方向,应该尝试增加额外的特征。另外,对于大数据的处理仍然对系统压力很大,在保持性能的情况我们还是希望从算法上减少计算量。
以线性回归的梯度下降法为例,在每次的迭代过程中,我们令$ θ_j := θ_j - α\frac{1}{m}\sum_{i=1}^m (h_θ (x^{(i)}) - y^{(i)})\cdot x_j^{(i)} $,这样在每次迭代中我们都需要把所有样本代入计算,这称为Batch gradient descent。为了减少计算量,我们再每次迭代中可以随机选择一个样本,计算这个样本对应的梯度,即Stochastic gradient descent:
1. 随机打乱样本集(这一步很重要);
2. 重复执行以下步骤直至收敛:对于1到m,令$ θ_j := θ_j - α (h_θ (x^{(i)}) - y^{(i)})\cdot x_j^{(i)} $
当训练集的个数m很大时,随机梯度下降算法计算快很多。但是并不是每次迭代中代价函数都会减少,有时甚至会增大,但总体是曲曲折折地下降至最低点附近。
此外,也许你会觉得每次迭代使用一个样本也太少,因此可以折中,使用Mini-batch gradient descent,在每次迭代中选b个样本进行计算。
那么在运行梯度下降算法时,如何才能确定算法正常收敛?批量梯度下降中我们画出代价函数随着迭代次数增加的曲线图,确保它每次迭代都在下降。那么在随机梯度下降算法中,我们可以每隔1000次迭代计算一次最近1000个样本的平均成本,曲线有可能是曲曲折折下降的,这个时候可以每5000个样本计算一次,会得到更平滑的下降曲线。如果你发现曲线平缓,也不下降,那有可能需要改变$\alpha$或者对算法进行改进。如果你看到曲线反而是上升的,那说明算法是发散的,你可以尝试使用较小的$\alpha$,通常$\alpha$是保持不变的,但有时为了收敛我们可以逐渐的减小它,例如可以令$\alpha = const1/(iterationNumber + const2)$。
2. Advanced Topics
来看两个大数据学习相关的主题。
第一个是在线学习(Online Learning),在之前的例子中,我们都是在本地保存了大量的训练样本,用来训练算法。那么如果你经营一个网站,有连续的数据流,需要实时的学习并更新参数,那么在线学习就是合适的方法。例如,对于快递网站,用户选择出发地和目的地后,你给出包裹报价,用户会选择下单(y=1)或者不下单(y=0),那么可以构造特征(用户属性,出发地,目的地等),我们希望学习$p(y = 1|x;\theta)$来优化报价。每一次有新用户,你都能得到一对(x, y),然后你就可以用这个样本去更新$\theta$。此外,在网上商城产品推荐,新闻文章定制化推荐等地方都可以利用在线学习。
在线学习的另一个好处在于它能够适应不断变化的用户偏好。例如,随着时间推移,经济形势发生转变,用户价格敏感度降低,愿意支付更高价格来买某个产品,采用在线学习就能不断更新自己的参数,与时俱进。如果你的用户类型也发生了变化,或者有了新类型的用户,这种算法也能不断适应。
另一个是Map-reduce,我们之所以改进批量梯度下降算法,就是因为我们觉得每次迭代中计算所有的样本太慢,那如果我们有4台机器,我们可以把求和的那部分式子分成4份,分别在4台机器中进行计算相加得到一个临时值,最后合到一台机器上更新参数。如果不考虑网络传输速率和延迟问题,那么可以把速度提高4倍。或者,如果有一台具有多内核的计算器,也可以采用这种方法,而且这种情况下不容易出现网络延迟问题。目前已经有一些不错的MapReduce开源工具,如Hadoop。
通常情况下,许多学习算法都包含训练样本某种形式的和,这种情况下就可以考虑采用MapReduce方法。
------Week 11------2018.12.09------
Application Example: Photo OCR
课程的最后,来看一个机器学习应用的实例:Photo OCR,从中我们可以看到一个复杂的机器学习系统是如何组合实现的,也会学习到机器学习流水线(machine learning pipeline)的有关概念,以及如何分配你的资源,最后可以了解到如何将机器学习应用于计算机视觉问题,以及人工数据合成(artificial data synthesis)的概念。
OCR其实就是字符识别,简单的例子就是自动抓拍超速车牌。如果给计算机一幅图像,需要计算机识别出图像中的文字,需要哪些步骤?1. 文字检测(Text detection),计算机先要识别图像中哪些区域是包含文字的,把这些区域提取出来,便于处理;2. 字符分隔(Character segmentation),对于一个单词直接识别似乎比较难,我们可以先按字符把图像区域分隔,得到只包含一个字符的小区域;3. 字符分类(Character classification),最后就是对提取出来的字符图像做字符分类。
以上就是图像OCR流水线(Pipeline),在每个步骤中都需要一定的人力和算法去处理。
首先来看文字检测,我们先用更简单的行人检测作例子。如果在一幅图像中有多个行人,怎么识别出他们的区域?这个会比文字检测简单些,因为大部分行人都比较相似,因此可以用一个固定长宽比的矩形来做检测,例如取图像左上角82x36的图像块,通过机器学习训练到的分类器来确定是不是有行人,如果没有的话,分类器应该输出为y=0。然后我们把窗口向右移动一点,再次做检测,依此向右移动,直到达到右边界后回到最左边,向下移动一点,然后重复之前的过程,完成对整幅图像的检测。这就是滑动窗(slide windows)。回到文字检测,也是类似的过程,使用滑动窗进行检测,没有文字的区域就变黑,检测到文字的区域变白,方便下一步提取。
对包含文字的区域进行文字分隔,也是同样的处理过程,如果滑动窗中只包含一个字符,则归类为y=0,如果不是单个字符,就归类为y=0。
最后就是字符分类,运用之前介绍过的机器学习算法实现即可。
这套系统有良好性能需要一个前提,就是有训练优异的分类器。怎么获得一个高效的机器学习系统呢?一种方法是先选择一个低偏差的学习算法(通过增加特征,或在神经网络中增加隐藏层),然后用大量的训练集来训练它,那么从哪获得大量的训练集呢?
既然没办法获得那么多真实数据,我们可以进行人工数据合成,例如在字符分类学习中,为了获得更多的训练样本,可以采集同一字符的不同字体,然后加上随机背景,这样就可以获得成千上万的训练样本。另一种方法是对字符图像进行扭曲,实现各种各样的效果。此外还有一种人为标记的做法,其实很多人现在就从事这样的工作,每天的工作内容就是给AI公司标记样本,当样本数量足够多后,AI公司的产品算法才能有良好的性能。不过在你做这些事情之前,你得先问问自己,如果要获得10倍的数据量,需要花费多少时间?划不划算?
最后来看一下在系统搭建的过程中,你必须知道哪部分是你值得投入资源去提高的,资源是有限的,同时并不是每件事情努力了都有回报的!这就是上限分析(Ceiling analysis)。以上面的OCR流水线为例,如果整套系统的准确度为72%,手动令文字检测的结果为100%正确,此时评估系统准确度为89%,因此我们说改善文字检测模块,系统得到17%的准确度提升,非常值得投入资源去做;如果手动令文字分隔的结果为100%,得到系统准确度为90%,因此系统准确度只有1%的提升,因此没有必要花费额外的人力物力在改善这个模块上。
注:部分图片来源于课程讲义和网络。