聚类--KM、DBACSN,层次聚类

1. 聚类

对于聚类,关键一步是要告诉计算机怎样计算两个数据点的相似性,不同的算法需要的相似性是不一样的。

 

1.1. DBSCAN

1.1.1. DBSCAN原理

    DBSCAN核心原理就是密度聚类的原理:寻找出稠密的地方,把它们当做一个簇,也就是密度相连的区域,我们把它当成一个簇。
​
    “DBSCAN如何发现簇?”初始,给定数据集D中的所有对象都被为‘unvisited’。DBSCAN随机选择一个未访问的对象p,标记p为‘visited’,并检查p的e-领域是否至少包含MinPts个对象,如果不是,则p被标记为噪声点,否则为p创建一个新的簇C,并且把p的e-领域中的所有对象都放到候选集合N中。DBSCAN迭代地把N中不属于其它簇的对象添加到C中。在此过程中,对于N中标记为‘unvisited’的对象p‘,DBSCAN把它标记为’visited‘并且检查它的e-领域。如果p’的e-领域至少有MinPts个对象,则p‘的e-领域中的对象都被添加到N中。DBSCAN继续添加对象到C,知道C不能再扩展。

1.1.2 粗糙伪代码

radius=半径
points_num=邻近点数 
p=随机质心点
c={}
"""
以下注意:每次计算一次簇就要把数据剔除掉,用剩下的进行密度聚类
"""
for 数据 in 数据集:
    num= 计算每个数据是否属于质心半径内数据数量
    if num 
  

1.2 K-means

1.2.1 K-Means原理

    K-means的原理:就是计算每个数据到质心的距离,然后选出来簇后,再计算簇内新的质心,再次计算每个数据到质心的距离,一直迭代。知道新质心和旧质心距离小于某个阈值。

1.2.2 K-means伪代码

# 质心
center=[x1..x5]
# 存入簇和其对应数据点的字典
n_datas={}
for i in datas:
    distance_list=[]
    for j in center:
        # 计算两个点之间的距离
        distance = numpy.sqrt(sum(np.power((i,j),2)))
        # 把距离存入列表
        distance_list.append(distance)
    # 对列表进行排序,并返回最小距离和其索引
    cluster=distance_list.argsort()[0]
    # 把数据存入到对应的簇内
    keys = n_datas.keys()
    if not cluster in keys:
        n_datas['{}'.format(cluster)]=[i]
    else:
        dict_k = n_datas['{}'.format(cluster)]
        dict_k.append(i)

 

1.3 层次聚类

1.3.1 层次聚类的原理

    层次聚类,是一种很直观的算法。顾名思义就是要一层一层地聚类,可以从下而上地把小cluster合并聚类,也可以从上而下地将大cluster进行分割。似乎一般用得比较多的是从下而上地聚集。
    所谓从下而上地合并cluster,具体而言,就是每次找到最短的两个cluster,然后合并成为一个大的cluster,知道全部合并为一个cluster。整个过程就是建立一个树结构,类似于下图。

聚类--KM、DBACSN,层次聚类_第1张图片

    那么,如何判断两个cluster之间的距离呢?一开始每个数据点作为一个簇,他们的距离就是这两个点之间的距离,二对于包含不止一个点的cluster就可以选择多种方法了。最常用的,就是average-linkage,即计算两个cluster各自数据点的两两距离的平均值。类似的还有single-linkage、complete-linkage,选择两个cluster中距离最短、最长的一对数据点的距离作为类的距离。这两种不怎么用。
    层次聚类较大的有点,就是它一次性得到了整个聚类过程,只要得到上面的聚类数,想要分多少cluster都可以直接根据树结构来得到结果,改变cluster数目不需要再次计算数据点的归属。层次聚类的缺点是计算量比较大,因为每次都要计算多个cluster内所有数据点的两两之间的距离。另外,层次聚类,是贪心算法,得到的是局部最优,不是全局最优,可以通过加入随机效应。

