什么是聚类?
在机器学习领域,主要有两大类学习任务:有监督学习和无监督学习(也有一些分法认为还有半监督学习,即是有监督和无监督的结合)。
有监督学习:训练集有明确答案,监督学习就是寻找问题(又称输入、特征、自变量)与答案(又称输出、目标、因变量)之间关系的学习方式。简单来讲就是训练集是有标签的。监督学习模型有两类,分类和回归。
• 分类模型:目标变量是离散的分类型变量
• 回归模型:目标变量是连续性数值型变量
无监督学习:只有数据,无明确答案,即训练集没有标签。
•聚类(clustering):把有相似属性的样本聚集在一起,每个组也称为簇(cluster)
•主成分分析(PCA):数据降维
•自编码器(Auto-Encoder):用于去噪和稀疏化数据
•生成对抗网络(GAN):生成器和判别器互相博弈对抗,可用于数据生成、风格迁移等
半监督学习:是监督学习和无监督学习相结合的一种学习方法。它主要考虑如何利用少量的样本标注和大量的未标注样本进行训练和分类的问题。半监督学习对于减少标注代价,提高学习机器性能具有非常大的实际意义。
kmeans一般目标函数为:
J
=
∑
j
=
1
k
∑
i
=
1
n
(
x
i
−
c
j
)
2
J=\sum_{j=1}^k\sum_{i=1}^n(x_i-c_j)^2
J=∑j=1k∑i=1n(xi−cj)2
直接求解上述目标函数并不容易,因为里面的求和符号要求的是知道每个数据属于哪个簇才能算出这个簇下的欧式距离之和,所以一般采用贪心策略,通过迭代来近似求解。
实现步骤如下:
a)假定我们要对m个样本点做聚类,要求聚为k类,首先选择k个点作为初始中心点;
b)接下来,按照距离初始中心点最小的原则,针对每一个样本点,计算到k个中心的距离,并把这个样本点分到距离最小的中心点所在的类中;
c)每类中已经有若干个样本点,计算k个类中所有样本点的均值,作为第二次迭代的k个中心点;
d)然后根据这个中心重复第2、3步,直到收敛(中心点不再改变或达到指定的迭代次数),聚类过程结束。
算法特性及优缺点
特性:本算法需要确定k个划分以到达平方误差最小。当聚类是密集的,且类与类之间区别明显时,效果较好。
优点:
(1)原理简单,实现容易
(2)对于处理大数据集,这个算法是相对可伸缩和高效的 超大规模的数据集如何快速实现聚类?
(3)当簇近似为高斯分布时,它的效果较好(即数据不仅是要呈凸形状,最好是为高斯分布)
缺点:
(1)在簇的平均值可被定义的情况下才能使用,可能不适用某些应用
(2)初始聚类中心的选择比较敏感,可能只能收敛到局部最优解
(3)必须事先确定k的个数
(4)算法复杂度高O(nkt)
(5)不能发现非凸形状的簇,或大小差别很大的簇 为什么每个簇的个数最好均匀一点?
(6)对噪声和孤立点数据敏感
python实现算法
不同的初始中心导致不同的结果,可以看出如果完全随机选择初始中心, 则kmeans聚成的簇内的样本个数很可能非常接近,但是很容易发现左图聚类效果不好的部分两个簇的中心之间的距离远远小于它们到上面簇的中心的距离,因此可以采用kmeans++的思路解决这个问题。K-means++按照如下的思想选取K个聚类中心:假设已经选取了n个初始聚类中心(0<n<K),则在选取第n+1个聚类中心时:距离当前n个聚类中心越远的点会有更高的概率被选为第n+1个聚类中心。在选取第一个聚类中心(n=1)时同样通过随机的方法。可以说这也符合我们的直觉:聚类中心当然是互相离得越远越好。这个改进虽然直观简单,但是却非常得有效。
随着迭代次数增加,可以发现最后算法聚类效果稳定下来
一些延伸拓展
kmeans一般的预处理有哪些?
异常点处理:去除异常点:离群值(3倍以上标准差)
缺失值处理:特殊值填充;或者以平均值(没有数据倾斜)/中值(有数据倾斜)替换。
标准化:需要计算样本间的距离;为了避免某一维度的取值范围过大,故需要做标准化到0,1区间
是否可以采用除欧式距离外的距离函数?
目前, 像标准的机器学习库(Sklearn)都只实现了基于欧几里得距离的kmeans算法,而且不允许自行设置距离函数。因为余弦距离计算是的向量的夹角,它并不关心向量的绝对大小,侧重的是相似度的概念,即有可能两个向量在空间距离上相距非常远,但是由于它们的夹角很小,导致余弦距离很小,因此被聚成一块;而欧式距离体现的是数值上的绝对差异。这也导致像余弦距离不适用于kmeans算法。
初始中心如何确定?
1.多次选取中心点进行多次试验,并用损失函数来评估效果,选择最优的一组(类似神经网络里面多次随机选择初始权重进行优化);
2.选取距离尽量远的K个样本点作为中心点:随机选取第一个样本C1作为第一个中心点,遍历所有样本选取离C1最远的样本C2为第二个中心点,以此类推,选出K个初始中心点(计算量大,一般很少这么做,除非数据量很少的情况下);
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
# # x1
data1 = np.random.normal([0, -10], 1, [500, 2])
# # x2
data2 = np.random.normal([-10, 20], 1, [50, 2])
# # x3
data3 = np.random.normal([2, 20], 1, [500, 2])
o_data = np.array(data1, data2, data3)
est = KMeans(n_clusters=3, init=np.vstack([o_data[600], o_data[601], o_data[100]]))
est.fit(o_data)
y = est.labels_
fig = plt.figure(1)
plt.scatter(o_data[:, 0], o_data[:, 1], c=y)
plt.show()```