1、先直观解释什么是平面(线性子空间)和流形(非线性子空间):
答:如果线性子空间是一张平展的纸,那么非线性流形的一个简单例子就是卷起来的纸,可以把流形看作一个可以以多种方式伸展和卷动的曲面,平面(线性子空间)可以推广为流形(非线性子空间)。
2、为什么能够使用降维手段实现降维?(后面有图)
答:即使一个大的流形看上去非常复杂,但它的每个数据点的邻近区域通常可以非常好地近似为一块平面。换句话说,可以通过多个小平面使用局部结构组成全局结构。
3、为什么聚类算法可以实现降维?
答:彼此相近(可以用一种特定的度量方式(比如欧式距离)来定义“近”的概念)的点属于同一个簇。给定一个聚类,数据点可以用它的簇成员向量来表示。如果簇的数量小于初始的特征数量,那么相对于初始表示,这种新表示就具有更少的维度,初始数据就被压缩进一个更低维度的空间。
K-means属于无监督学习方法,不需要标签,仅基于数据本身的结构推测出簇标签。
为了说明算法实现过程,先解释算法的伪代码,再手推一个实例,最后用代码实现举例。
K-means好像成篇的数学推导,这个算法简单来说就是基于距离度量,把每个样本点聚类到与它距离最近的类中。
E = ∑ i = 1 k ∑ x ∈ C i ∥ x − μ i ∥ 2 2 (1) E=\sum_{i=1}^{k}\sum_{x\in C_{i}}\left\|x-\mu_{i}\right\|_{2}^{2}\tag{1} E=i=1∑kx∈Ci∑∥x−μi∥22(1)
解释下上面的平方误差公式: 假 定 样 本 集 D = { x 1 , x 2 , . . . , x m } , “ 希 望 ” 使 用 K − m e a n s 算 法 聚 类 出 K 个 簇 ( 类 ) , 分 别 为 C = { C 1 , C 2 , . . , C K } , ( 1 ) 式 中 的 μ 是 这 K 个 簇 的 均 值 向 量 μ i = 1 ∣ C i ∣ ∑ x ∈ C i x , 聚 类 算 法 希 望 E 越 小 越 好 。 假定样本集D=\{x_{1},x_{2},...,x_{m}\},“希望”使用K-means算法聚类出K个簇(类),分别为C=\{C_{1},C_{2},..,C_{K}\},(1)式中的\mu是这K个簇的均值向量\mu_{i}=\frac{1}{|C_{i}|}\sum_{x\in C_{i}}x,聚类算法希望E越小越好。 假定样本集D={x1,x2,...,xm},“希望”使用K−means算法聚类出K个簇(类),分别为C={C1,C2,..,CK},(1)式中的μ是这K个簇的均值向量μi=∣Ci∣1∑x∈Cix,聚类算法希望E越小越好。
那么怎样划分每一个样本?
答:这块使用欧氏距离。 假 设 当 前 已 有 K 个 簇 , 每 个 簇 的 均 值 向 量 为 { μ 1 , μ 2 , . . . , μ k } , 使 用 欧 氏 距 离 计 算 当 前 样 本 x j 与 每 一 个 簇 的 μ i 的 距 离 d j i = ∥ x j − μ i ∥ 2 , 找 到 最 小 距 离 对 应 的 簇 μ i , 便 将 该 样 本 点 划 入 到 簇 μ i 中 , 然 后 重 新 计 算 μ i 的 均 值 向 量 , 这 样 不 断 对 每 个 样 本 点 进 行 计 算 , 知 道 所 有 样 本 点 都 划 分 完 毕 , 算 法 终 止 。 假设当前已有K个簇,每个簇的均值向量为\{\mu_{1},\mu_{2},...,\mu_{k}\},使用欧氏距离计算当前样本x_{j}与每一个簇的\mu_{i}的距离d_{ji}=\left\| x_{j}-\mu_{i}\right\|_{2},找到最小距离对应的簇\mu_{i},便将该样本点划入到簇\mu_{i}中,然后重新计算\mu_{i}的均值向量,这样不断对每个样本点进行计算,知道所有样本点都划分完毕,算法终止。 假设当前已有K个簇,每个簇的均值向量为{μ1,μ2,...,μk},使用欧氏距离计算当前样本xj与每一个簇的μi的距离dji=∥xj−μi∥2,找到最小距离对应的簇μi,便将该样本点划入到簇μi中,然后重新计算μi的均值向量,这样不断对每个样本点进行计算,知道所有样本点都划分完毕,算法终止。
用西瓜书上的例子吧
下面是原数据集
该数据集一共有30个样本,将其分别编号为 { x 1 , x 2 , x 3 , . . . , x 30 } \{x_{1},x_{2},x_{3},...,x_{30}\} {x1,x2,x3,...,x30},每个样本有两个属性。
1、算法初始化:
取聚类簇个数K = 3,随机选取三个样本( x 6 , x 12 , x 27 x_{6},x_{12},x_{27} x6,x12,x27)作为初始均值向量 μ \mu μ,即:
μ 1 = ( 0.403 ; 0.237 ) , μ 2 = ( 0.343 ; 0.099 ) , μ 3 = ( 0.532 ; 0.472 ) \mu_{1}=(0.403;0.237),\mu_{2}=(0.343;0.099),\mu_{3}=(0.532;0.472) μ1=(0.403;0.237),μ2=(0.343;0.099),μ3=(0.532;0.472)
此时对应的三个簇为: C 1 = { x 6 } , C 2 = { x 12 } , C 3 = { x 27 } C_{1}=\{x_{6}\},C_{2}=\{x_{12}\},C_{3}=\{x_{27}\} C1={x6},C2={x12},C3={x27}
2、循环遍历:
分别取数据集中剩下的样本,假设此时取样本 x 1 = ( 0.697 ; 0.460 ) x_{1}=(0.697;0.460) x1=(0.697;0.460),使用欧式距离公式分别计算它与当前均值向量 μ 1 , μ 2 , μ 3 \mu_{1},\mu_{2},\mu_{3} μ1,μ2,μ3的距离,如下:
d 11 = ∥ x 1 − μ 1 ∥ 2 = ( 0.697 − 0.403 ) 2 + ( 0.460 − 0.237 ) 2 = 0.369 d_{11}=\left\|x_{1}-\mu_{1}\right\|_{2} = \sqrt{(0.697-0.403)^{2}+(0.460-0.237)^{2}}=0.369 d11=∥x1−μ1∥2=(0.697−0.403)2+(0.460−0.237)2=0.369
d 12 = ∥ x 1 − μ 2 ∥ 2 = ( 0.697 − 0.343 ) 2 + ( 0.460 − 0.099 ) 2 = 0.506 d_{12}=\left\|x_{1}-\mu_{2}\right\|_{2} = \sqrt{(0.697-0.343)^{2}+(0.460-0.099)^{2}}=0.506 d12=∥x1−μ2∥2=(0.697−0.343)2+(0.460−0.099)2=0.506
d 13 = ∥ x 1 − μ 3 ∥ 2 = ( 0.697 − 0.532 ) 2 + ( 0.460 − 0.472 ) 2 = 0.166 d_{13}=\left\|x_{1}-\mu_{3}\right\|_{2} = \sqrt{(0.697-0.532)^{2}+(0.460-0.472)^{2}}=0.166 d13=∥x1−μ3∥2=(0.697−0.532)2+(0.460−0.472)2=0.166
可以看出 d 13 < d 11 < d 12 d_{13}
C 1 = { x 6 } C_{1}=\{x_{6}\} C1={x6}
C 2 = { x 12 } C_{2}=\{x_{12}\} C2={x12}
C 3 = { x 1 , x 27 } C_{3}=\{x_{1},x_{27}\} C3={x1,x27}
每计算完一个样本,一定要更新对应簇的均值向量,那些没有改变的簇的均值向量不改变,直接参加下一个样本的计算,即:
μ 1 = ( 0.403 ; 0.237 ) ( 没 变 ) , μ 2 = ( 0.343 ; 0.099 ) ( 没 变 ) \mu_{1}=(0.403;0.237)(没变),\mu_{2}=(0.343;0.099)(没变) μ1=(0.403;0.237)(没变),μ2=(0.343;0.099)(没变),但是因簇 C 3 C_{3} C3加入了新样本点,所以要更新 μ 3 \mu_{3} μ3:
μ 3 = 1 n ∑ i = 1 n C 3 = 1 2 [ x 1 + x 27 ] = 1 2 [ ( 0.697 ; 0.460 ) + ( 0.532 ; 0.472 ) ] = ( 0.6145 ; 0.466 ) \mu_{3} = \frac{1}{n}\sum_{i=1}^{n}C_{3}=\frac{1}{2}[x_{1}+x_{27}]=\frac{1}{2}[(0.697;0.460)+(0.532;0.472)]=(0.6145;0.466) μ3=n1i=1∑nC3=21[x1+x27]=21[(0.697;0.460)+(0.532;0.472)]=(0.6145;0.466)
就这样不断计算每个样本点,直到全部样本被划分完毕。
3、返回结果
按照上面的循环,最后可得下面的三个簇:
C 1 = { x 5 , x 6 , x 7 , x 8 , x 9 , x 10 , x 13 , x 14 , x 15 , x 17 , x 18 , x 19 , x 20 , x 23 } C_{1} =\{x_{5},x_{6},x_{7},x_{8},x_{9},x_{10},x_{13},x_{14},x_{15},x_{17},x_{18},x_{19},x_{20},x_{23}\} C1={x5,x6,x7,x8,x9,x10,x13,x14,x15,x17,x18,x19,x20,x23}
C 2 = { x 11 , x 12 , x 16 } C_{2}=\{x_{11},x_{12},x_{16}\} C2={x11,x12,x16}
C 3 = { x 1 , x 2 , x 2 , x 4 , x 21 , x 22 , x 24 , x 25 , x 26 , x 27 , x 28 , x 29 , x 30 } C_{3} =\{x_{1},x_{2},x_{2},x_{4},x_{21},x_{22},x_{24},x_{25},x_{26},x_{27},x_{28},x_{29},x_{30}\} C3={x1,x2,x2,x4,x21,x22,x24,x25,x26,x27,x28,x29,x30}
计算最后的均值向量:
μ 1 ‘ = ( 0.473 ; 0.214 ) \mu_{1}^{`}=(0.473;0.214) μ1‘=(0.473;0.214)
μ 2 ‘ = ( 0.394 ; 0.066 ) \mu_{2}^{`}=(0.394;0.066) μ2‘=(0.394;0.066)
μ 1 ‘ = ( 0.623 ; 0.388 ) \mu_{1}^{`}=(0.623;0.388) μ1‘=(0.623;0.388)
上面介绍完K-means算法的原理,下面将其应用到降维任务中。
为了理解前言中的问题二,现举个例子:
代码:
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn import manifold, datasets
# 生成带噪声的瑞士卷数据集
X, color = datasets.samples_generator.make_swiss_roll(n_samples=1500)
# 使用100个k-均值簇对数据进行近似
clusters_swiss_roll = KMeans(n_clusters=100, random_state=1).fit_predict(X)
# 使用k-均值簇ID作为颜色来绘制数据集
fig2 = plt.figure()
ax = fig2.add_subplot(111, projection='3d')
ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=clusters_swiss_roll, cmap='Spectral')
plt.show()
运行图:
如果把每个聚类簇的均值向量作为新的数据集,那么就可以实现降维的目的。
代码实现:
def K_means(X,k,rand_seed):
m = X.shape[0]#样本个数
n = X.shape[1]#属性个数
#初始化均值向量
np.random.seed(rand_seed)
rand_index = np.random.choice(m,k,replace=False)###先从所有样本中随机选择出K个样本作为均值向量(先随机取k个索引)
u = X[rand_index,:]
# 初始化簇
C = []
for sample in u:
C.append(sample)
X = np.delete(X,rand_index,axis = 0)#去除掉选中作为初始均值向量的样本
#遍历除随机选到的样本以外的所有样本
for i,x in enumerate(X):
dist = np.sqrt(np.sum(np.square(x - u),axis = 1))#计算距离
dist_order = np.argsort(dist)[0]#取最小距离的索引
C[dist_order] = np.row_stack([C[dist_order],x])#将样本添加到距离最近的簇中
u[dist_order] = np.mean(u[dist_order])#更新均值向量
return C,u
修改随机种子,每次得到的聚类结果都不同:
随机种子等于1:
随机种子等于2:
随机种子等于3:
这就表明了K-means算法的缺点:受初值和离群点的影响,每次结果不稳定。所以才有了K-means++、ISODATA、Bi-kmeasn、mini batch kmeans等。