什么是聚类?
通常来说,当一个数据集没有标签的时候,我们又希望对它们进行分类,此时聚类算法就会通过一些指标来自动寻找彼此相关或相似的数据点,其中最常用的就是欧氏距离和余弦距离。比较常见的聚类算法有K-means、Meanshift(均值漂移算法)、DSBSCAN等无监督学习模型,KNN监督学习模型。
欧氏距离
通俗来讲欧氏距离就是计算空间中两点之间的距离
代码实现
def EuclideanDistance(x, y):
import numpy as np
x = np.array(x)
y = np.array(y)
return np.sqrt(np.sum(np.square(x-y)))
余弦距离
余弦距离又叫做余弦相似度,几何中夹角余弦可用来衡量两个向量方向的差异,机器学习中借用这一概念来衡量样本向量之间的差异。相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。n维空间中的余弦距离为:
代码实现
def CosineDistance(x, y):
import numpy as np
x = np.array(x)
y = np.array(y)
return np.dot(x,y)/(np.linalg.norm(x)*np.linalg.norm(y))
K-means
K-means是一种比较常见的聚类算法。其主要步骤为:
1.随机选取k个中心点作为初始中心点
2.遍历所有数据点,计算每一个数据点到每个中心点的距离,然后将每个点与中心点距离最近的分为一类。
3.计算分为一类的每个点各个维度的平均值,将计算完的均值作为新的中心点,然后重复2的操作,直到中心点不变或者收敛。
评估标准
调用kmeans里的inertia_函数,即每个样本与质心的距离。
损失函数
我们希望损失函数越小越好,即每个点到质心的距离越小越好。如何选择一个合适的k值呢?此时我们就可以多做几组对比试验,然后绘图分析
缺点:k值难以确定;如果数据量过大,计算成本很高,即复杂度与样本数量呈线性关系;很难发现任意类型的簇,像一些圆形、形状不规则的等等
最主要的我认为就是随机选取中心的不同,可能会导致分类类别产生巨大的差异,具体的可以去做一些对比试验。
Meanshift
均值漂移算法,一种基于密度梯度上升的聚类算法(沿着密度上升方向寻找聚类中心点),主要步骤:
1、在未被标记的数据点中随机选择一个点作为中心center;
2、找出离center距离在bandwidth之内的所有点,记作集合M。认为这些点属于簇c。同时,把这些求内点属于这个类的概率加1,这个步骤将用于最后步骤的分类。
3、以center为中心点,计算M中所有点到中心点向量,将这些向量相加的带向量shift
4、center = center+shift。即center沿着shift的方向移动,移动距离是||shift||。
5、重复步骤2、3、4,直到shift的大小很小(就是迭代到收敛),记住此时的center。注意,这个迭代过程中遇到的点都应该归类到簇c。
6、如果收敛时当前簇c的center与其它已经存在的簇c2中心的距离小于阈值,那么把c2和c合并。否则,把c作为新的聚类,增加1类。
6、重复1、2、3、4、5直到所有的点都被标记访问。
7、分类:根据每个类,对每个点的访问频率,取访问频率最大的那个类,作为当前点集的所属类。
from sklearn.cluster import MeanShift
import numpy as np
X = np.array([[1, 1], [2, 1], [1, 0],
[4, 7], [3, 5], [3, 6]])
clustering = MeanShift(bandwidth=2).fit(X) #bandwidth就是半径
KNN
KNN算法是一种监督学习的聚类模型,它有确定的标签,KNN算法预测数据属于哪一个类别我感觉十分容易理解,就是基于已有标签的数据,对于需要预测的数据计算与其最近的k个,k值是我们自己定义的,然后预测数据类别就为这k个样本中类别数量最多的一类。下面就是一个简单KNN模型分类器的代码,里面的参数看他的API文档吧,很详细,多看API文档可以让你很熟悉对模型的搭建及其中的一些参数。
from sklearn.neighbors import KNeighborsClassifie
KNN = KNeighborsClassifier(n_neighbors = 5,
weights='uniform',
algorithm = '',
leaf_size = '30',
p = 2,
metric = 'minkowski',
metric_params = None,
n_jobs = None
)
DBSCAN
这个是我最常用的一个聚类算法,其步骤有点类似于“传销”,一些官方概念比如核心对象,密度可达,直接密度可达,边界点等等我就不一一解释了,可以自己去了解一下。这个算法需要两个参数,第一个就是半径r,第二个就是阈值m。比如在一个二维数据点上,随机选取一个点作为核心点,以该点为圆心,r为半径,如果在这个圆内数据点的数量大于或等于我们设定的阈值m,我们把圆内这些点都当作为核心点,然后不断去发展下限,直到不能发展下线了,我们把这些不能发展下限的点称作为边界点。
这种算法的优点就是可以发现任意类型的簇,不需要指定簇的个数,非常善于发现离群点,可以用于异常检测任务中;当然,它也有缺点,由于DBSCAN算法是无监督学习,没有标准答案,所以它的参数难以设定,这个往往我们可以做一些对比试验,通过可视化或者损失函数来选择合适的参数,它对高维数据处理也有些困难,当然我们也可以选择降维等操作。
代码
from sklearn.cluster import DBSCAN
clustering = DBSCAN(eps=3, min_samples=2).fit(X) #eps就是半径r,min_samples就是我们设定的阈值
#其他的一些参数或属性去sklearnAPI文档查看即可
加油加油!!!