1.3.2 如何确定如何取cluster?

    对于层次聚类,可以根据聚类过程中,每次合并的两个cluster的距离来做大概判断。根据一下图可以做个大概的估计,在簇4位置随着聚类步数增加簇量增加,可以得到簇4比较好

聚类--KM、DBACSN,层次聚类_第2张图片

1.3.3 层次聚类伪代码

# 计算点与点距离公式
def em(self,A,B):
    distance = np.sqrt(sum(np.power(A-B,2)))
    return distance
# 计算两个簇中每个数据点与其他数据点的距离,取均值作为两个数据点的距离
# 计算簇与簇之间的距离
def anerageLinkage(self,A,B):
    total=0.0
    for i in A:
        for j in B:
            # 计算所有数据点两两之间的距离,具有A*B个
            total+=em(i,j)
    ret = total/(A.shape[0]*B.shape[0])
    return ret
# 对簇之间的距离进行对比,选取最近的两个合并

1.4 算法之间的优缺点

1.4.1 K-means

K-means的标准:
    1.k值得确定,我们必须确定我们算法中需要分几类。
    2.计算距离公式,这个公式可以用欧氏距离计算。
    3.聚类中心的计算,因为要不断更新聚类中心点需要一个更新策略更新。
​
优点:
    1.k均值算法是解决聚类问题的一种经典算法,算法简单,快速
    2.对处理大数据,该算法是相对可伸缩的和高效率的,因为它的复杂度是O(nkt)
    3.算法尝试找出使平方误差函数值最小的k个划分。当簇是密集的球状或团装,而      簇与簇之间区别明显时,它的聚类效果很好。
​
缺点:
    1.对K值敏感。k值得选择会在很大程度上影响分类效果。需要进行数据分析
    2.对离群点和噪声点敏感。如果上述数据集汇总添加一个噪声点,这个噪声点独立称为一个类。
    3.初始聚类中心的选择。K-means是随机选择K个点作为初始的聚类中心。
    4.只能聚集凸的数据集,因为是计算连接两个点之间的距离。所以计算的聚类形状只能是球形。研究表明,若采用Bregman距离,则可显著增强此类算法对更多类型簇结构的适用性。
​
改进:
    1.针对K值得选择其问题,主要是K值必须预先设定,并且整个算法执行过程汇总无法更改。此时,可以利用ISODATA算法;当属于某个类别的样本过少,九江这个类别跳出;当这个类别的样本过多的时候,分散程度很大的时候,九江这个特类别分为两个自类。实际应用中,最常用的任然是基于不同的K值,多次运行取平均值
    2.针对离群点和噪声点,我们可以使用一些算法,比如RANSAC,LOD等提出离群点。此外基于KM的算法有k-medoids和k-medians
    3.对于初始聚类中心点的问题,K-means++不在选择K格局类中心:假设已经选择m个聚类中心(0 
  

1.4.2 DBSCAN算法:基于密度的聚类算法

优点:
    1.自适应的聚类,不需要提前设定K值大小,可以自适应的做聚类效果。
    2.对噪声不敏感。因为该算法能够很好的判断离群点,并且即使判错离群点,对最终的聚类结果也没什么影响
    3.能发现任意形状的簇。这是因为DBSCAN是靠不断链接邻域高密度点来发现簇,只需要定义邻域大小和密度阈值,因此可以发现不同形状的簇
    4.聚类效果没有偏倚,相对的KM均值初始值对聚类结果有很大影响。
​
缺点:
    1.对两个参数的设置敏感,即圈的半径和阈值。
    2.DBSCAN使用固定的参数识别聚类,显然,当聚类的稀疏程度不同,聚类的效果也不同。即数据密度不均匀,很难使用该算法。
    3.如果数据样本集雨大,收敛时间越长。此时可以使用KD树优化。

1.4.3 层次聚类

优点:
    1.距离和规则的相似度容易定义,限制少。
    2.不需要余弦指定聚类数。
    3.可以发现类的层次关系
​
缺点:
    1.计算复杂度搞。
    2.奇异值也能产生很大影响
    3.算法很可能聚类成链状

你可能感兴趣的:(机器学习)