python中聚类的函数 python 聚类函数( 五 )


kmeans有几个缺点(这在很多资料上都有说明):
1、最终簇的类别数目(即中心点或者说种子点的数目)k并不一定能事先知道,所以如何选一个合适的k的值是一个问题 。
2、最开始的种子点的选择的好坏会影响到聚类结果 。
3、对噪声和离群点敏感 。
4、等等 。
2、kmeans++算法的基本思路
kmeans++算法的主要工作体现在种子点的选择上 , 基本原则是使得各个种子点之间的距离尽可能的大,但是又得排除噪声的影响 。以下为基本思路:
1、从输入的数据点集合(要求有k个聚类)中随机选择一个点作为第一个聚类中心
2、对于数据集中的每一个点x , 计算它与最近聚类中心(指已选择的聚类中心)的距离D(x)
3、选择一个新的数据点作为新的聚类中心 , 选择的原则是:D(x)较大的点,被选取作为聚类中心的概率较大
4、重复2和3直到k个聚类中心被选出来
5、利用这k个初始的聚类中心来运行标准的k-means算法
假定数据点集合X有n个数据点 , 依次用X(1)、X(2)、……、X(n)表示,那么,在第2步中依次计算每个数据点与最近的种子点(聚类中心)的
距离,依次得到D(1)、D(2)、……、D(n)构成的集合D 。在D中,为了避免噪声 , 不能直接选取值最大的元素,应该选择值较大的元素 , 然后将其对应
的数据点作为种子点 。
如何选择值较大的元素呢 , 下面是一种思路(暂未找到最初的来源,在资料[2]等地方均有提及,笔者换了一种让自己更好理解的说法):
把集合D中的每个元素D(x)想象为一根线L(x),线的长度就是元素的值 。将这些线依次按照L(1)、L(2)、……、L(n)的顺序连接起来,组成长
线L 。L(1)、L(2)、……、L(n)称为L的子线 。根据概率的相关知识,如果我们在L上随机选择一个点,那么这个点所在的子线很有可能是比较长的子
线 , 而这个子线对应的数据点就可以作为种子点 。下文中kmeans++的两种实现均是这个原理 。
3、python版本的kmeans++
在 中能找到多种编程语言版本的Kmeans++实现 。下面的内容是基于python的实现(中文注释是笔者添加的):
复制代码 代码如下:
from math import pi, sin, cos
from collections import namedtuple
from random import random, choice
from copy import copy
try:
import psyco
psyco.full()
except ImportError:
pass
FLOAT_MAX = 1e100
class Point:
__slots__ = ["x", "y", "group"]
def __init__(self, x=0.0, y=0.0, group=0):
self.x, self.y, self.group = x, y, group
def generate_points(npoints, radius):
points = [Point() for _ in xrange(npoints)]
# note: this is not a uniform 2-d distribution
for p in points:
r = random() * radius
ang = random() * 2 * pi
p.x = r * cos(ang)
p.y = r * sin(ang)
return points
def nearest_cluster_center(point, cluster_centers):
"""Distance and index of the closest cluster center"""
def sqr_distance_2D(a, b):
return (a.x - b.x) ** 2+(a.y - b.y) ** 2
min_index = point.group
min_dist = FLOAT_MAX
for i, cc in enumerate(cluster_centers):
d = sqr_distance_2D(cc, point)
if min_distd:
min_dist = d
min_index = i
return (min_index, min_dist)
'''
points是数据点 , nclusters是给定的簇类数目
cluster_centers包含初始化的nclusters个中心点,开始都是对象-(0,0,0)
'''
def kpp(points, cluster_centers):
cluster_centers[0] = copy(choice(points)) #随机选取第一个中心点
d = [0.0 for _ in xrange(len(points))]#列表,长度为len(points),保存每个点离最近的中心点的距离

推荐阅读