2.编写k-均值聚类算法程序,对人工生成数据集AriGen 与 Iris数据集进行聚类﹐并计算DB指数。 一、数据集(150)
具体数据如下(如果不能运行,尝试在末尾加回车)
5.1 3.5 1.4 0.2 1
4.9 3 1.4 0.2 1
4.7 3.2 1.3 0.2 1
4.6 3.1 1.5 0.2 1
5 3.6 1.4 0.2 1
5.4 3.9 1.7 0.4 1
4.6 3.4 1.4 0.3 1
5 3.4 1.5 0.2 1
4.4 2.9 1.4 0.2 1
4.9 3.1 1.5 0.1 1
5.4 3.7 1.5 0.2 1
4.8 3.4 1.6 0.2 1
4.8 3 1.4 0.1 1
4.3 3 1.1 0.1 1
5.8 4 1.2 0.2 1
5.7 4.4 1.5 0.4 1
5.4 3.9 1.3 0.4 1
5.1 3.5 1.4 0.3 1
5.7 3.8 1.7 0.3 1
5.1 3.8 1.5 0.3 1
5.4 3.4 1.7 0.2 1
5.1 3.7 1.5 0.4 1
4.6 3.6 1 0.2 1
5.1 3.3 1.7 0.5 1
4.8 3.4 1.9 0.2 1
5 3 1.6 0.2 1
5 3.4 1.6 0.4 1
5.2 3.5 1.5 0.2 1
5.2 3.4 1.4 0.2 1
4.7 3.2 1.6 0.2 1
4.8 3.1 1.6 0.2 1
5.4 3.4 1.5 0.4 1
5.2 4.1 1.5 0.1 1
5.5 4.2 1.4 0.2 1
4.9 3.1 1.5 0.1 1
5 3.2 1.2 0.2 1
5.5 3.5 1.3 0.2 1
4.9 3.1 1.5 0.1 1
4.4 3 1.3 0.2 1
5.1 3.4 1.5 0.2 1
5 3.5 1.3 0.3 1
4.5 2.3 1.3 0.3 1
4.4 3.2 1.3 0.2 1
5 3.5 1.6 0.6 1
5.1 3.8 1.9 0.4 1
4.8 3 1.4 0.3 1
5.1 3.8 1.6 0.2 1
4.6 3.2 1.4 0.2 1
5.3 3.7 1.5 0.2 1
5 3.3 1.4 0.2 1
7 3.2 4.7 1.4 2
6.4 3.2 4.5 1.5 2
6.9 3.1 4.9 1.5 2
5.5 2.3 4 1.3 2
6.5 2.8 4.6 1.5 2
5.7 2.8 4.5 1.3 2
6.3 3.3 4.7 1.6 2
4.9 2.4 3.3 1 2
6.6 2.9 4.6 1.3 2
5.2 2.7 3.9 1.4 2
5 2 3.5 1 2
5.9 3 4.2 1.5 2
6 2.2 4 1 2
6.1 2.9 4.7 1.4 2
5.6 2.9 3.6 1.3 2
6.7 3.1 4.4 1.4 2
5.6 3 4.5 1.5 2
5.8 2.7 4.1 1 2
6.2 2.2 4.5 1.5 2
5.6 2.5 3.9 1.1 2
5.9 3.2 4.8 1.8 2
6.1 2.8 4 1.3 2
6.3 2.5 4.9 1.5 2
6.1 2.8 4.7 1.2 2
6.4 2.9 4.3 1.3 2
6.6 3 4.4 1.4 2
6.8 2.8 4.8 1.4 2
6.7 3 5 1.7 2
6 2.9 4.5 1.5 2
5.7 2.6 3.5 1 2
5.5 2.4 3.8 1.1 2
5.5 2.4 3.7 1 2
5.8 2.7 3.9 1.2 2
6 2.7 5.1 1.6 2
5.4 3 4.5 1.5 2
6 3.4 4.5 1.6 2
6.7 3.1 4.7 1.5 2
6.3 2.3 4.4 1.3 2
5.6 3 4.1 1.3 2
5.5 2.5 4 1.3 2
5.5 2.6 4.4 1.2 2
6.1 3 4.6 1.4 2
5.8 2.6 4 1.2 2
5 2.3 3.3 1 2
5.6 2.7 4.2 1.3 2
5.7 3 4.2 1.2 2
5.7 2.9 4.2 1.3 2
6.2 2.9 4.3 1.3 2
5.1 2.5 3 1.1 2
5.7 2.8 4.1 1.3 2
6.3 3.3 6 2.5 3
5.8 2.7 5.1 1.9 3
7.1 3 5.9 2.1 3
6.3 2.9 5.6 1.8 3
6.5 3 5.8 2.2 3
7.6 3 6.6 2.1 3
4.9 2.5 4.5 1.7 3
7.3 2.9 6.3 1.8 3
6.7 2.5 5.8 1.8 3
7.2 3.6 6.1 2.5 3
6.5 3.2 5.1 2 3
6.4 2.7 5.3 1.9 3
6.8 3 5.5 2.1 3
5.7 2.5 5 2 3
5.8 2.8 5.1 2.4 3
6.4 3.2 5.3 2.3 3
6.5 3 5.5 1.8 3
7.7 3.8 6.7 2.2 3
7.7 2.6 6.9 2.3 3
6 2.2 5 1.5 3
6.9 3.2 5.7 2.3 3
5.6 2.8 4.9 2 3
7.7 2.8 6.7 2 3
6.3 2.7 4.9 1.8 3
6.7 3.3 5.7 2.1 3
7.2 3.2 6 1.8 3
6.2 2.8 4.8 1.8 3
6.1 3 4.9 1.8 3
6.4 2.8 5.6 2.1 3
7.2 3 5.8 1.6 3
7.4 2.8 6.1 1.9 3
7.9 3.8 6.4 2 3
6.4 2.8 5.6 2.2 3
6.3 2.8 5.1 1.5 3
6.1 2.6 5.6 1.4 3
7.7 3 6.1 2.3 3
6.3 3.4 5.6 2.4 3
6.4 3.1 5.5 1.8 3
6 3 4.8 1.8 3
6.9 3.1 5.4 2.1 3
6.7 3.1 5.6 2.4 3
6.9 3.1 5.1 2.3 3
5.8 2.7 5.1 1.9 3
6.8 3.2 5.9 2.3 3
6.7 3.3 5.7 2.5 3
6.7 3 5.2 2.3 3
6.3 2.5 5 1.9 3
6.5 3 5.2 2 3
6.2 3.4 5.4 2.3 3
5.9 3 5.1 1.8 3
二、代码:
(1)人工生成数据集AriGen:
import math # 数学
import random # 随机
import numpy as np
import matplotlib.pyplot as plt
# 计算两个样本距离
def dist(xy, a, b):
d_l = 0 # 储存当前距离值
for i in range(len(xy) - 1): # 对每个属性
d_l += (xy[i][a] - xy[i][b]) ** 2 # 计算平方和
d_l = d_l ** 0.5 # 开根号
return d_l
# 计算avg(C)
def avg(xy, Ci):
sum = 0
for i in Ci:
for j in Ci:
sum += dist(xy, i, j)
return sum * 2 / (len(Ci) * (len(Ci) - 1))
# 计算DB指数
def DB(xy, C, u):
sum = 0
for i in range(len(C)): # 每一簇
max_C = -float('inf')
for j in range(len(C)):
if i == j:
continue
dcen = 0
for k in range(len(xy) - 1): # 对每个属性
dcen += (u[i][k] - u[j][k]) ** 2 # 计算平方和
dcen = dcen ** 0.5 # 开根号
max_ = (avg(xy, C[i]) + avg(xy, C[j])) / dcen
if max_ > max_C:
max_C = max_
sum += max_C
return sum / len(C)
# k均值聚类算法,分k簇。
def jvlei_k(xy, k):
n = len(xy[0]) # 储存数据数。
u = [] # 储存簇的均值向量
C = [] # 储存簇划分
# 挑选k个不重复的样本。
i = 0
j = 0
u = random.sample(range(n), k) # (如果数据随机,这一步其实可以直接选前k个)
for i in range(k): # 对每个初始点。
l = u[i] # 暂存
u[i] = []
print('初始点', i, end='\t: ')
for j in range(len(xy) - 1): # 对每个属性
u[i].append(xy[j][l])
print(u[i], xy[j + 1][l])
while 1:
C = [] # 储存簇划分
for i in range(k): # k 簇
C.append([]) # 初始化C。
for i in range(n): # 所有的数据
d = float('inf') # 初始无穷大
l = 0 # 属于哪个簇
for j in range(k): # 看和每个簇的距离,找最小。
d_ = 0 # 储存当前距离值
for ii in range(len(xy) - 1): # 对每个属性
d_ += (xy[ii][i] - u[j][ii]) ** 2 # 计算平方和
d_ = d_ ** 0.5 # 开根号
if d_ < d: # 距离更近
d = d_ # 最近值更改
l = j # 属于第j簇
C[l].append(i) # 并入第l簇
u_ = [] # 新的均值向量
for i in range(k): # 重新计算每个簇的均值
u_.append([0] * (len(xy) - 1))
for j in C[i]: # 对簇中每个样本
for ii in range(len(xy) - 1): # 对每个属性
u_[i][ii] += xy[ii][j] # 求和
for ii in range(len(xy) - 1): # 对每个属性
u_[i][ii] /= len(C[i]) # 均值
l = 0 # 标记
for i in range(k): # 每个均值向量
for j in range(len(u[0])): # 每个属性
l += (u[i][j] - u_[i][j]) ** 2 # 求误差
if l < 0.01:
print('DB=', DB(xy, C, u))
return C
else:
u = u_[:]
# 簇分类和标签对比,返回【最多标签,最多标签所占比例】
def panduan(yi, Ci):
biaoqian = {} # 标签,出现次数
for i in Ci:
if yi[i] in biaoqian: # 存在
biaoqian[yi[i]] += 1 # 加一
else:
biaoqian[yi[i]] = 1 # 创建
max_ = -1 # 标签
max_t = -1 # 标签数
for i in biaoqian: # 所有标签
if biaoqian[i] > max_t: # 找最多的
max_ = i
max_t = biaoqian[i]
return [max_, (max_t * 100 / len(Ci))]
# 生成数据集=============================================
x = [] # 数据集x属性
y = [] # 数据集y属性
x.extend(np.random.normal(loc=040.0, scale=10, size=100)) # 向x中放100个均值为40,方差为10,正态分布的随机数
x.extend(np.random.normal(loc=060.0, scale=10, size=200)) # 向x中放200个均值为60,方差为10,正态分布的随机数
x.extend(np.random.normal(loc=100.0, scale=10, size=300)) # 向x中放300个均值为100,方差为10,正态分布的随机数
y.extend(np.random.normal(loc=050.0, scale=10, size=100)) # 向y中放100个均值为50,方差为10,正态分布的随机数
y.extend(np.random.normal(loc=100.0, scale=10, size=200)) # 向y中放200个均值为100,方差为10,正态分布的随机数
y.extend(np.random.normal(loc=040.0, scale=10, size=300)) # 向y中放300个均值为40,方差为10,正态分布的随机数
c = [1] * 100 # c标签第一类为 1 x均值:40 y均值:50
c.extend([2] * 200) # # c标签第二类为 2 x均值:60 y均值:100
c.extend([3] * 300) # # c标签第三类为 3 x均值:100 y均值:40
# 生成训练集与测试集=======================================
lt = list(range(600)) # 得到一个顺序序列
random.shuffle(lt) # 打乱序列
x1 = [[], [], []] # 初始化x1
for i in lt: # 做训练集
x1[0].append(x[i]) # 加上数据集x属性
x1[1].append(y[i]) # 加上数据集y属性
x1[2].append(c[i]) # 加上数据集c标签
# 生成簇划分 ==========================================
k = 3 # 分成三簇
C = jvlei_k(x1, k)
# 计算正确率===========================================
for i in range(k):
c = panduan(x1[2], C[i])
print('第', i, '簇,标签最多的类为', c[0], '占比', c[1], '%')
# 绘图 ===============================================
plt.figure(1) # 第一张画布
for i in range(len(x1[2])): # 对数据集‘上色’
if x1[2][i] == 1:
x1[2][i] = 'r' # 数据集 1 红色
else:
if x1[2][i] == 2:
x1[2][i] = 'y' # 数据集 2 黄色
else:
x1[2][i] = 'b' # 数据集 3 蓝色
plt.scatter(x1[0], x1[1], c=x1[2], alpha=0.5) # 绘点数据集
plt.xlabel('x') # x轴标签
plt.ylabel('y') # y轴标签
plt.title('Initial') # 标题
# 簇划分:==========================================
plt.figure(2) # 第二张画布
for i in range(k): # 对数据集‘上色’
for j in C[i]:
if i == 1:
x1[2][j] = 'r' # 簇 1 红色
else:
if i == 2:
x1[2][j] = 'y' # 簇 2 黄色
else:
x1[2][j] = 'b' # 簇 3 蓝色
plt.scatter(x1[0], x1[1], c=x1[2], alpha=0.5) # 绘点数据集
plt.xlabel('x') # x轴标签
plt.ylabel('y') # y轴标签
plt.title('End') # 标题
plt.show() # 显示
结果示例:
(2) Iris 数据集:
import math # 数学
import random # 随机
import numpy as np
import matplotlib.pyplot as plt
# 计算两个样本距离
def dist(xy, a, b):
d_l = 0 # 储存当前距离值
for i in range(len(xy) - 1): # 对每个属性
d_l += (xy[i][a] - xy[i][b]) ** 2 # 计算平方和
d_l = d_l ** 0.5 # 开根号
return d_l
# 计算avg(C)
def avg(xy, Ci):
sum = 0
for i in Ci:
for j in Ci:
sum += dist(xy, i, j)
return sum * 2 / (len(Ci) * (len(Ci) - 1))
# 计算DB指数
def DB(xy, C, u):
sum = 0
for i in range(len(C)): # 每一簇
max_C = -float('inf')
for j in range(len(C)):
if i == j:
continue
dcen = 0
for k in range(len(xy) - 1): # 对每个属性
dcen += (u[i][k] - u[j][k]) ** 2 # 计算平方和
dcen = dcen ** 0.5 # 开根号
max_ = (avg(xy, C[i]) + avg(xy, C[j])) / dcen
if max_ > max_C:
max_C = max_
sum += max_C
return sum / len(C)
# k均值聚类算法,分k簇。
def jvlei_k(xy, k):
n = len(xy[0]) # 储存数据数。
u = [] # 储存簇的均值向量
C = [] # 储存簇划分
# 挑选k个不重复的样本。
i = 0
j = 0
u = random.sample(range(n), k) # (如果数据随机,这一步其实可以直接选前k个)
for i in range(k): # 对每个初始点。
l = u[i] # 暂存
u[i] = []
print('初始点', i, end='\t: ')
for j in range(len(xy) - 1): # 对每个属性
u[i].append(xy[j][l])
print(u[i], xy[j + 1][l])
while 1:
C = [] # 储存簇划分
for i in range(k): # k 簇
C.append([]) # 初始化C。
for i in range(n): # 所有的数据
d = float('inf') # 初始无穷大
l = 0 # 属于哪个簇
for j in range(k): # 看和每个簇的距离,找最小。
d_ = 0 # 储存当前距离值
for ii in range(len(xy) - 1): # 对每个属性
d_ += (xy[ii][i] - u[j][ii]) ** 2 # 计算平方和
d_ = d_ ** 0.5 # 开根号
if d_ < d: # 距离更近
d = d_ # 最近值更改
l = j # 属于第j簇
C[l].append(i) # 并入第l簇
u_ = [] # 新的均值向量
for i in range(k): # 重新计算每个簇的均值
u_.append([0] * (len(xy) - 1))
for j in C[i]: # 对簇中每个样本
for ii in range(len(xy) - 1): # 对每个属性
u_[i][ii] += xy[ii][j] # 求和
for ii in range(len(xy) - 1): # 对每个属性
u_[i][ii] /= len(C[i]) # 均值
l = 0 # 标记
for i in range(k): # 每个均值向量
for j in range(len(u[0])): # 每个属性
l += (u[i][j] - u_[i][j]) ** 2 # 求误差
if l < 0.01:
print('DB=', DB(xy, C, u))
return C
else:
u = u_[:]
# 簇分类和标签对比,返回【最多标签,最多标签所占比例】
def panduan(yi, Ci):
biaoqian = {} # 标签,出现次数
for i in Ci:
if yi[i] in biaoqian: # 存在
biaoqian[yi[i]] += 1 # 加一
else:
biaoqian[yi[i]] = 1 # 创建
max_ = -1 # 标签
max_t = -1 # 标签数
for i in biaoqian: # 所有标签
if biaoqian[i] > max_t: # 找最多的
max_ = i
max_t = biaoqian[i]
return [max_, (max_t * 100 / len(Ci))]
f = open('Iris.txt', 'r') # 读文件
x = [[], [], [], [], []] # 花朵属性,(0,1,2,3),花朵种类
x1 = [[], [], [], [], []]
x2 = [[], [], [], [], []]
y = [] # 分支节点[分支类,[分支节点1],[分支节点2]···] 递归决策树
y1 = []
while 1:
yihang = f.readline() # 读一行
if len(yihang) <= 1: # 读到末尾结束
break
fenkai = yihang.split('\t') # 按\t分开
for i in range(5): # 分开的五个值
x[i].append(eval(fenkai[i])) # 化为数字加到x中
print('数据集===============================================')
print(len(x[0]))
for i in range(len(x)):
print(x[i])
x1 = x[:]
# 生成簇划分 ==========================================
k = 3 # 分成三簇
C = jvlei_k(x1, k)
# 计算正确率===========================================
for i in range(k):
c = panduan(x1[4], C[i])
print('第', i, '簇,标签最多的类为', c[0], '占比', c[1], '%')
# 绘图 ===============================================
# 这里改输出那三维,(有四维,选三维)
a = 0
b = 2
c = 3
for i in range(len(x1[4])): # 对数据集‘上色’
if x1[4][i] == 1:
x1[4][i] = 'r' # 数据集 1 红色
else:
if x1[4][i] == 2:
x1[4][i] = 'y' # 数据集 2 黄色
else:
x1[4][i] = 'b' # 数据集 3 蓝色
fig = plt.figure()
m = plt.axes(projection='3d')
m.scatter3D(x1[a], x1[b], x1[c], c=x1[4], alpha=0.8) # 绘制散点图
plt.xlabel(a) # x轴标签
plt.ylabel(b) # y轴标签
plt.title('Initial') # 标题
# 簇划分:==========================================
for i in range(k): # 对数据集‘上色’
for j in C[i]:
if i == 1:
x1[4][j] = 'r' # 簇 1 红色
else:
if i == 2:
x1[4][j] = 'y' # 簇 2 黄色
else:
x1[4][j] = 'b' # 簇 3 蓝色
fig = plt.figure()
m = plt.axes(projection='3d')
m.scatter3D(x1[a], x1[b], x1[c], c=x1[4], alpha=0.8) # 绘制散点图
plt.xlabel(a) # x轴标签
plt.ylabel(b) # y轴标签
plt.title('End') # 标题
plt.show() # 显示
结果示例:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)