python实现k_means聚类

K-Means算法是将一组N个样本的特征矩阵X划分为K个无交集的簇,直观上来看是簇是一组一组聚集在一起的数据,在一个簇中的数据就认为是同一类。簇就是聚类的结果表现。

簇中所有数据的均值通常被称为这个簇的“质心”(Centroids)。在一个二维平面中,一簇数据点的质心的横坐标就是这一簇数据点的横坐标的均值,质心的纵坐标就是这一簇数据点的纵坐标的均值。同理可推广至高维空间。

算法实现:

一、随机取n个点,即想要分类数目

二、将当前数据每个点都与取到的n个点进行作差,将差值最小的分为一类

三、将分好类的结果取出计算均值,取出每个类中和均值距离最小的值,将其做为新的中心点

四、重复上述步骤,直到最终分成的簇内结果不再发生变化(在当前的算法里,我们连续验证三次,即在三次内,结果不再发生变化,迭代就会停止)

#k均值计算

import numpy as np

import pandas as pd

import random

import math

def data():

rand_value = [random.randint(1,10000) for i in range(10000)]

# print(rand_value)

# rand_value = [63, 23, 93, 52, 33, 84, 34, 91, 52, 68, 64, 4, 3, 58, 37, 76, 75, 52, 49, 34, 91, 29, 67, 42, 97, 69, 99, 9, 15,

# 44, 12, 46, 86, 92, 10, 67, 46, 93, 49, 29, 93, 95, 60, 33, 30, 63, 24, 45, 26, 47, 12, 62, 50, 54, 13, 62, 40, 39,

# 32, 2, 92, 34, 20, 72, 68, 37, 88, 32, 84, 28, 88, 85, 5, 88, 56, 30, 5, 3, 43, 9, 13, 62, 44, 11, 90, 97, 80, 34,

# 12, 90, 56, 54, 87, 59, 20, 51, 58, 54, 29, 32]

return rand_value

#进行计算,并返回质心及详细信息

def k_mean(data_list,k,rand_choice):

# rand_choice = [random.choice(data_list) for i in range(k)]

temp_dict = {}

for i in range(len(data_list)):

temp_list = []

for j in range(len(rand_choice)):

#解决符号差异带来的影响

temp_list.append(abs(abs(data_list[i]) - abs(rand_choice[j])))

insert_index = temp_list.index(min(temp_list))

if temp_dict.get(rand_choice[insert_index]):

temp_dict[rand_choice[insert_index]].append(data_list[i])

else:

temp_dict[rand_choice[insert_index]] = [data_list[i]]

return temp_dict

#输出距离均值最近的点,返回新的质心及中心点

def min_distince(data_dict):

k_list = []

k_keys = list(data_dict.keys())

for j in range(len(k_keys)):

data_list = data_dict[k_keys[j]]

mean_value = sum(data_list)/len(data_list)

for i in range(len(data_list)):

if i == 0:

distance_value = abs(data_list[i] - mean_value)

s = 0

# distance_list.append(distance_value)

else:

if distance_value > abs(data_list[i] - mean_value):

s = i

distance_value = min(distance_value,abs(data_list[i] - mean_value))

k_list.append(data_list[s])

# distance_list.append(distance_value)

return k_list

def iteration(source_data,k):

iter_num = 0

end_list = []

if len(source_data) < k:

print('需要计算的数据量少于要分类的数据量,请检查数据源\n')

else:

while True:

iter_num += 1

print('迭代次数%d'%iter_num)

if iter_num == 1:

data_dict = k_mean(source_data,k,[random.choice(source_data) for i in range(k)])

end_list.append(data_dict)

# print(data_dict)

result = min_distince(data_dict)

# result = min_distince(k_mean(source_data,k,[random.choice(source_data) for i in range(k)]))

else:

data_dict = k_mean(source_data,k,result)

end_list.append(data_dict)

# print(data_dict)

result = min_distince(data_dict)

if len(end_list) == 4:

del end_list[0]

if end_list[0] == end_list[1] and end_list[1] == end_list[2]:

print(data_dict)

break

if __name__ == '__main__':

source_data = data()

iteration(source_data,5)

算法经过测试,目前常规运行没有问题,但是bug还是存在的,主要是对数据的筛选,即符合条件的数据。

一、要分类的数据数据量是否大于要分类的数目

二、要分类的数据去重后的数据量是否大于要分类的数目

这两个可能带来异常的场景,未做捕获,在代码里添加处理一下就可以了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值