机器学习算法-k-means聚类算法介绍

聚类算法介绍:

在“无监督学习”(unsupervised learning)中,训练样本的标记信息是未知的,目标是通过对无标记训练样本的学习来揭示数据的内在性质及规律,为进一步的数据分析提供基础、此类学习任务中研究最多、应用最广的是“聚类”(clustering)。
聚类(clustering)是指根据“物以类聚”的原理,将本身没有类别的样本聚集成不同的组,这样的一组数据对象的集合叫做簇,并且对每一个这样的簇进行描述的过程。
在分类( classification )中,对于目标数据库中存在哪些类是知道的,要做的就是将每一条记录分别属于哪一类标记出来。聚类分析也称无监督学习, 因为和分类学习相比,聚类的样本没有标记,需要由聚类学习算法来自动确定。聚类分析是研究如何在没有训练的条件下把样本划分为若干类。

评价指标:

聚类性能度量亦称聚类“有效性指标”(validityindex).与监督学习中的性能度量作用相似,对聚类结果,我们需通过某种性能度量来评估其好坏;另一方面,若明确了最终将要使用的性能度量,则可直接将其作为聚类过程的优化目标,从而更好地得到符合要求的聚类结果。
聚类性能度量大致有两类. 一类是将聚类结果与某个“参考模型”进行比较,称为“ 外部指标”;另一类是直接考察聚类结果而不利用任何参考模型,称为“内部指标”。

优缺点:

优点:

是解决聚类问题的一种经典算法,简单、快速。
对处理大数据集,该算法是相对可伸缩和高效率的。
因为它的复杂度是0 (nkt ) , 其中, n 是所有对象的数目, k 是簇的数目, t 是迭代的次数。通常k < <n 且t < <n 。
当结果簇是密集的,而簇与簇之间区别明显时, 它的效果较好

缺点:

在簇的平均值被定义的情况下才能使用,这对于处理符号属性的数据不适用。
必须事先给出k(要生成的簇的数目),而且对初值敏感,对于不同的初始值,可能会导致不同结果。经常发生得到次优划分的情况。解决方法是多次尝试不同的初始值。
它对于“躁声”和孤立点数据是敏感的,少量的该类数据能够对平均值产生极大的影响

距离计算:
对函数dist(,),若它是一个“距离度量”,则需满足一些基本性质:非负性、同一性、对称性和直递性。

在这里插入图片描述

对无序属性可采用VDM方法计算,令mu,a表示在属性u .上取值为a的样本数, mu,a,i 表示在第i个样本簇中在属性u.上取值为a的样本数, k为样本簇数,则属性u上两个离散值a与b 之间的VDM距离为:

在这里插入图片描述

于是,将闵可夫斯基距离和VDM结合即可处理混合属性.假定有nc个有序属性、n-nc个无序属性,不失一般性,令有序属性排列在无序属性之前,则

在这里插入图片描述

K-means算法介绍

聚类分析是无监督类机器学习算法中最常用的一类,其目的是将数据划分成有意义或有用的组(也被称为簇)。组内的对象相互之间是相似的(相关的),而不同组中的对象是不同的(不相关的)。组内的相似性(同质性) 越大,组间差别越大,聚类就越好。
简单来说,簇就是分类结果中的类,但实际上簇并没有明确的定义,并且簇的划分没有客观标准,我们可以利用下图来理解什么是簇。该图显示了20个点和将它们划分成簇的3种不同方法。标记的形状指示簇的隶属关系。下图分别将数据划分成两部分、四部分和六部分。将2个较大的簇每一个 都划分成3个子簇可能是人的视觉系统造成的假象。此外,说这些点形成4个簇可能也不无道理。该图表明簇的定义是不精确的,而最好的定义依赖于数据的特性和期望的结果。

在这里插入图片描述

K-均值聚类算法
K均值是发现给定数据集的k个簇的算法。簇个数k是用户给定的,每一一个簇通过其质心(centroid) 来描述。K均值工作流程是这样的:首先,随机选择K个初始质心,其中K是用户指定的参数,即所期望的簇的个数。然后将数据集中每个点指派到最近的质心,而指派到- -个质心的点即为一个簇。然后,根据指派到簇的点,将每个簇的质心更新为该簇所有点的平均值。重复指派和更新步骤,直到簇不发生变化,或等价地,直到质心不发生变化。
根据k-均值算法的工作流程,我们可以写出伪代码:
创建k个点作为初始质心(通常是随机选择)
当任意一个点的簇分配结果发生改变时:
对数据集中的每个点:
对每个质心:
计算质心与数据点之间的距离
将数据点分配到据其最近的簇
对每个簇,计算簇中所有点的均值并将均值作为新的质心
直到簇不再发生变化或者达到最大迭代次数

k-means鸢尾花聚类实现

#导入包
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
#导入数据集
iris=pd.read_csv('iris.txt',header=None);
# print(iris)
#计算两个数据集之间的距离
def distEclued(arra,arrb):
    d=arra-arrb;
    dist=np.sum(np.power(d,2),axis=1);
    return dist;
#编写自动生成的随机的质心
def suiji_zhixin(dataset,k):
    n=dataset.shape[1];
    data_min=dataset.iloc[:,:n-1].min();
    data_max=dataset.iloc[:,:n-1].max();
    #随机生成质心
    data_cent=np.random.uniform(data_min,data_max,(k,n-1));
    return data_cent;
