K-MEANS聚类算法的原理和案例
本文字数4000左右,主要涉及以下几个重点:
1、聚类原理
2、数据划分方法
3、kmeans聚类算法
4、基于python的kmeans案例
5、基于python的肘部算法案例
聚类原理
将物理或抽象对象的集合分成由类似的对象组成的多个类的过程被称为聚类。即给定一组数据点,可以用聚类算法将每个数据点划分为一个特定的组,理论上同一组中的数据点颖具有相似的属性或特征,而不同组的数据点应具有高度不同的属性或特征。
不同于分类,聚类所要求划分的类是未知的。聚类是一种无监督学习的方法(没有标签的数据),是常用的统计数据分析技术。无监督学习问题是指,有一系列标签,用假设函数去拟合它,作为对比;而在无监督学习中数据并没有任何标签,无监督学习做的是就是将系列没有标签的数据输入到算法中,再让算法找到隐含在数据中的结构。
传统的聚类分析计算方法可分为几种:以划分方法为基本思想的K-MEANS算法、K-MEDOIDS算法和CLARANS算法;以层次方法为基本思想的BIRCH算法、CURE算法和CHAMELEON算法;基于密度的方法的DBSCAN算法、OPTICS算法和DENCLUE算法;基于网格的方法的STING算法、CLIQUE算法和WAVE-CLUSTER算法;基于模型的方法算法等。
数据划分方法
即给定一个有N个元组或记录的数据集,分裂法构造K个分组,每个分组代表一个聚类,K<N。K个分组满足:
(1)每个分组至少包含一个数据记录;
(2)每一个数据记录数据且仅属于一个分组。对于给定的K,算法先给出一个初始的分组方法,以后通过反复迭代的方法改变分组,使得每一次改进后的分组方案比前一次要好,其标准是:同一分组中的记录越近越好,而不同分组中的记录越远越好。
kmeans聚类算法
原理:
即K均值算法,是一种迭代求解的聚类分析算法,是一个将数据集中在某些方面相似的数据成员进行分类组织的过程。给定一个数据点集合和需要的聚类数目K,K由用户指定,K均值算法根据某个距离函数反复把数据分入K个聚类中。
K均值算法优势在于它速度很快,算法复杂度为O(k值*迭代次数t*数据的数目n)。但是也有缺点,一是必须选择有多少个组或类,二是不同的算法运行中可能产生不同的聚类结果,结果不可重复,缺乏一致性,三是常常终止于局部最优,四是对噪声和异常数据敏感及不适合用于发现非凸形状的聚类簇。关键是用该方法从数据中获得一些启示。
步骤是:
1、随机选取K个对象作为初始的聚类中心,预将数据分为K组。随机初始化K个聚类中心,记为u1,u2,……uK。可多次随机初始化并运行算法多次以得到足够好的结果。
如何选取K呢?若有一个评估标准,则看哪个聚类数目能更好应用于后续目的。还一个可尝试方法是肘部法则:
(1)先用一个类来聚类,所有数据都分到一个类中,在计算代价函数即畸变函数J,画出来。
(2)再用两个类来聚类,期间可多次初始化,该情况下得到畸变值,可能会变小,再画出来。再用三个、四个……
(3)最后得到一条曲线,随着聚类数量增多畸变值下降。
每个类别距离该类别中心点的距离称为畸变程度,而畸变程度的改善效果下降幅度最大的位置就是肘部,一般用畸变程度确定最佳值。
2、计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心;聚类中心以及分配给它们的对象就代表一个聚类。称为簇分配过程。
3、每分配一个样本,聚类的聚类中心就会根据聚类中现有对象被重新计算。即每分配一个样本,每个聚类就就算内部已有点的平均值,并将聚类中心移动到该处。
4、过程不断重复直至满足终止条件,条件可以是没有对象被重新分配给不同的聚类,没有聚类中心在发生变化,误差平方和局部最小。
基于python的kmeans案例
KMeans(n_clusters=8,
init='k-means++',
n_init=10,
max_iter=300,
tol=0.0001,
precompute_distances='auto',
verbose=0,
random_state=None,
copy_x=True,
n_jobs=1,
algorithm='auto')
(1)n_cluster即K值,为聚类的个数;
(2)n_init为初始化中心点的运算次数默认10,因为每次中心点都是随机生成的,得到的结果有好有坏,多次运行取最好的中心点作为初始;
(3)init为初始值选择方式,默认K-means++;
(4)algoritm为kmeans的实现算法:auto/full/elkan。
创建好kmeans类后就使用它,方法有fit和predict两个函数,也可合并为fit_predict函数。fit对数据进行聚类,predict针对data每个样本的聚类结果,确定所属类别。
(pred=KMeans(n_clusters=4).fit_predict(list1))
一般情况下特征数大于2,但可视化时用2维特征就可以,因此需要降维度,用到TSNE()函数,调用其中的fit_transform()函数。它是fit和transfrom函数的组合。
fit用于求得训练集X的均值、方差、最大最小值等属性,是一个训练过程,transform函数在fit函数的基础上进行标准化、降维、归一化等操作。
1、导入相关库
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.manifold import TSNE
import plotly as py
from plotly.graph_objs as go
from plotly import Scatter,Layout
pyplt=py.offline.iplot
2、导入数据集
list1=pd.DataFrame(np.random.randn(100,4))
3、特征训练和聚类分析
kmeans=KMeans(n_clusters=4).fit(list1)
pred=kmeans.predict(list1)
#或直接
#pred=KMeans(n_clusters=4).fit_predict(list1)
4、将两个数据集转化为DataFrame,并重新命名,再合并到一起:
x=pd.DataFrame(list1)
x.rename(columns={0:'one',1:'two',2:'three',3:'four'},inplace=True)
y=pd.DataFrame(pred)
y.rename(columns={0:'labels'},inplace=True)
a=pd.concat([x,y],axis=1)
5、将数据降维,并转化为DataFrame:
tsne = TSNE()
b = tsne.fit_transform(a)
liris = pd.DataFrame(b,index=a.index)
6、用标签区分并取出降维后的数据集,一分为四:
d1 = liris[a['labels']==0]
d2= liris[a['labels']==1]
d3= liris[a['labels']==2]
d4= liris[a['labels']==3]
7、将结果可视化:
trace0 = go.Scatter(
x=d1[0],
y=d1[1],
name='one',
mode='markers',
marker=dict(
size=10,
color='rgba(152, 0, 0, 0.8)',
line=dict(width=2, color='rgb(0, 0, 0)')
)
)
trace1 = go.Scatter(
x=d2[0],
y=d2[1],
name='two',
mode='markers',
marker=dict(
size=10,
color='rgba(0, 255, 93, 0.9)',
line=dict(width=2, color='rgb(0, 0, 0)')#圆圈的轮廓
)
)
trace2 = go.Scatter(
x=d3[0],
y=d3[1],
name='three',
mode='markers',
marker=dict(
size=10,
color='rgba(100, 52,200, 0.9)',
line=dict(width=2, color='rgb(0, 0, 0)')
)
)
trace3 = go.Scatter(
x=d4[0],
y=d4[1],
name='four',
mode='markers',
marker=dict(
size=10,
color='rgba(100, 220, 50, 0.9)',
line=dict(width=2, color='rgb(0, 0, 0)')
)
)
data = [trace0,trace1,trace2,trace3]
layout =go.Layout(
title='Styled Scatter',
yaxis=dict(zeroline=False), xaxis=dict(zeroline=False))
#zerline用于空值是否在0值处绘制刻度线
fig=go.Figure(data=data, layout=layout)
py.offline.iplot(fig)
基于python的肘部算法案例
#用于协助确定K值
from scipy.spatial.distance import cdist
meandistortions = []
for k in range(1, 100):
kmeans = KMeans(n_clusters=k)
kmeans.fit(RF0)
meandistortions.append(np.min(cdist(X,
kmeans.cluster_centers_,metric='euclidean'), axis=1).sum()/RF0.shape[0])
trace0=go.Scatter(x=[x for x in
range(1,100)],y=meandistortions)
data=[trace0]
layout=go.Layout()
fig=go.Figure(data=data,layout=layout)
pyplt(fig)
END