K均值(K-Means)是聚类算法中最为简单、高效的,属于无监督学习算法
大概目的要求就是用户指定K个中心,让若干数据点能成功分成K簇,采取的方法是每个点去找离自己最近的簇中心,再根据簇中元素重新定位簇中心,反复迭代直到算法收敛(即分类不再改变)
以上是调用sklearn实现kmeans
import random
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
def calcDis(dataSet, centroids, k):
clalist = []
for data in dataSet:
diff = np.tile(data, (k,
1)) - centroids
squaredDiff = diff ** 2 # 平方
squaredDist = np.sum(squaredDiff, axis=1) # 和 (axis=1表示行)
distance = squaredDist ** 0.5 # 开根号
clalist.append(distance)
clalist = np.array(clalist) # 返回一个每个点到质点的距离len(dateSet)*k的数组
return clalist
# 计算质心
def classify(dataSet, centroids, k):
# 计算样本到质心的距离
clalist = calcDis(dataSet, centroids, k)
# 分组并计算新的质心
minDistIndices = np.argmin(clalist, axis=1) # axis=1 表示求出每行的最小值的下标
newCentroids = pd.DataFrame(dataSet).groupby(
minDistIndices).mean() # DataFramte(dataSet)对DataSet分组,groupby(min)按照min进行统计分类,mean()对分类结果求均值
newCentroids = newCentroids.values
# 计算变化量
changed = newCentroids - centroids
return changed, newCentroids
# 使用k-means分类
def kmeans(dataSet, k):
# 随机取质心
centroids = random.sample(dataSet, k)
# 更新质心 直到变化量全为0
changed, newCentroids = classify(dataSet, centroids, k)
while np.any(changed != 0):
changed, newCentroids = classify(dataSet, newCentroids, k)
centroids = sorted(newCentroids.tolist()) # tolist()将矩阵转换成列表 sorted()排序
# 根据质心计算每个集群
cluster = []
clalist = calcDis(dataSet, centroids, k) # 调用欧拉距离
minDistIndices = np.argmin(clalist, axis=1)
for i in range(k):
cluster.append([])
for i, j in enumerate(minDistIndices): # enymerate()可同时遍历索引和遍历元素
cluster[j].append(dataSet[i])
return centroids, cluster
# 创建数据集
from scipy import *
import pylab as pl
np.random.seed(40)
array_size = (10, 2)
array = np.random.randint(0, 5, size=array_size)
pl.plot(array[:, 0], array[:, 1], 'b.')# 绘制出这些数据点,以点的形式
pl.show()
if __name__ == '__main__':
print(tuple(array))
print(createDataSet())
dataset = tuple(array)
centroids, cluster = kmeans(dataset, 2)
print('质心为:%s' % centroids)
print('集群为:%s' % cluster)
for i in range(len(dataset)):
plt.scatter(dataset[i][0], dataset[i][1], marker='o', color='green', s=40, label='原始点')
# 记号形状 颜色 点的大小 设置标签
for j in range(len(centroids)):
plt.scatter(centroids[j][0], centroids[j][1], marker='x', color='red', s=50, label='质心')
plt.show()
这是自己实现k-means