当前位置:首页 » 编程语言 » pythonkmeans算法

pythonkmeans算法

发布时间: 2024-08-05 19:22:04

⑴ kmeans算法python怎么实现

第一种: 引用scikit-learn包

fromsklearn.clusterimportKMeans

k=10#Kmeans的k值
model=Kmeans(n_clusters=k)
X=[[1,2],[1,3],[2,1],....]#改成你的数据
model.fit(X)
#然后就训练好了,可以查看model的属性
model.cluster_centers
model.labels_

第二种: 自己写代码实现

importnumpyasnp
importrandom
data=[[1,1,1],[1,1,3],[1,2,1],[5,1,1],[5,1,2],[5,2,1],[5,5,5],[5,5,4],[5,4,4]]
data=np.array(data)

k=4#kmeans的k
n_iteration=500#最大迭代次数


#求初始化的k个质心(这k个质心必须包含在k个点的凸空间内)
center=np.matrix(np.zeros((k,len(data[0]))))
center_after=np.matrix(np.zeros((k,len(data[0]))))
foriinrange(len(data[0])):
center[:,i]=min(data[:,i])+(max(data[:,i])-min(data[:,i]))*np.random.rand(k,1)


defcalc_distance(x,y,distance='eucidean'):
x,y=np.array(x),np.array(y)
ifdistance=='eucidean':
returnnp.sqrt(np.sum((y-x)**2))


n=0
while1:
n+=1
print('第%s次迭代'%n)
#计算所有点到每个质心的距离,将每个点分到距离最近的那个点那一类
#9个点里哪个质心最近,就分到第几个类
label=np.argmin(np.array([calc_distance(x,y)forxindataforyincenter]).reshape(len(data),k),axis=1)
print(label)
#重新计算质心
foriinrange(k):
center_after[i]=np.mean(np.array([data[j]forjinrange(len(data))iflabel[j]==i]),axis=0)
ifnp.sum(np.abs(center_after-center))<0.01:
#print(np.sum(np.abs(center_after-center)))
print('相邻两次迭代改变甚小,迭代结束')
break
ifn>n_iteration:
print('迭代次数已达上限,迭代结束')
break
center=center_after

⑵ kmeans算法用Python怎么实现

1、从Kmeans说起
Kmeans是一个非常基础的聚类算法,使用了迭代的思想,关于其原理这里不说了。下面说一下如何在matlab中使用kmeans算法。
创建7个二维的数据点:

复制代码代码如下:
x=[randn(3,2)*.4;randn(4,2)*.5+ones(4,1)*[4 4]];

使用kmeans函数:

复制代码代码如下:
class = kmeans(x, 2);

x是数据点,x的每一行代表一个数据;2指定要有2个中心点,也就是聚类结果要有2个簇。 class将是一个具有70个元素的列向量,这些元素依次对应70个数据点,元素值代表着其对应的数据点所处的分类号。某次运行后,class的值是:

复制代码代码如下:

2
2
2
1
1
1
1

这说明x的前三个数据点属于簇2,而后四个数据点属于簇1。 kmeans函数也可以像下面这样使用:

复制代码代码如下:

>> [class, C, sumd, D] = kmeans(x, 2)

class =
2
2
2
1
1
1
1
C =
4.0629 4.0845
-0.1341 0.1201
sumd =
1.2017
0.2939
D =
34.3727 0.0184
29.5644 0.1858
36.3511 0.0898
0.1247 37.4801
0.7537 24.0659
0.1979 36.7666
0.1256 36.2149

class依旧代表着每个数据点的分类;C包含最终的中心点,一行代表一个中心点;sumd代表着每个中心点与所属簇内各个数据点的距离之和;D的每一行也对应一个数据点,行中的数值依次是该数据点与各个中心点之间的距离,Kmeans默认使用的距离是欧几里得距离(参考资料[3])的平方值。kmeans函数使用的距离,也可以是曼哈顿距离(L1-距离),以及其他类型的距离,可以通过添加参数指定。
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++
在http://rosettacode.org/wiki/K-means%2B%2B_clustering 中能找到多种编程语言版本的Kmeans++实现。下面的内容是基于python的实现(中文注释是笔者添加的):

复制代码代码如下:

