一.PAM聚类算法:
        选用簇中位置最中心的对象,试图对n个对象给出k个划分;代表对象也被称为是中心点,其他对象则被称为非代表对象;最初随机选择k个对象作为中心点,该算法反复地用非代表对象来代替代表对象,试图找出更好的中心点,以改进聚类的质量;在每次迭代中,所有可能的对象对被分析,每个对中的一个对象是中心点,而另一个是非代表对象。对可能的各种组合,估算聚类结果的质量;一个对象Oi可以被使最大平方-误差值减少的对象代替;在一次迭代中产生的最佳对象集合成为下次迭代的中心点。

对比kmeans:k-means是每次选簇的均值作为新的中心,迭代直到簇中对象分布不再变化。其缺点是对于离群点是敏感的,因为一个具有很大极端值的对象会扭曲数据分布。那么我们可以考虑新的簇中心不选择均值而是选择簇内的某个对象,只要使总的代价降低就可以。kmedoids算法比kmenas对于噪声和孤立点更鲁棒,因为它最小化相异点对的和(minimizes a sum of pairwise dissimilarities )而不是欧式距离的平方和(sum of squared Euclidean distances.)。一个中心点(medoid)可以这么定义:簇中某点的平均差异性在这一簇中所有点中最小。

 
二.算法描述:
wiki上有对pam算法的解释,这里着重对维基百科的例子进行介绍:k-medoids
k-medoid聚类算法的最常见实现为Partitioning Around Medoids (PAM)算法,PAM利用了贪婪搜索,不一定可以找到最优解,但是比穷尽搜索更快。
 
输入:簇的数目k和包含n个对象的数据
输出:k个簇,使得所有对象与其距离最近中心点的相异度总和最小

1. 初始化:随机挑选n个点中的k个点作为中心点。

2. 将其余的点根据距离划分至这k个类别中。

3. 当损失值减少时:

1)对于每个中心点m,对于每个非中心点o:

i)交换m和o,重新计算损失(损失值的大小为:所有点到中心点的距离和)

ii)如果总的损失增加则不进行交换

 
另外的一个解释,和上面一样:
1) 任意选择k个对象作为初始的簇中心点
2) Repeat
3) 指派每个剩余对象给离他最近的中心点所表示的簇
4) Repeat
5) 选择一个未被选择的中心点Oi
6) Repeat
7) 选择一个未被选择过的非中心点对象Oh
8) 计算用Oh代替Oi的总代价并记录在S中
9) Until 所有非中心点都被选择过
10) Until 所有的中心点都被选择过
11) If 在S中的所有非中心点代替所有中心点后的计算出总代价有小于0的存在,then找出S中的用非中心点替代中心点后代价最小的一个,并用该非中心点替代对应的中心点,形成一个新的k个中心点的集合;
12) Until 没有再发生簇的重新分配,即所有的S都大于0.
 
三. 例子:
对下列表中(图1)的10个数据聚类, k=2.可以看到这里每个数据的维度都为2。
           
                                 图1                                                                               图2

1. 随机挑选k=2个中心点:c1=(3,4) , c2=(7,4).那么将所有点到这两点的距离计算出来(图2),可以看到黑体为到两个中心点距离较小的距离值。那么根据图2,我们可以对所有数据点进行归类:

Cluster1 = {(3,4)(2,6)(3,8)(4,7)}

Cluster2 = {(7,4)(6,2)(6,4)(7,3)(8,5)(7,6)}

很容易算出此时的损失值cost为:20

2. 挑选一个非中心点O’,让我们假定挑选的为X7 ,即O‘=(7,3)。那么此时这两个中心点暂时变成了c1(3,4) and O′(7,3),那么我们要计算一下这一替换措施所带来的损失cost:

               

图3                                                                                                                                图4

正如图3和图4所见,此时的cost(很好计算,黑体数值的和)变成了:  total cost = 3+4+4+2+2+1+3+3 = 22

此时的cost为22,比之前的cost=20要大,所以这次替换的损失变大啦,我们最终不进行这次替换。

这仅仅是X替代了c2点,我们应该计算除了c1和c2点外的所有点分别替代c1和c2,将这些替换后的损失都计算出来,看看有没有比20小的损失,如果有那么我们就将这个最小损失对应的中心点对作为新的中心点对。至此才完成了一次迭代。重复迭代直至收敛。

 
四. python实现:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Oct 22 20:31:32 2017 @author: LPS
""" import numpy as np
import pandas as pd
import copy df = np.loadtxt('waveform.txt',delimiter=',') # 载入waveform数据集,22列,最后一列为标签0,1,2
s= np.array(df)
print(s.shape)
print(s[0:10]) data0 = s[s[:,s.shape[1]-1]==0][:100] # 取标签为0的前100个样本
data1 = s[s[:,s.shape[1]-1]==1][:100] # 取标签为1的前100个样本
data2 = s[s[:,s.shape[1]-1]==2][:100] # 取标签为2的前100个样本 data = np.array([data0,data1,data2])
data = data.reshape(-1,22) def dis(data_a, data_b):
return np.sqrt(np.sum(np.square(data_a - data_b), axis=1)) # 返回欧氏距离 def kmeans_wave(n=10, k=3, data=data):
data_new = copy.deepcopy(data) # 前21列存放数据,不可变。最后1列即第22列存放标签,标签列随着每次迭代而更新。
data_now = copy.deepcopy(data) # data_now用于存放中间过程的数据 center_point = np.random.choice(300,3,replace=False)
center = data_new[center_point,:20] # 随机形成的3个中心,维度为(3,21) distance = [[] for i in range(k)]
distance_now = [[] for i in range(k)] # distance_now用于存放中间过程的距离
lost = np.ones([300,k])*float('inf') # 初始lost为维度为(300,3)的无穷大 for j in range(k): # 首先完成第一次划分,即第一次根据距离划分所有点到三个类别中
distance[j] = np.sqrt(np.sum(np.square(data_new[:,:20] - np.array(center[j])), axis=1))
data_new[:, 21] = np.argmin(np.array(distance), axis=0) # data_new 的最后一列,即标签列随之改变,变为距离某中心点最近的标签,例如与第0个中心点最近,则为0 for i in range(n): # 假设迭代n次 for m in range(k): # 每一次都要分别替换k=3个中心点,所以循环k次。这层循环结束即算出利用所有点分别替代3个中心点后产生的900个lost值 for l in range(300): # 替换某个中心点时都要利用全部点进行替换,所以循环300次。这层循环结束即算出利用所有点分别替换1个中心点后产生的300个lost值 center_now = copy.deepcopy(center) # center_now用于存放中间过程的中心点
center_now[m] = data_now[l,:20] # 用第l个点替换第m个中心点
for j in range(k): # 计算暂时替换1个中心点后的距离值
distance_now[j] = np.sqrt(np.sum(np.square(data_now[:,:20] - np.array(center_now[j])), axis=1))
data_now[:, 21] = np.argmin(np.array(distance), axis=0) # data_now的标签列更新,注意data_now时中间过程,所以这里不能选择更新data_new的标签列 lost[l, m] = (dis(data_now[:, :20], center_now[data_now[:, 21].astype(int)]) \
- dis(data_now[:, :20], center[data_new[:, 21].astype(int)])).sum() # 这里很好理解lost的维度为什么为300*3了。lost[l,m]的值代表用第l个点替换第m个中心点的损失值 if np.min(lost) < 0: # lost意味替换代价,选择代价最小的来完成替换
index = np.where(np.min(lost) == lost) # 即找到min(lost)对应的替换组合
index_l = index[0][0] # index_l指将要替代某个中心点的候选点
index_m = index[1][0] # index_m指将要被替代的某个中心点,即用index_l来替代index_m center[index_m] = data_now[index_l,:20] #更新聚类中心 for j in range(k):
distance[j] = np.sqrt(np.sum(np.square(data_now[:, :20] - np.array(center[j])), axis=1))
data_new[:, 21] = np.argmin(np.array(distance), axis=0) # 更新参考矩阵,至此data_new的标签列得以更新,即完成了一次迭代 return data_new # 最后返回data_new,其最后一列即为最终聚好的标签 if __name__ == '__main__':
data_new = kmeans_wave(10,3,data)
print(data_new.shape)
print(np.mean(data[:,21] == data_new[:,21])) # 验证划分准确度

附:利用上面实现的代码对图片聚类。结果发现和kmeans相比实在是太慢了。就拿500*500的三通道jpg来说,有500*500=250000个像素值,即这个图像的数据集维度为(250000,3)。而上文我们实现的数据集维度仅仅为(300, 3)。这意味每次迭代都要循环250000*3次。所以我只好截选了一张小图来测试。。代码与结果如下:

pam for image

                         

图1.从1200*800图中截取的70*70的图片                                                                           图2. 迭代20次k=3的结果

其实这个结果意义不大,只是作为测试。因为像素分布太集中,可以选择其他分布较散的图像,此外改进pam算法来实现更高效的聚类。

 
 
参考:
注:无意中发现sklearn中python的实现->scikit-learn/sklearn/cluster/k_medoids_.py

K中心点算法之PAM的更多相关文章

  1. ML: 聚类算法R包-K中心点聚类

    K-medodis与K-means比较相似,但是K-medoids和K-means是有区别的,不一样的地方在于中心点的选取,在K-means中,我们将中心点取为当前cluster中所有数据点的平均值, ...

  2. 聚类分析K均值算法讲解

    聚类分析及K均值算法讲解 吴裕雄 当今信息大爆炸时代,公司企业.教育科学.医疗卫生.社会民生等领域每天都在产生大量的结构多样的数据.产生数据的方式更是多种多样,如各类的:摄像头.传感器.报表.海量网络 ...

  3. 【机器学习】K均值算法(I)

    K均值算法是一类非监督学习类,其可以通过观察样本的离散性来对样本进行分类. 例如,在对如下图所示的样本中进行聚类,则执行如下步骤 1:随机选取3个点作为聚类中心. 2:簇分配:遍历所有样本然后依据每个 ...

  4. <转>从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

    转自 http://blog.csdn.net/likika2012/article/details/39619687 前两日,在微博上说:“到今天为止,我至少亏欠了3篇文章待写:1.KD树:2.神经 ...

  5. Bisecting KMeans (二分K均值)算法讲解及实现

    算法原理 由于传统的KMeans算法的聚类结果易受到初始聚类中心点选择的影响,因此在传统的KMeans算法的基础上进行算法改进,对初始中心点选取比较严格,各中心点的距离较远,这就避免了初始聚类中心会选 ...

  6. KMeans (K均值)算法讲解及实现

    算法原理 KMeans算法是典型的基于距离的聚类算法,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大.该算法认为簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标 ...

  7. K均值算法

    为了便于可视化,样本数据为随机生成的二维样本点. from matplotlib import pyplot as plt import numpy as np import random def k ...

  8. K均值算法-python实现

    测试数据展示: #coding:utf-8__author__ = 'similarface''''实现K均值算法 算法摘要:-----------------------------输入:所有数据点 ...

  9. 从K近邻算法、距离度量谈到KD树、SIFT+BBF算法

    转载自:http://blog.csdn.net/v_july_v/article/details/8203674/ 从K近邻算法.距离度量谈到KD树.SIFT+BBF算法 前言 前两日,在微博上说: ...

随机推荐

  1. Heaven of Imaginary(PKUSC2018)

    Day-4 巨佬一个星期前就停了课,而蒟蒻还在教室里,收拾一地学科的烂摊子. 蒟蒻为什么要停课呢?真的有\(1\%\)的可能,成功报名PKUSC吗? 真的有. 蒟蒻滚回了机房. 三天,能做些什么呢?可 ...

  2. Python的单向链表实现

    思路 链表由节点组成,先规定节点(Node),包含data和指向下个节点的next 初始化 data当然就是传入的data了,next指向None 添加 分两种情况: 链表为空,那么头节点和尾节点都指 ...

  3. 自学Zabbix12.4 Zabbix命令-zabbix_sender

    点击返回:自学Zabbix之路 点击返回:自学Zabbix4.0之路 点击返回:自学zabbix集锦 自学Zabbix12.4 Zabbix命令-zabbix_sender 1. zabbix_sen ...

  4. 【BZOJ2228】[ZJOI2011]礼物(单调栈)

    [BZOJ2228][ZJOI2011]礼物(单调栈) 题面 BZOJ 洛谷 题解 如果这个玩意不是一个三维立方体,而是一个二维的矩形,让你在里面找一个最大正方形,那么全世界都会做. 丢到三维上?似乎 ...

  5. 【转】如何基于linux进程通信设计方案

    前言 linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的.而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在 ...

  6. Selenium之WebDriver元素定位方法

    Selenium WebDriver 只是 Python 的一个第三方框架, 和 Djangoweb 开发框架属于一个性质. webdriver 提供了八种元素定位方法,python语言中也有对应的方 ...

  7. [Cqoi2014]数三角形——组合数

    Description: 给定一个nxm的网格,请计算三点都在格点上的三角形共有多少个.下图为4x4的网格上的一个三角形. 注意三角形的三点不能共线. Hint: 1<=m,n<=1000 ...

  8. 洛谷P5163 WD与地图

    只有洛谷的毒瘤才会在毒瘤月赛里出毒瘤题...... 题意:三个操作,删边,改变点权,求点x所在强连通分量内前k大点权之和. 解:狗屎毒瘤数据结构乱堆...... 整体二分套(tarjan+并查集) + ...

  9. [luogu1327][生活大爆炸石头剪子布]

    题目地址 https://www.luogu.org/problemnew/show/P1328 题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一样,则不分胜负. ...

  10. 【java】详解native方法的使用

    目录结构: contents structure [+] 关于native关键字 使用native关键字 使用步骤 案例 编写.java文件 编译.java文件 获得.h文件 编写hello.cpp文 ...