# print(suiji_zhixin(iris,3))
#k-means聚类算法实现
def Kmeans(dataset,k,distmeans=distEclued,createCent=suiji_zhixin):
    #dataset表示数据集
    #k表示簇
    #distmeans表示欧式距离
    #createCent表示随机生成k个质心
    m,n=dataset.shape;
    #生成质心
    centrods=createCent(dataset,k);
    #构造容器3列。第一列存放每个点到质心的距离,第二列表示对应的质心
    #第三列表示上一次对应的质心
    clusterAssment=np.zeros((m,3))
    clusterAssment[:,0]=np.inf;#第一列先设置无穷大
    clusterAssment[:,1:3]=-1;#第二列和第三列设置为-1
    #将数据集与容器相拼接
    resault_set=pd.concat([dataset,pd.DataFrame(clusterAssment)],axis=1,ignore_index=True);
    clusterchanged=True;
    while clusterchanged:
        #迭代循环
        clusterchanged=False;
        for i in range(m):
            #计算每一个点到质心的距离
            dist=distmeans(dataset.iloc[i,:n-1].values,centrods);
            #将距离的最小值放入结果的第n列存放
            resault_set.iloc[i,n]=dist.min();
            #将最小距离的的索引放入结果的第n+1列存放
            resault_set.iloc[i,n+1]=np.where(dist==dist.min())[0];
            #.np.where(condition) 当where内只有一个参数时,那个参数表示条件,
            # 当条件成立时,where返回的是每个符合condition条件元素的坐标
        clusterchanged=not(resault_set.iloc[:,-1]==resault_set.iloc[:,-2]).all();
            #all()表示所有,只要有一个是false则返回false
            #否则返回true
        if clusterchanged:
            #cent_df表示对本次的结果的第n+1列(表示的是质心的位置)
            cent_df=resault_set.groupby(n+1).mean();
            #重新计算质心,找出每一个
            centrods=cent_df.iloc[:,:n-1].values;
            resault_set.iloc[:,-1]=resault_set.iloc[:,-2];
        #返回质心和结果
        return centrods,resault_set
#显示分类结果
test1_cent,test1_cluster=Kmeans(iris,3,distEclued,suiji_zhixin)
#test1=Kmeans(iris,3,distEclued,suiji_zhixin)
# print(test1)
# plt.scatter(test_cluster.iloc[:,0],test_cluster.iloc[:,1],c=test_cluster.iloc[:,-1])
# plt.scatter(test_cent[:,0],test_cent[:,1],color='red',marker='x',s=80)
# plt.show();
#导入测试集
test=pd.read_table('testSet.txt',header=None)
# print(test)
#显示测试集的分布
plt.scatter(test.iloc[:,0],test.iloc[:,1]);
# plt.show();
#假设是标签
ze=pd.DataFrame(np.zeros(test.shape[0]).reshape(-1,1))
# print(ze.head())
test_set=pd.concat([test,ze],axis=1,ignore_index=True)
# print(test_set.head())
test_cent,test_cluster=Kmeans(test_set,4)
# print(test_cent)
# print(test_cluster)
plt.scatter(test_cluster.iloc[:,0],test_cluster.iloc[:,1],c=test_cluster.iloc[:,-1])
plt.scatter(test_cent[:,0],test_cent[:,1],color='red',marker='x',s=80)
plt.show();
#误差计算
# print(test_cluster.iloc[:,3].sum())
# print("----------------")
# print(test1_cluster.iloc[:,5].sum())
#
#学习聚类曲线
def KleanCruve(dataset,cluster=Kmeans,k=10):
    n=dataset.shape[1];
    SSE=[];
    for i in range(1,k):
        centroids,result=cluster(dataset,i+1);
        SSE.append(result.iloc[:,n].sum())
    plt.plot(range(2,k+1),SSE,'--o');
    plt.show();
    return SSE;
print(KleanCruve(iris))


在这里插入图片描述
在这里插入图片描述

分析:

在执行前面聚类算法的过程中,好像虽然初始质心是随机生成的,但最终分类结果均保持-致。若初始化参数是随机设置(如此处初始质心位置是随机生成的),但最终模型在多次迭代之后稳定输出结果,则可认为最终模型收敛,所谓迭代是指上次运算结果作为下一-次运算 的条件参与计算,kMeans的每次循环本质上都是迭代,我们利用上次生成的中心点参与到下次距离计算中。
同时,在之前我们编写k-Means聚类算法中我们设置的收敛条件比较简单,就是最近两次迭代各点归属簇的划分结果,若结果不发生变化,则表明结果收敛,停止迭代。但实际上这种收敛条件并不稳定,尤其是在我们采用均值作为质心带入计算的过程中,实际上是采用了梯度下降作为优化手段,但梯度下降本质上是无约束条件下局部最优手段,局部最优手段最终不一定导致全局最优, 即我们使用均值作为质心带入迭代,最终依据收敛判别结果计算的最终结果一定是基于初始质心的局部最优结果,但不一定是全局最优的结果,因此其实刚才的结果并不稳定,最终分类和计算的结果会收到初始质心选取的影响。
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值