内容:

        1.数据集:

        (1)人工生成数据集AriGen:自己生成含有3个类别的二维数据集,且类别间线性分开,分别具有100·200与300个样本;

        (2) Iris 数据集·

        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() # 显示

  结果示例:

 

推荐链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: