聚类算法介绍:
在“无监督学习”(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))