from math import pi, sin, cos
from collections import namedtuple
from random import random, choice
from import

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_dist > d:
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] = (choice(points)) #随机选取第一个中心点
d = [0.0 for _ in xrange(len(points))] #列表,长度为len(points),保存每个点离最近的中心点的距离
for i in xrange(1, len(cluster_centers)): # i=1...len(c_c)-1
sum = 0
for j, p in enumerate(points):
d[j] = nearest_cluster_center(p, cluster_centers[:i])[1] #第j个数据点p与各个中心点距离的最小值
sum += d[j]
sum *= random()
for j, di in enumerate(d):
sum -= di
if sum > 0:
continue
cluster_centers[i] = (points[j])
break
for p in points:
p.group = nearest_cluster_center(p, cluster_centers)[0]
'''
points是数据点,nclusters是给定的簇类数目
'''
def lloyd(points, nclusters):
cluster_centers = [Point() for _ in xrange(nclusters)] #根据指定的中心点个数,初始化中心点,均为(0,0,0)
# call k++ init
kpp(points, cluster_centers) #选择初始种子点
# 下面是kmeans
lenpts10 = len(points) >> 10
changed = 0
while True:
# group element for centroids are used as counters
for cc in cluster_centers:
cc.x = 0
cc.y = 0
cc.group = 0
for p in points:
cluster_centers[p.group].group += 1 #与该种子点在同一簇的数据点的个数
cluster_centers[p.group].x += p.x
cluster_centers[p.group].y += p.y
for cc in cluster_centers: #生成新的中心点
cc.x /= cc.group
cc.y /= cc.group
# find closest centroid of each PointPtr
changed = 0 #记录所属簇发生变化的数据点的个数
for p in points:
min_i = nearest_cluster_center(p, cluster_centers)[0]
if min_i != p.group:
changed += 1
p.group = min_i
# stop when 99.9% of points are good
if changed <= lenpts10:
break
for i, cc in enumerate(cluster_centers):
cc.group = i
return cluster_centers
def print_eps(points, cluster_centers, W=400, H=400):
Color = namedtuple("Color", "r g b");
colors = []
for i in xrange(len(cluster_centers)):
colors.append(Color((3 * (i + 1) % 11) / 11.0,
(7 * i % 11) / 11.0,
(9 * i % 11) / 11.0))
max_x = max_y = -FLOAT_MAX
min_x = min_y = FLOAT_MAX
for p in points:
if max_x < p.x: max_x = p.x
if min_x > p.x: min_x = p.x
if max_y < p.y: max_y = p.y
if min_y > p.y: min_y = p.y
scale = min(W / (max_x - min_x),
H / (max_y - min_y))
cx = (max_x + min_x) / 2
cy = (max_y + min_y) / 2
print "%%!PS-Adobe-3.0\n%%%%BoundingBox: -5 -5 %d %d" % (W + 10, H + 10)
print ("/l {rlineto} def /m {rmoveto} def\n" +
"/c { .25 sub exch .25 sub exch .5 0 360 arc fill } def\n" +
"/s { moveto -2 0 m 2 2 l 2 -2 l -2 -2 l closepath " +
" gsave 1 setgray fill grestore gsave 3 setlinewidth" +
" 1 setgray stroke grestore 0 setgray stroke }def")
for i, cc in enumerate(cluster_centers):
print ("%g %g %g setrgbcolor" %
(colors[i].r, colors[i].g, colors[i].b))
for p in points:
if p.group != i:
continue
print ("%.3f %.3f c" % ((p.x - cx) * scale + W / 2,
(p.y - cy) * scale + H / 2))
print ("\n0 setgray %g %g s" % ((cc.x - cx) * scale + W / 2,
(cc.y - cy) * scale + H / 2))
print "\n%%%%EOF"
def main():
npoints = 30000
k = 7 # # clusters
points = generate_points(npoints, 10)
cluster_centers = lloyd(points, k)
print_eps(points, cluster_centers)
main()

上述代码实现的算法是针对二维数据的,所以Point对象有三个属性,分别是在x轴上的值、在y轴上的值、以及所属的簇的标识。函数lloyd是kmeans++算法的整体实现,其先是通过kpp函数选取合适的种子点,然后对数据集实行kmeans算法进行聚类。kpp函数的实现完全符合上述kmeans++的基本思路的2、3、4步。

⑶ python代码如何应用系统聚类和K-means聚类法进行聚类分析 然后选择变量,建立适当的模型

-Means聚类算法
k-means算法以k为参数,把n个对象分成k个簇,使簇内具有较高的相似度,而簇间的相似度较低。

随机选择k个点作为初始的聚类中心。
对于剩下的点,根据其与聚类中心的距离,将其归入最近的簇。
对每个簇,计算所有点的均值作为新的聚类中心。
重复2,3直到聚类中心不再发生改变

Figure 1

K-means的应用
数据介绍:
现有1999年全国31个省份城镇居民家庭平均每人全年消费性支出的八大主要变量数据,这八大变量分别是:食品、衣着、家庭设备用品及服务、医疗保健、交通和通讯、娱乐教育文化服务、居住以及杂项商品和服务。利用已有数据,对31个省份进行聚类。

实验目的:
通过聚类,了解1999年各个省份的消费水平在国内的情况。

技术路线:
sklearn.cluster.Kmeans

数据实例:

⑷ kmeans算法用Python怎么实现

K-means算法是集简单和经典于一身的基于距离的聚类算法

采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。

该算法认为类簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。

核心思想

通过迭代寻找k个类簇的一种划分方案,使得用这k个类簇的均值来代表相应各类样本时所得的总体误差最小。

k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。

k-means算法的基础是最小误差平方和准则,


各类簇内的样本越相似,其与该类均值间的误差平方越小,对所有类所得到的误差平方求和,即可验证分为k类时,各聚类是否是最优的。

上式的代价函数无法用解析的方法最小化,只能有迭代的方法。

热点内容
超低温疫苗存储冰柜生产厂家 发布:2024-11-25 22:32:58 浏览:537
x86linux 发布:2024-11-25 22:09:24 浏览:450
qq群怎么设置上传 发布:2024-11-25 22:08:37 浏览:16
加密户籍 发布:2024-11-25 22:08:32 浏览:214
newman算法 发布:2024-11-25 21:34:55 浏览:201
a算法概念 发布:2024-11-25 21:24:16 浏览:588
jquery源码书籍 发布:2024-11-25 21:19:50 浏览:804
银行卡输入密码超限怎么办 发布:2024-11-25 21:09:07 浏览:958
编译指令多发 发布:2024-11-25 20:58:17 浏览:751
java上传文件到服务器 发布:2024-11-25 20:52:47 浏览:742