机器学习从0到1——10 无监督学习算法

无监督学习大多数尝试从没有人为标注的样本中抽取信息,学习从分布中采样、学习从分布中去噪、寻找数据分布的流形或是将数据中相关的样本聚类。

一个经典的无监督学习任务是找到数据的最佳表示,最佳可以是不同的表示,但一般来说,是指该表示在比原表示更简单或更易访问的情况下,尽可能地保存关于特征向量x更多的信息。

接下来我们将介绍两种无监督学习算法:主成分分析(Principal Component Analysis,PCA)和k-means聚类。

10.1主成分分析

在有些应用中向量的维数非常高。以图像数据为例,对于高度和宽度都为100像素的图像,如果将所有像素值拼接起来形成一个向量,这个向量的维数是10000。一般情况下,向量的各个分量之间可能存在相关性,直接将向量送入机器学习算法中处理效率会很低,也影响算法的精度。为了可视化显示样本数据,有时候需要把向量变换到低维空间中。如何降低向量的维数并且去掉各个分量的相关性?PCA就是达到这种目的的一种方法。

10.1.1数据降维问题

主成分分析是一种数据降维和去除相关性的方法,它通过线性变换将向量投影到低维空间。对向量投影就是对向量左乘一个矩阵,得到结果向量:

y=Wx

在这里,结果向量的维数小于原始向量的维数。降维要确保的是在低维空间中的投影能很好地近似表达原始向量,即重构误差最小化。

10.1.2计算投影矩阵

主成分分析的核心问题是如何得到投影矩阵,与其他机器学习算法一样,它通过优化目标函数得到。下面我们首先考虑最简单的情况,将向量投影到一维空间,然后推广到一般情况。假设有n个d维向量x_{i},如果要用一个向量x_{0}来近似代替它们,这个向量取什么值的时候近似误差最小?如果用均方误差作为标准,就是要最小化如下函数:

L(x_{0})=\sum\limits_{i=1}^{n}\parallel x_{0}-x_{i}\parallel ^{2}

为了求上面这个目标函数的极小值,对它求梯度并令梯度等于0,可以得到:

\nabla L(x_{0})=\sum\limits_{i=1}^{n}2(x_{0}-x_{i})=0

解这个方程可以得到问题的最优解是这些向量的均值:

m=\sum\limits_{i=1}^{n}x_{i}

但是只用均值代表整个样本集过于简单,误差太大。作为改进,可以将每个向量表示成均值向量和另一个向量的和:

x_{i}=m+a_{i}e

其中,e为单位向量,a_{i}是标量。上面这种表示相当于把向量投影到一维空间,坐标就是a_{i}。当e和a_{i}取什么值得时候,这种近似表达的误差最小?这相当于最小化如下误差函数:

L(a,e)=\sum\limits_{i=1}^{n}\parallel m+a_{i}e-x_{i}\parallel ^{2}

为了求这个函数的极小值,对a_{i}求偏导数并令其为0可以得到:

2e^{T}(m+a_{i}ex_{i}-x_{i})=0

变形后得到:

a_{i}e^{T}e=e^{T}(x_{i}-m)

由于e是单位向量,因此e^{T}e=1,最后得到:

a_{i}=e^{T}(x_{i}-m)

也就是样本和均值的差对向量e做投影。现在的问题是e的值如何确定。定义如下散布矩阵:

S=\sum\limits_{i=1}^{n}(x_{i}-m)(x_{i}-m)^{T}

它是协方差矩阵的n倍,协方差矩阵的计算公式为:

\Sigma=\frac{1}{n}\sum\limits_{i=1}^{n}(x_{i}-m)(x_{i}-m)^{T}

将上面求得的a_{i}带入目标函数中,得到只有变量e的函数:

上式的后半部分与e无关,由于e是单位向量,因此有\parallel e \parallel=1的约束,这个约束条件可以写成e^{T}e=1。我们要求解的是一个带等式约束的极值问题,可以使用我们在支持向量机中讲解的拉格朗日乘数法。构造拉格朗日函数:

L(e,\lambda) =-e^{T}Se+\lambda(e^{T}e-1)

对e求梯度并令其为0可以得到:

-2Se+2\lambda e=0

即:

Se=\lambda e

\lambda就是散布矩阵的特征值,e为它对应的特征向量,上面的最优化问题可以归结为矩阵的特征值和特征向量问题。矩阵S是实对称半正定矩阵,因此,一定可以对角化,并且所有特征值非负。为了使损失函数最小,这里需要最大化e^{T}Se的值,由于:

e^{T}Se=\lambda e^{T}e=\lambda

因此,\lambda为散布矩阵最大的特征值时,e^{T}Se有极大值,目标函数取得极小值。将上述结论推广到d^{'}维,每个向量可以表示成:

x=m+\sum\limits_{j=1}^{d^{'}}a_{j}e_{j}

在这里e_{j}是单位向量,并且相互正交。误差函数变成了:

L=\sum\limits_{i=1}^{n}\parallel m+\sum\limits_{j=1}^{d^{'}}a_{ij}e_{j}-x_{i}\parallel ^{2}

根据前面的推导,我们可以知道使得该函数取最小值的e_{j}为散布矩阵最大的d^{'}个特征值对应的单位长度特征向量,即求解下面的优化问题:

\min\limits_{W}(-tr(W^{T}SW))

W^{T}W=I

其中,tr为矩阵的迹,I为单位矩阵,矩阵W的列e_{j}是要求解的基向量。散布矩阵不同特征值对应的特征向量相互正交,这些特征向量构成一组基向量,可以用它们的组合来表示向量x。这种表示相当于去除了各分量之间的相关性。

从上面的推导过程可以得到计算投影矩阵的流程如下:

(1)计算样本集的均值向量,将所有的向量减去均值向量,这个过程可以称为白化。

(2)计算样本集的散布矩阵。

(3)对散布矩阵进行特征值分解,得到所有特征值与特征向量。

(4)将特征值从大到小排序,保留最大的一部分特征值对应的特征向量,以它们为行,形成投影矩阵。

具体保留多少个特征值由投影后的向量维数决定。

10.1.3向量降维

得到投影矩阵之后可以进行向量降维,将其投影到低维空间。向量投影的流程为:

(1)将样本减掉均值向量。

(2)左乘投影矩阵,得到降维后的结果。

10.1.4向量重构

向量重构指根据投影后的向量重构原始向量,与向量投影的作用和过程相反。向量重构的流程如下:

(1)降维后的向量左乘投影矩阵的转置矩阵。

(2)加上均值向量,得到重构后的结果。

从上面的过程可以看到,在计算过程中没有使用样本标签值,因此,主成分分析是一种无监督学习算法。

10.2 k-means聚类

聚类属于无监督学习问题,其目标是将样本集划分成多个类,保证同一类的样本之间尽量相似,不同样本之间尽量不同,这些类称为簇(Cluster)。

10.2.1 问题定义

聚类也是分类问题,它的目标也是确定每个样本所属的类别。与有监督的分类算法不同,这里的类别不是人工预定好的,而是由聚类算法确定。假设有一个样本集:

C=\{x_{1},x_{2},...,x_{l}\}

聚类算法把这个样本集划分成m个不相交的子集C_{1},C_{2},...,C_{m}。这些子集的并集是整个样本集:

C_{1}\cup C_{2}\cup ...\cup C_{m}=C

每个样本只能属于这些子集中的一个,即任意两个子集之间没有交集:

C_{i}\cap C_{j}=\phi ,\forall i,j,i\neq j

其中,m的值可以由人工设定,也可以由算法确定。下面用一个实际的例子来说明聚类任务。假设有一堆水果,我们事先并不知道有几类水果,聚类算法要完成对这堆水果的归类,而且在没有人工的指导下完成。

聚类本质上是集合划分问题。因为没有人工定义的类别标准,因此,要解决的核心问题是如何定义簇。通常的做法是根据簇内样本间的距离或样本点在数据空间中的密度确定。典型的代表是k-means算法,它用中心向量表示一个簇,样本所属的簇由它到每个簇的中心向量的距离确定。

10.2.2 算法原理

k-means算法是一种被广泛用于实际问题的聚类算法。它将样本划分成k个类,参数k由人工设定。算法将每个样本划分到离他最近的那个类中心所代表的类,而中心的确定依赖于样本的划分方案。假设有l个样本,特征向量x_{i}为n维向量,给定参数k的值,算法将这些样本划分成k个集合:

S=\{S_{1},S_{2},...,S_{k}\}

最佳分配方案是如下最优化问题的解:

\min\limits_{S}\sum\limits_{i=1}^{k}\sum\limits_{x\in S_{i}}\parallel x-\mu_{i}\parallel ^{2}

其中,\mu_{i}为类中心向量。这个问题是组合优化问题,是NP难问题,不易求得全局最优解,只能近似求解。实现时采用迭代法,只能保证收敛到局部最优解处。

算法的流程如下:

初始化k个类的中心向量\mu_{1},\mu_{2},...,\mu_{k}

循环,直到收敛

        分配阶段。根据当前的类中心值确定每个样本所属的类:

        循环,对每个样本x_{i}

                 计算样本离每个类中心向量\mu_{j}的距离:

d_{ij}=\parallel x_{i}-\mu_{j}\parallel

                 将样本分类到距离最近的那个类

        循环结束

        更新阶段。更新每个类的类中心:

        循环,对每个类

                 根据上一步的分配方案更新每个类的类中心为该类所有样本的均值:

\mu_{i}=\sum\limits_{j=1,y_{j}=i}^{l}x_{j}/N_{i}

        循环结束

循环结束

其中,y_{j}为第j个样本的类别,N_{i}为第i类的样本数。

与kNN算法相同,这里也依赖于样本之间的距离,因此需要定义距离的计算方式,最常用的是欧式距离,也可以采用其他距离定义,距离的计算方式已经在讲kNN算法时讲过。算法在实现时要考虑下面几个问题:

(1)类中心向量的初值。一般采用随机初始化。第一种方案是从样本集中随机选择k个样本作为每个类的初始类中心。第二种方案是将所有样本随机地分配给k个类中的一个,然后按照这种分配方案计算各个类的中心向量。

(2)参数k的设定。可以根据先验知识人工指定一个值,或者由算法自己确定[1,2]。

(3)迭代终止的判定规则。计算本次迭代后的类中心和上一次迭代时的类中心之间的距离,如果小于指定阈值,则终止算法。

k-means算法有多种改进版本,包括模糊c均值聚类、用三角不等式加速,感兴趣的同学可以自行学习。

10.2.3 算法评价指标

与有监督学习算法相同,需要对聚类算法的效果进行评估。由于聚类算法要处理的样本没有人工标记的标签值,因此需要定义其特有的评价指标。这些指标可以分为内部指标和外部指标两种类型。

内部指标指用算法对聚类样本的处理结果来评价聚类的效果,不依赖于事先由人工给出的标准聚类结果,因此,它完全由聚类算法的内部结果而定。下面介绍几种常用的内部指标。

Davies-Bouldin指标(DBI)定义为:

\frac{1}{k}\sum\limits_{i=1}^{k}\max\limits_{i\neq j}(\frac{\sigma_{i}+\sigma_{j}}{d(c_{i},c_{j})})

其中,k为簇的数量,c_{i}是第i个簇的中心向量,\sigma_{i}是第i个簇的所有样本离这个簇的中心向量的平均距离,d(c_{i},c_{j})是第i个簇的中心向量与第j个簇的中心向量之间的距离,上式的求和项是簇内差异与簇间差异的比值。DBI指标值越大,聚类效果越差,反之越好

Dunn指标是簇间距离的最小值与簇内距离的最大值之间的比值,计算公式为:

\frac{\min\limits_{1 \leq i<j\leq k}d(i,j)}{\max\limits_{1\leq m \leq k}d^{'}(m)}

其中,d(i,j)为第i个簇与第j个簇的簇间距离,d^{'}(m)为第m个簇的簇内距离,是簇内所有样本距离簇中心的平均距离。这个比值越大,说明簇之间被分得越开,簇内越紧密,聚类效果越好,反之则越差。

外部指标是用事先定义好的聚类结果来评价算法的处理效果,它的计算依赖于人工标注的结果。下面介绍几种典型的外部指标。

纯度定义了一个簇包含某一个类的程度,即这个簇内的样本是否都属于同一个类,类似于决策树中的纯度指标,定义为:

\frac{1}{N}\sum\limits_{m\in M}\max\limits_{d\in D}|m\cap d|

其中,M是人工划分的簇,D是聚类算法划分的簇,N为样本数。这个指标反应了算法聚类的结果与人工聚类结果的重叠程度,值越大,说明聚类效果越好。

Rand指数定义了算法划分的结果与人工划分结果之间的耦合度,定义为:

\frac{\text{TP}+\text{TN}}{\text{TP}+\text{FP}+\text{FN}+\text{TN}}

上式中的4个值定义与我们在朴素贝叶斯分类器中的定义相同,Rand指数的公式与准确率的公式相同。这个指标值越大,聚类结果与人工分类结果越相似。

Jaccard指标是两个集合的交集与并集的比值,定义为:

\frac{|A\cap B|}{|A\cup B|}=\frac{TP}{TP+FP+FN}

这个值越大,说明两个集合的重合度越高,即算法聚类的结果与人工聚类的结果越接近,聚类效果越好。

10.3实验程序

10.3.1主成分分析法

我们使用iris数据集来验证算法,iris数据集的特征向量是4维的,下面把它降维成2维的,并显示降维后的结果。

# 主成分分析法(Principal Component Analysis)
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.decomposition import PCA

# 载入iris数据集
iris = datasets.load_iris()
# 特征向量为4维的
X = iris.data
# 标签值用于将样本显示成不同的颜色
y = iris.target
target_names = iris.target_names

# 创建PCA对象,并计算投影矩阵,对X执行降维操作,得到降维后的结果X_r
pca = PCA(n_components=2)
X_r = pca.fit(X).transform(X)

plt.figure()
colors = ['navy', 'turquoise', 'darkorange']
lw = 2
# 显示降维后的样本
for color, i, target_name in zip(colors, [0, 1, 2], target_names):
    plt.scatter(X_r[y == i, 0], X_r[y == i, 1], color=color, alpha=.8, lw=lw,
                label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('PCA of IRIS dataset')

plt.show()

10.3.2 k-means算法

import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
from sklearn.metrics import davies_bouldin_score, jaccard_score

# 生成随机数据
# n_samples是样本总数,centers指定聚类的中心数(即k的值),n_features是每个样本的特征数
X, y_true = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)

# 使用KMeans算法
# n_clusters指定聚类的数目,即要分成的簇的个数
kmeans = KMeans(n_clusters=4, n_init=10)
kmeans.fit(X)
y_kmeans = kmeans.predict(X)

# 可视化
plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis')

# 画出聚类中心
centers = kmeans.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.75)
plt.title("K-Means Clustering")
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.show()

# 评估指标
davies_bouldin = davies_bouldin_score(X, y_kmeans)
jaccard = jaccard_score(y_true, y_kmeans, average='weighted')
print("Davies-Bouldin Score: %0.3f" % davies_bouldin)
print("jaccard Index: %0.3f" % jaccard)

代码下载地址:

链接:https://pan.baidu.com/s/1saYsZ5T8V13xZ1Mufi78yA

提取码:eekq

参考文献

[1]Pelleg, Dan, and Andrew Moore. "X-means: Extending K-means with E cient Estimation of the Number of Clusters." ICML’00. 2000.

[2] Hamerly, Greg, and Charles Elkan. "Learning the k in k-means." Advances in neural information processing systems 16 (2003).

雷明. 机器学习——原理、算法与应用.清华大学出版社.

  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值