写在前面
那么如何把相近的样本点聚合在一起,同样不相近的样本尽可能不在同一个簇中?一个思路就是假设每个样本有标签,只是“隐藏”起来了,把它当作隐变量(latent variable)。然后用监督学习的思路去求解,把相同标签的样本聚合在一起即可。
如此一来,会发现整个过程出现两类变量:
- 样本类别变量
- 模型参数变量
传统的参数学习算法无法解决该类问题,How to do it? 下面要介绍的期望最大值算法可以很好的解决该类问题。
期望最大值算法
期望最大值(Expectation Maximization,简称EM算法)是在概率模型中寻找参数最大似然估计或者最大后验估计的算法,其中概率模型依赖于无法观测的隐藏变量。
其主要思想就是通过迭代来建立完整数据的对数似然函数的期望界限,然后最大化不完整数据的对数似然函数。
本节将尽可能详尽地描述EM算法的原理。并结合下一节的高斯混合模型介绍EM算法是如何求解的。
数学铺垫
Jensen不等式
Jensen不等式表述如下:
如果f是凸函数,X是随机变量,那么有 E[f(X)]≥f(E[X]).
特别的,如果f是凸函数,那么 E[f(X)]=f[E(X)]当且仅当p(x=E[X])=1,此时随机变量X就是常量。
在图中,实现f是凸函数,X是随机变量,假设其取值为x和y(概率分别为0.5)。那么X的期望值就是[x,y]的中值,从图中可以看到E[f(x)]≥f(E[x])成立。
Jensen不等式同样可应用于凹函数,不等号方向相反即可,即E[f(X)]≤f(E[X])。
EM算法描述
EM初探
解释公式(ml.1.10.1),首先对极大似然函数取对数,然后对每个样本的每一种可能类别z求联合分布概率之和。
直接求参数w会比较困难,因为有隐变量z的存在,如果确定了z之后,再求解就容易了(不同于监督学习过程,这里存在两个变量:模型参数变量w和模型类别变量z)。
EM算法是一种求解存在隐变量的参数优化问题的有效方法。既然不能直接最大化ℓ(w),我们可以不断的建立ℓ的下界(E步),然后优化下界(M步)。
公式推导
公式(ml.1.10.2)解释:
(1)到(2)比较直接,分子分母同乘以一个相等的函数;(2)到(3)利用了Jensen不等式。这里面函数log(x)是凹函数(二阶导数小于0),并且
E步
M步
伪代码中提到,直到收敛循环才退出。那么如何保证收敛?这是下一节要介绍的内容。
EM算法收敛性证明
收敛性证明
EM算法思想总结:
高斯混合模型
密度估计(Density Estimation)是无监督学习非常重要的一个应用方向。本节主要介绍高斯混合模型(Gaussian Mixture Model,简称GMM)如何求解,进而做密度估计的?
GMM介绍
高斯混合模型可以描述为:
高斯混合模型与高斯判别分析
公式(ml.1.10.6)与第5章中的(ml.1.5.6)表达的是同一个意思。包括(ml.1.10.8)与(ml.1.5.7)的求解结果,在物理意义也是等价的。
GMM与GDA相同点:
- 模型的概率假设相同:类别z(i)服从多项式分布,样本特征服从多变量高斯分布;
- 目标函数一致:都是联合概率分布(在训练集上)的极大似然估计
GMM与GDA不同点:
- 学习方式不同:GDA是有监督学习,而GMM用于无监督学习;
- 求解算法不同:GDA直接通过MLE求参数偏导即可得到闭式解;GMM因为有隐变量,需要用EM算法不断迭代,得到结果。
GMM参数学习过程
因此用EM算法求解高斯混合模型的步骤如下:
跟下面要介绍的经典聚类算法K-menas相比,这里使用类别“软”指定,为每个样例分配的类别z(i)是有概率分布的,同时计算量也变大了,每个样例i都要计算属于每一个类别j的概率。与K-means相同的是,结果仍然是局部最优解。对其它参数取不同的初始值进行多次计算不失为一种好方法。
K-means聚类
K-menas是聚类算法中最经典的一个。这里首先介绍K-means算法的流程,然后阐述其背后包含的EM思想。
关于聚类
聚类属于无监督学习,之前章节中的Regression,Naive Bayes,SVM等都是有类别标签的,也就是样本中已经给出了真实分类标签。而聚类样本中没有给定标签,只有特征(向量)。
K-means算法流程
K-means算法是将样本聚类成k个簇,算法描述如下:
#include<iostream>
#include<cmath>
#include<vector>
#include<ctime>
using namespace std;
typedef unsigned int uint;
struct Cluster
{
vector<double> centroid;
vector<int> samples;
}
vector<Cluster> k_means(vector<vector<double> > trainX, int k, int maxepoches)
{
const int row_num = trainX.size();
const int col_num = trainX[0].size();
/*初始化聚类中心*/
vector<Cluster> clusters(k);
int seed = (int)time(NULL);
for (int i = 0; i < k; i++)
{
srand(seed);
int c = rand() % row_num;
clusters[i].centroid = trainX[c];
seed = rand();
}
......
}
然后,迭代中的每一步计算每个星星到k个质心中的每一个的距离,选取距离最近的那个星团作为\(c^{(i)}\)。
这样经过第一步每个星星都有了所属的星团;第二步对于每个星团,重新计算它的质心\(\mu_j\)(对里面所有的星星坐标求平均)。重复迭代第一步和第二步直至质心不变或变动很小。示例代码如下
vector k_means(vector > trainX, int k, int maxepoches)
{
const size_t row_num = trainX.size();
const size_t col_num = trainX[0].size();
/*初始化聚类中心*/
(在此省略)
/*多次迭代直至收敛,这里固定迭代次数(100次)*/
for (int it = 0; it < maxepoches; it++)
{
/*每一次重新计算样本点所属类别之前,清空原来样本点信息*/
for (int i = 0; i < k; i++)
{
clusters[i].samples.clear();
}
/*求出每个样本点距应该属于哪一个聚类*/
for (int j = 0; j < row_num; j++)
{
/*都初始化属于第0个聚类*/
int c = 0;
double min_distance = cal_distance(trainX[j], clusters[c].centroid);
for (int i = 1; i < k; i++)
{
double distance = cal_distance(trainX[j], clusters[i].centroid);
if (distance < min_distance)
{
min_distance = distance;
c = i;
}
}
clusters[c].samples.push_back(j);
}
/*更新聚类中心*/
for (int i = 0; i < k; i++)
{
vector<double> val(col_num, 0.0);
for (int j = 0; j < clusters[i].samples.size(); j++)
{
int sample = clusters[i].samples[j];
for (int d = 0; d < col_num; d++)
{
val[d] += trainX[sample][d];
if (j == clusters[i].samples.size() - 1)
{
clusters[i].centroid[d] = val[d] / clusters[i].samples.size();
}
}
}
}
} // 多次迭代,直至收敛
return clusters;
}
double cal_distance(vector a, vector b)
{
size_t da = a.size();
size_t db = b.size();
if (da != db)
{
cerr << "Dimensions of two vectors must be same!\n";
}
double val = 0.0;
for (size_t i = 0; i < da; i++)
{
val += pow((a[i] - b[i]), 2);
}
return pow(val, 0.5);
}
K-means收敛性
k-means面对的第一个问题是如何保证收敛,算法描述中抢到结束条件就是收敛,可以证明的是k-means完全可以保证收敛。下面是定性的描述,先定义畸变函数(Distortion Function)如下:
K-means与EM算法
如果我们找到的y能够使P(x,y)最大,那么可以说y是样本x的最佳类别了,x归类为y就顺理成章了。但是我们第一次指定的y不一定会让P(x,y)最大。而且P(x,y)还依赖于其它未知参数,当然在给定y的情况下,我们可以调整其它参数让P(x,y)最大。但是调整参数后,我们发现有更好的y可以指定。那么我们重新指定y,然后再计算P(x,y)最大时的参数,反复迭代知道没有更好的y可以指定。
联合概率分布P(x,y)最大所对应的y就是x的最佳类别。
更多案例请关注“思享会Club”公众号或者关注思享会博客:http://gkhelp.cn/