1. 前言
聚类任务是无监督学习,无监督学习的目标是通过对无标记训练样本的学习来揭示数据的内在性质及规律,为进一步的数据分析提供基础。聚类试图将数据集中的样本划分为若干个通常是不相交的子集,每个子集称为一个“簇”(cluster)。
1.1 性能度量
-
外部指标:将聚类结果与某个“参考模型”(reference model)进行比较;
根据参考模型的簇划分和聚类给出的簇划分,定义
参考簇与聚类簇
常用的聚类性能度量外部指标为JC、FMI和RI。(值越大越好)
外部指标
外部指标
-
内部指标:直接考察聚类结果而不利用任何参考模型。
定义一组距离。
相关距离
聚类性能度量内部指标DBI(值越小越好)和DI(值越大越好)。
内部指标
1.2 距离计算
最常用的是闵可夫斯基距离,由此可推导出诸多如欧氏距离、曼哈顿距离等。

对于无序属性,使用VDM,即

因此对于混合属性,

有时可根据属性重要性的不同,使用加权距离

2. 原型聚类
原型聚类亦称“基于原型的聚类(prototype-based clustering)”,通常情况下算法先对原型进行初始化,然后对原型进行迭代更新求解。
- 数据集:西瓜数据集1.0
编号 密度 含糖率
1 0.697 0.46
2 0.774 0.376
3 0.634 0.264
4 0.608 0.318
5 0.556 0.215
6 0.403 0.237
7 0.481 0.149
7 0.666 0.091
8 0.437 0.211
9 0.666 0.091
10 0.243 0.267
11 0.245 0.057
12 0.343 0.099
13 0.639 0.161
14 0.657 0.198
15 0.36 0.37
16 0.593 0.042
17 0.719 0.103
18 0.359 0.188
19 0.339 0.241
20 0.282 0.257
21 0.748 0.232
22 0.714 0.346
23 0.483 0.312
24 0.478 0.437
25 0.525 0.369
26 0.751 0.489
27 0.532 0.472
28 0.473 0.376
29 0.725 0.445
30 0.446 0.459
2.1 k均值算法
通过不断迭代最小化平方误差。

算法流程

代码
#-*-coding:utf-8-*-
#K均值算法的思路是通过迭代优化最小化平方误差
import pandas as pd
import random
import math
import matplotlib.pyplot as plt
#加载数据
def loadData(path):
#从excel中载入数据
data = pd.read_excel(path)
#去除第一行表头
data = data.values
#转化为list
data = data.tolist()
print(data)
return data
#划分簇
def spiltSample(ave_vec,ori_data,C):
#在这里使用欧氏距离来进行计算
for metaData in ori_data:
#初始化最小值,设置为无穷
minDist = 1000000
#记录样本离的最近的簇的标号
index_ave_vec = 0
count = 0
for metaAve in ave_vec:
dist = 0
#计算样本离均值向量的距离
for i in range(len(metaAve)):
dist = dist + pow(metaAve[i]-metaData[i],2)
dist = math.sqrt(dist)
#若小于最近距离,则记录该簇的标号
if dist < minDist:
minDist = dist
index_ave_vec = count
count = count + 1
#将该样本点划分到离得最近的簇
C[index_ave_vec].append(metaData)
#返回划分簇的结果
return C
#更新均值向量
def updateAve(ave_vec,C):
count = 0
for metaCluster in C:
tempData = []
for i in range(len(metaCluster[0])):
tempData.append(0)
#临时列表记录该簇内样本对应属性的总值
for metaData in metaCluster:
for i in range(len(metaData)):
tempData[i] = tempData[i] + metaData[i]
#总值求平均
for i in range(len(metaCluster[0])):
ave_vec[count][i] = tempData[i]/len(metaCluster)
count = count + 1
#返回均值向量
return ave_vec
#判断新更新的向量与原均值向量是否相等
def isEqual(newVec,oldVec):
for index1 in range(len(newVec)):
for index2 in range(len(newVec[0])):
if math.fabs(newVec[index1][index2] - oldVec[index1][index2]) > 1 :
return False
return True
def drawPlot(data):
fig = plt.figure()
#画子图,这里的定义是将画布分为1行1列画在第一块即相当于没有划分
axes = fig.add_subplot(111)
count = 0
for metaCluster in data:
for metaData in metaCluster:
if count == 0:
pointColor = 'red'
elif count ==1:
pointColor = 'yellow'
elif count == 2:
pointColor = 'green'
print("metaData")
print(metaData)
axes.scatter(metaData[0],metaData[1],color=pointColor)
count = count +1
plt.xlabel("Density")
plt.ylabel("Sugar")
plt.title("K-Means Cluster")
plt.show()
if __name__=="__main__":
dataPath ="/home/stardream/DDML/MachineLearning/dataSet/watermelon4.0.xlsx"
mellonData = loadData(dataPath)
#在这里设置k值,并且随机挑选出k个样本作为初始均值向量
k = 3
aveVec = random.sample(mellonData,k)
#是否更新均值变量,用于判定是否结束循环
isUpdate = True
# iteration = 5
#while isUpdate:
for iteration in range(10):
cluster = []
# 创建k个聚类集合,并组织为列表形式
for i in range(k):
tempSet = []
cluster.append(tempSet)
#将每一个样本划入离其最近的簇中
cluster = spiltSample(aveVec,mellonData,cluster)
print("aveVec")
print(aveVec)
#取得新的均值变量
newAveVec = updateAve(aveVec,cluster)
print("newAveVec")
print(newAveVec)
drawPlot(cluster)
#判断均值变量是否更新,若更新了继续循环,否则退出循环
if isEqual(newAveVec,aveVec):
isUpdate = False
else:
isUpdate = False
#输出分类结果
for metaCluster in cluster:
print(mellonData)



聚类我看完了,里面有很多算法,挨个实现的时候写流程。
网友评论